You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by el...@apache.org on 2011/10/15 00:36:15 UTC
svn commit: r1183537 [4/11] - in /directory/apacheds/trunk/interceptors:
admin/ admin/.settings/ authn/ authn/.settings/ authz/.settings/ changelog/
changelog/src/ changelog/src/main/ changelog/src/main/java/
changelog/src/main/java/org/ changelog/src/...
Added: directory/apacheds/trunk/interceptors/logger/src/main/java/org/apache/directory/server/core/logger/TimerInterceptor.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/interceptors/logger/src/main/java/org/apache/directory/server/core/logger/TimerInterceptor.java?rev=1183537&view=auto
==============================================================================
--- directory/apacheds/trunk/interceptors/logger/src/main/java/org/apache/directory/server/core/logger/TimerInterceptor.java (added)
+++ directory/apacheds/trunk/interceptors/logger/src/main/java/org/apache/directory/server/core/logger/TimerInterceptor.java Fri Oct 14 22:36:08 2011
@@ -0,0 +1,571 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.directory.server.core.logger;
+
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.apache.directory.server.core.api.DirectoryService;
+import org.apache.directory.server.core.api.filtering.EntryFilteringCursor;
+import org.apache.directory.server.core.api.interceptor.Interceptor;
+import org.apache.directory.server.core.api.interceptor.NextInterceptor;
+import org.apache.directory.server.core.api.interceptor.context.AddOperationContext;
+import org.apache.directory.server.core.api.interceptor.context.BindOperationContext;
+import org.apache.directory.server.core.api.interceptor.context.CompareOperationContext;
+import org.apache.directory.server.core.api.interceptor.context.DeleteOperationContext;
+import org.apache.directory.server.core.api.interceptor.context.EntryOperationContext;
+import org.apache.directory.server.core.api.interceptor.context.GetRootDSEOperationContext;
+import org.apache.directory.server.core.api.interceptor.context.ListOperationContext;
+import org.apache.directory.server.core.api.interceptor.context.LookupOperationContext;
+import org.apache.directory.server.core.api.interceptor.context.ModifyOperationContext;
+import org.apache.directory.server.core.api.interceptor.context.MoveAndRenameOperationContext;
+import org.apache.directory.server.core.api.interceptor.context.MoveOperationContext;
+import org.apache.directory.server.core.api.interceptor.context.RenameOperationContext;
+import org.apache.directory.server.core.api.interceptor.context.SearchOperationContext;
+import org.apache.directory.server.core.api.interceptor.context.UnbindOperationContext;
+import org.apache.directory.shared.ldap.model.entry.Entry;
+import org.apache.directory.shared.ldap.model.exception.LdapException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * An interceptor used to log times to process each operation.
+ *
+ * The way it works is that it gathers the time to process an operation
+ * into a global counter, which is logged every 1000 operations (when
+ * using the OPERATION_STATS logger). It's also possible to get the time for
+ * each single operation if activating the OPERATION_TIME logger.
+ *
+ * Thos two loggers must be set to DEBUG.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class TimerInterceptor implements Interceptor
+{
+ /** A aggregating logger */
+ private static final Logger OPERATION_STATS = LoggerFactory.getLogger( "OPERATION_STATS" );
+
+ /** An operation logger */
+ private static final Logger OPERATION_TIME = LoggerFactory.getLogger( "OPERATION_TIME" );
+
+ /** Speedup for logs */
+ private static final boolean IS_DEBUG_STATS = OPERATION_STATS.isDebugEnabled();
+ private static final boolean IS_DEBUG_TIME = OPERATION_TIME.isDebugEnabled();
+
+ /** The Logger's name */
+ private String name;
+
+ /** Stats for the add operation */
+ private static AtomicLong totalAdd = new AtomicLong( 0 );
+ private static AtomicInteger nbAddCalls = new AtomicInteger( 0 );
+
+ /** Stats for the bind operation */
+ private static AtomicLong totalBind = new AtomicLong( 0 );
+ private static AtomicInteger nbBindCalls = new AtomicInteger( 0 );
+
+ /** Stats for the compare operation */
+ private static AtomicLong totalCompare = new AtomicLong( 0 );
+ private static AtomicInteger nbCompareCalls = new AtomicInteger( 0 );
+
+ /** Stats for the delete operation */
+ private static AtomicLong totalDelete = new AtomicLong( 0 );
+ private static AtomicInteger nbDeleteCalls = new AtomicInteger( 0 );
+
+ /** Stats for the GetRootDSE operation */
+ private static AtomicLong totalGetRootDSE = new AtomicLong( 0 );
+ private static AtomicInteger nbGetRootDSECalls = new AtomicInteger( 0 );
+
+ /** Stats for the HasEntry operation */
+ private static AtomicLong totalHasEntry = new AtomicLong( 0 );
+ private static AtomicInteger nbHasEntryCalls = new AtomicInteger( 0 );
+
+ /** Stats for the list operation */
+ private static AtomicLong totalList = new AtomicLong( 0 );
+ private static AtomicInteger nbListCalls = new AtomicInteger( 0 );
+
+ /** Stats for the lookup operation */
+ private static AtomicLong totalLookup = new AtomicLong( 0 );
+ private static AtomicInteger nbLookupCalls = new AtomicInteger( 0 );
+
+ /** Stats for the modify operation */
+ private static AtomicLong totalModify = new AtomicLong( 0 );
+ private static AtomicInteger nbModifyCalls = new AtomicInteger( 0 );
+
+ /** Stats for the move operation */
+ private static AtomicLong totalMove = new AtomicLong( 0 );
+ private static AtomicInteger nbMoveCalls = new AtomicInteger( 0 );
+
+ /** Stats for the moveAndRename operation */
+ private static AtomicLong totalMoveAndRename = new AtomicLong( 0 );
+ private static AtomicInteger nbMoveAndRenameCalls = new AtomicInteger( 0 );
+
+ /** Stats for the rename operation */
+ private static AtomicLong totalRename = new AtomicLong( 0 );
+ private static AtomicInteger nbRenameCalls = new AtomicInteger( 0 );
+
+ /** Stats for the search operation */
+ private static AtomicLong totalSearch = new AtomicLong( 0 );
+ private static AtomicInteger nbSearchCalls = new AtomicInteger( 0 );
+
+ /** Stats for the unbind operation */
+ private static AtomicLong totalUnbind = new AtomicLong( 0 );
+ private static AtomicInteger nbUnbindCalls = new AtomicInteger( 0 );
+
+ /**
+ *
+ * Creates a new instance of TimerInterceptor.
+ *
+ * @param name This interceptor's name
+ */
+ public TimerInterceptor( String name )
+ {
+ this.name = name;
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public void add( NextInterceptor next, AddOperationContext addContext ) throws LdapException
+ {
+ long t0 = System.nanoTime();
+ next.add( addContext );
+ long delta = System.nanoTime() - t0;
+
+ if ( IS_DEBUG_STATS )
+ {
+ nbAddCalls.incrementAndGet();
+ totalAdd.getAndAdd( delta );
+
+ if ( nbAddCalls.get() % 1000 == 0 )
+ {
+ long average = totalAdd.get()/(nbAddCalls.get() * 1000);
+ OPERATION_STATS.debug( name + " : Average add = {} microseconds, nb adds = {}", average, nbAddCalls.get() );
+ }
+ }
+
+ if ( IS_DEBUG_TIME )
+ {
+ OPERATION_TIME.debug( "{} : Delta add = {}", name, delta );
+ }
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public void bind( NextInterceptor next, BindOperationContext bindContext ) throws LdapException
+ {
+ long t0 = System.nanoTime();
+ next.bind( bindContext );
+ long delta = System.nanoTime() - t0;
+
+ if ( IS_DEBUG_STATS )
+ {
+ nbBindCalls.incrementAndGet();
+ totalBind.getAndAdd( delta );
+
+ if ( nbBindCalls.get() % 1000 == 0 )
+ {
+ long average = totalBind.get()/(nbBindCalls.get() * 1000);
+ OPERATION_STATS.debug( name + " : Average bind = {} microseconds, nb binds = {}", average, nbBindCalls.get() );
+ }
+ }
+
+ if ( IS_DEBUG_TIME )
+ {
+ OPERATION_TIME.debug( "{} : Delta bind = {}", name, delta );
+ }
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean compare( NextInterceptor next, CompareOperationContext compareContext ) throws LdapException
+ {
+ long t0 = System.nanoTime();
+ boolean compare = next.compare( compareContext );
+ long delta = System.nanoTime() - t0;
+
+ if ( IS_DEBUG_STATS )
+ {
+ nbCompareCalls.incrementAndGet();
+ totalCompare.getAndAdd( delta );
+
+ if ( nbCompareCalls.get() % 1000 == 0 )
+ {
+ long average = totalCompare.get()/(nbCompareCalls.get() * 1000);
+ OPERATION_STATS.debug( name + " : Average compare = {} microseconds, nb compares = {}", average, nbCompareCalls.get() );
+ }
+ }
+
+ if ( IS_DEBUG_TIME )
+ {
+ OPERATION_TIME.debug( "{} : Delta compare = {}", name, delta );
+ }
+
+ return compare;
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public void delete( NextInterceptor next, DeleteOperationContext deleteContext ) throws LdapException
+ {
+ long t0 = System.nanoTime();
+ next.delete( deleteContext );
+ long delta = System.nanoTime() - t0;
+
+ if ( IS_DEBUG_STATS )
+ {
+ nbDeleteCalls.incrementAndGet();
+ totalDelete.getAndAdd( delta );
+
+ if ( nbDeleteCalls.get() % 1000 == 0 )
+ {
+ long average = totalDelete.get()/(nbDeleteCalls.get() * 1000);
+ OPERATION_STATS.debug( name + " : Average delete = {} microseconds, nb deletes = {}", average, nbDeleteCalls.get() );
+ }
+ }
+
+ if ( IS_DEBUG_TIME )
+ {
+ OPERATION_TIME.debug( "{} : Delta delete = {}", name, delta );
+ }
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public void destroy()
+ {
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getName()
+ {
+ return name;
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public Entry getRootDSE( NextInterceptor next, GetRootDSEOperationContext getRootDseContext )
+ throws LdapException
+ {
+ long t0 = System.nanoTime();
+ Entry rootDSE = next.getRootDSE( getRootDseContext );
+ long delta = System.nanoTime() - t0;
+
+ if ( IS_DEBUG_STATS )
+ {
+ nbGetRootDSECalls.incrementAndGet();
+ totalGetRootDSE.getAndAdd( delta );
+
+ if ( nbGetRootDSECalls.get() % 1000 == 0 )
+ {
+ long average = totalGetRootDSE.get()/(nbGetRootDSECalls.get() * 1000);
+ OPERATION_STATS.debug( name + " : Average getRootDSE = {} microseconds, nb getRootDSEs = {}", average, nbGetRootDSECalls.get() );
+ }
+ }
+
+ if ( IS_DEBUG_TIME )
+ {
+ OPERATION_TIME.debug( "{} : Delta getRootDSE = {}", name, delta );
+ }
+
+ return rootDSE;
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean hasEntry( NextInterceptor next, EntryOperationContext hasEntryContext ) throws LdapException
+ {
+ long t0 = System.nanoTime();
+ boolean hasEntry = next.hasEntry( hasEntryContext );
+ long delta = System.nanoTime() - t0;
+
+ if ( IS_DEBUG_STATS )
+ {
+ nbHasEntryCalls.incrementAndGet();
+ totalHasEntry.getAndAdd( delta );
+
+ if ( nbHasEntryCalls.get() % 1000 == 0 )
+ {
+ long average = totalHasEntry.get()/(nbHasEntryCalls.get() * 1000);
+ OPERATION_STATS.debug( name + " : Average hasEntry = {} microseconds, nb hasEntrys = {}", average, nbHasEntryCalls.get() );
+ }
+ }
+
+ if ( IS_DEBUG_TIME )
+ {
+ OPERATION_TIME.debug( "{} : Delta hasEntry = {}", name, delta );
+ }
+
+ return hasEntry;
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public void init( DirectoryService directoryService ) throws LdapException
+ {
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public EntryFilteringCursor list( NextInterceptor next, ListOperationContext listContext ) throws LdapException
+ {
+ long t0 = System.nanoTime();
+ EntryFilteringCursor cursor = next.list( listContext );
+ long delta = System.nanoTime() - t0;
+
+ if ( IS_DEBUG_STATS )
+ {
+ nbListCalls.incrementAndGet();
+ totalList.getAndAdd( delta );
+
+ if ( nbListCalls.get() % 1000 == 0 )
+ {
+ long average = totalList.get()/(nbListCalls.get() * 1000);
+ OPERATION_STATS.debug( name + " : Average list = {} microseconds, nb lists = {}", average, nbListCalls.get() );
+ }
+ }
+
+ if ( IS_DEBUG_TIME )
+ {
+ OPERATION_TIME.debug( "{} : Delta list = {}", name, delta );
+ }
+
+ return cursor;
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public Entry lookup( NextInterceptor next, LookupOperationContext lookupContext ) throws LdapException
+ {
+ long t0 = System.nanoTime();
+ Entry entry = next.lookup( lookupContext );
+ long delta = System.nanoTime() - t0;
+
+ if ( IS_DEBUG_STATS )
+ {
+ nbLookupCalls.incrementAndGet();
+ totalLookup.getAndAdd( delta );
+
+ if ( nbLookupCalls.get() % 1000 == 0 )
+ {
+ long average = totalLookup.get()/(nbLookupCalls.get() * 1000);
+ OPERATION_STATS.debug( name + " : Average lookup = {} microseconds, nb lookups = {}", average, nbLookupCalls.get() );
+ }
+ }
+
+ if ( IS_DEBUG_TIME )
+ {
+ OPERATION_TIME.debug( "{} : Delta lookup = {}", name, delta );
+ }
+
+ return entry;
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public void modify( NextInterceptor next, ModifyOperationContext modifyContext ) throws LdapException
+ {
+ long t0 = System.nanoTime();
+ next.modify( modifyContext );
+ long delta = System.nanoTime() - t0;
+
+ if ( IS_DEBUG_STATS )
+ {
+ nbModifyCalls.incrementAndGet();
+ totalModify.getAndAdd( delta );
+
+ if ( nbModifyCalls.get() % 1000 == 0 )
+ {
+ long average = totalModify.get()/(nbModifyCalls.get() * 1000);
+ OPERATION_STATS.debug( name + " : Average modify = {} microseconds, nb modifys = {}", average, nbModifyCalls.get() );
+ }
+ }
+
+ if ( IS_DEBUG_TIME )
+ {
+ OPERATION_TIME.debug( "{} : Delta modify = {}", name, delta );
+ }
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public void move( NextInterceptor next, MoveOperationContext moveContext ) throws LdapException
+ {
+ long t0 = System.nanoTime();
+ next.move( moveContext );
+ long delta = System.nanoTime() - t0;
+
+ if ( IS_DEBUG_STATS )
+ {
+ nbMoveCalls.incrementAndGet();
+ totalMove.getAndAdd( delta );
+
+ if ( nbMoveCalls.get() % 1000 == 0 )
+ {
+ long average = totalMove.get()/(nbMoveCalls.get() * 1000);
+ OPERATION_STATS.debug( name + " : Average move = {} microseconds, nb moves = {}", average, nbMoveCalls.get() );
+ }
+ }
+
+ if ( IS_DEBUG_TIME )
+ {
+ OPERATION_TIME.debug( "{} : Delta move = {}", name, delta );
+ }
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public void moveAndRename( NextInterceptor next, MoveAndRenameOperationContext moveAndRenameContext ) throws LdapException
+ {
+ long t0 = System.nanoTime();
+ next.moveAndRename( moveAndRenameContext );
+ long delta = System.nanoTime() - t0;
+
+ if ( IS_DEBUG_STATS )
+ {
+ nbMoveAndRenameCalls.incrementAndGet();
+ totalMoveAndRename.getAndAdd( delta );
+
+ if ( nbMoveAndRenameCalls.get() % 1000 == 0 )
+ {
+ long average = totalMoveAndRename.get()/(nbMoveAndRenameCalls.get() * 1000);
+ OPERATION_STATS.debug( name + " : Average moveAndRename = {} microseconds, nb moveAndRenames = {}", average, nbMoveAndRenameCalls.get() );
+ }
+ }
+
+ if ( IS_DEBUG_TIME )
+ {
+ OPERATION_TIME.debug( "{} : Delta moveAndRename = {}", name, delta );
+ }
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public void rename( NextInterceptor next, RenameOperationContext renameContext ) throws LdapException
+ {
+ long t0 = System.nanoTime();
+ next.rename( renameContext );
+ long delta = System.nanoTime() - t0;
+
+ if ( IS_DEBUG_STATS )
+ {
+ nbRenameCalls.incrementAndGet();
+ totalRename.getAndAdd( delta );
+
+ if ( nbRenameCalls.get() % 1000 == 0 )
+ {
+ long average = totalRename.get()/(nbRenameCalls.get() * 1000);
+ OPERATION_STATS.debug( name + " : Average rename = {} microseconds, nb renames = {}", average, nbRenameCalls.get() );
+ }
+ }
+
+ if ( IS_DEBUG_TIME )
+ {
+ OPERATION_TIME.debug( "{} : Delta rename = {}", name, delta );
+ }
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public EntryFilteringCursor search( NextInterceptor next, SearchOperationContext searchContext ) throws LdapException
+ {
+ long t0 = System.nanoTime();
+ EntryFilteringCursor cursor = next.search( searchContext );
+ long delta = System.nanoTime() - t0;
+
+ if ( IS_DEBUG_STATS )
+ {
+ nbSearchCalls.incrementAndGet();
+ totalSearch.getAndAdd( delta );
+
+ if ( nbSearchCalls.get() % 1000 == 0 )
+ {
+ long average = totalSearch.get()/(nbSearchCalls.get() * 1000);
+ OPERATION_STATS.debug( name + " : Average search = {} microseconds, nb searches = {}", average, nbSearchCalls.get() );
+ }
+ }
+
+ if ( IS_DEBUG_TIME )
+ {
+ OPERATION_TIME.debug( "{} : Delta search = {}", name, delta );
+ }
+
+ return cursor;
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public void unbind( NextInterceptor next, UnbindOperationContext unbindContext ) throws LdapException
+ {
+ long t0 = System.nanoTime();
+ next.unbind( unbindContext );
+ long delta = System.nanoTime() - t0;
+
+ if ( IS_DEBUG_STATS )
+ {
+ nbUnbindCalls.incrementAndGet();
+ totalUnbind.getAndAdd( delta );
+
+ if ( nbUnbindCalls.get() % 1000 == 0 )
+ {
+ long average = totalUnbind.get()/(nbUnbindCalls.get() * 1000);
+ OPERATION_STATS.debug( name + " : Average unbind = {} microseconds, nb unbinds = {}", average, nbUnbindCalls.get() );
+ }
+ }
+
+ if ( IS_DEBUG_TIME )
+ {
+ OPERATION_TIME.debug( "{} : Delta unbind = {}", name, delta );
+ }
+ }
+}
Propchange: directory/apacheds/trunk/interceptors/normalization/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Fri Oct 14 22:36:08 2011
@@ -0,0 +1,11 @@
+target
+.project
+.classpath
+.settings
+eclipse-classes
+*.log
+*.iml
+*.ipr
+dependency-reduced-pom.xml
+META-INF
+
Added: directory/apacheds/trunk/interceptors/normalization/pom.xml
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/interceptors/normalization/pom.xml?rev=1183537&view=auto
==============================================================================
--- directory/apacheds/trunk/interceptors/normalization/pom.xml (added)
+++ directory/apacheds/trunk/interceptors/normalization/pom.xml Fri Oct 14 22:36:08 2011
@@ -0,0 +1,178 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.directory.server</groupId>
+ <artifactId>apacheds-interceptors</artifactId>
+ <version>2.0.0-M4-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>apacheds-interceptors-normalization</artifactId>
+ <name>ApacheDS Normalization Interceptor</name>
+ <packaging>jar</packaging>
+
+ <description>
+ Normalization interceptor
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.directory.junit</groupId>
+ <artifactId>junit-addons</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>apacheds-i18n</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>apacheds-core-api</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>apacheds-core-api</artifactId>
+ <classifier>tests</classifier>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>commons-collections</groupId>
+ <artifactId>commons-collections</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>commons-lang</groupId>
+ <artifactId>commons-lang</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.directory.shared</groupId>
+ <artifactId>shared-ldap-client-api</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.directory.shared</groupId>
+ <artifactId>shared-i18n</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.directory.shared</groupId>
+ <artifactId>shared-ldap-codec-standalone</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.directory.shared</groupId>
+ <artifactId>shared-ldap-codec-core</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.directory.shared</groupId>
+ <artifactId>shared-ldap-extras-aci</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.directory.shared</groupId>
+ <artifactId>shared-ldap-extras-trigger</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.directory.shared</groupId>
+ <artifactId>shared-ldap-extras-util</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.directory.shared</groupId>
+ <artifactId>shared-ldap-model</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.directory.shared</groupId>
+ <artifactId>shared-ldap-schema-data</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.directory.shared</groupId>
+ <artifactId>shared-util</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>bouncycastle</groupId>
+ <artifactId>bcprov-jdk15</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>net.sf.ehcache</groupId>
+ <artifactId>ehcache-core</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.directory.shared</groupId>
+ <artifactId>shared-ldap-extras-codec</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <systemPropertyVariables>
+ <workingDirectory>${basedir}/target/server-work</workingDirectory>
+ </systemPropertyVariables>
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-source-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>attach-sources</id>
+ <phase>verify</phase>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+
+ <resources>
+ <resource>
+ <directory>src/main/resources</directory>
+ <filtering>true</filtering>
+ <excludes>
+ <exclude>**/*.gif</exclude>
+ </excludes>
+ </resource>
+ </resources>
+ </build>
+</project>
+
Added: directory/apacheds/trunk/interceptors/normalization/src/main/java/org/apache/directory/server/core/normalization/ExpandingVisitor.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/interceptors/normalization/src/main/java/org/apache/directory/server/core/normalization/ExpandingVisitor.java?rev=1183537&view=auto
==============================================================================
--- directory/apacheds/trunk/interceptors/normalization/src/main/java/org/apache/directory/server/core/normalization/ExpandingVisitor.java (added)
+++ directory/apacheds/trunk/interceptors/normalization/src/main/java/org/apache/directory/server/core/normalization/ExpandingVisitor.java Fri Oct 14 22:36:08 2011
@@ -0,0 +1,185 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.directory.server.core.normalization;
+
+
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.directory.server.i18n.I18n;
+import org.apache.directory.shared.ldap.model.exception.LdapException;
+import org.apache.directory.shared.ldap.model.filter.ApproximateNode;
+import org.apache.directory.shared.ldap.model.filter.BranchNode;
+import org.apache.directory.shared.ldap.model.filter.EqualityNode;
+import org.apache.directory.shared.ldap.model.filter.ExprNode;
+import org.apache.directory.shared.ldap.model.filter.ExtensibleNode;
+import org.apache.directory.shared.ldap.model.filter.FilterVisitor;
+import org.apache.directory.shared.ldap.model.filter.GreaterEqNode;
+import org.apache.directory.shared.ldap.model.filter.LeafNode;
+import org.apache.directory.shared.ldap.model.filter.LessEqNode;
+import org.apache.directory.shared.ldap.model.filter.OrNode;
+import org.apache.directory.shared.ldap.model.filter.PresenceNode;
+import org.apache.directory.shared.ldap.model.filter.SubstringNode;
+import org.apache.directory.shared.ldap.model.schema.AttributeType;
+import org.apache.directory.shared.ldap.model.schema.SchemaManager;
+
+
+/**
+ *
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class ExpandingVisitor implements FilterVisitor
+{
+ /** The schemaManager */
+ private SchemaManager schemaManager;
+
+
+ /**
+ *
+ * Creates a new instance of ExpandingVisitor.
+ *
+ * @param schemaManager The server schemaManager
+ */
+ public ExpandingVisitor( SchemaManager schemaManager )
+ {
+ this.schemaManager = schemaManager;
+ }
+
+
+ public boolean canVisit( ExprNode node )
+ {
+ return node instanceof BranchNode;
+ }
+
+
+ public List<ExprNode> getOrder( BranchNode node, List<ExprNode> children )
+ {
+ return children;
+ }
+
+
+ public boolean isPrefix()
+ {
+ return false;
+ }
+
+
+ public Object visit( ExprNode node )
+ {
+ BranchNode bnode = ( BranchNode ) node;
+
+ // --------------------------------------------------------------------
+ // we want to check each child leaf node to see if it must be expanded
+ // children that are branch nodes are recursively visited
+ // --------------------------------------------------------------------
+
+ final List<ExprNode> children = bnode.getChildren();
+ int childNumber = 0;
+
+ for ( ExprNode child : children )
+ {
+ if ( child instanceof LeafNode )
+ {
+ LeafNode leaf = ( LeafNode ) child;
+
+ try
+ {
+ if ( schemaManager.getAttributeTypeRegistry().hasDescendants( leaf.getAttributeType() ) )
+ {
+ // create a new OR node to hold all descendent forms
+ // add to this node the generalized leaf node and
+ // replace the old leaf with the new OR branch node
+ BranchNode orNode = new OrNode();
+ orNode.getChildren().add( leaf );
+ children.set( childNumber++, orNode );
+
+ // iterate through descendants adding them to the orNode
+ Iterator<AttributeType> descendants = schemaManager.getAttributeTypeRegistry().descendants( leaf.getAttributeType() );
+
+ while ( descendants.hasNext() )
+ {
+ LeafNode newLeaf = null;
+ AttributeType descendant = descendants.next();
+
+ if ( leaf instanceof PresenceNode )
+ {
+ newLeaf = new PresenceNode( descendant );
+ }
+ else if ( leaf instanceof ApproximateNode )
+ {
+ ApproximateNode approximateNode = ( ApproximateNode ) leaf;
+
+ newLeaf = new ApproximateNode( descendant, approximateNode.getValue() );
+ }
+ else if ( leaf instanceof EqualityNode )
+ {
+ EqualityNode equalityNode = (EqualityNode) leaf;
+
+ newLeaf = new EqualityNode( descendant, equalityNode.getValue() );
+ }
+ else if ( leaf instanceof GreaterEqNode )
+ {
+ GreaterEqNode greaterEqNode = ( GreaterEqNode ) leaf;
+
+ newLeaf = new GreaterEqNode( descendant, greaterEqNode.getValue() );
+ }
+ else if ( leaf instanceof LessEqNode )
+ {
+ LessEqNode lessEqNode = ( LessEqNode ) leaf;
+
+ newLeaf = new LessEqNode( descendant, lessEqNode.getValue() );
+ }
+ else if ( leaf instanceof ExtensibleNode )
+ {
+ ExtensibleNode extensibleNode = ( ExtensibleNode ) leaf;
+ newLeaf = new ExtensibleNode( descendant, extensibleNode.getValue(),
+ extensibleNode.getMatchingRuleId(), extensibleNode.hasDnAttributes() );
+ }
+ else if ( leaf instanceof SubstringNode )
+ {
+ SubstringNode substringNode = ( SubstringNode ) leaf;
+ newLeaf = new SubstringNode( descendant, substringNode.getInitial(),
+ substringNode.getFinal() );
+ }
+ else
+ {
+ throw new IllegalStateException( I18n.err( I18n.ERR_260, leaf ) );
+ }
+
+ orNode.addNode( newLeaf );
+ }
+ }
+ }
+ catch ( LdapException e )
+ {
+ // log something here and throw a runtime excpetion
+ throw new RuntimeException( I18n.err( I18n.ERR_261 ) );
+ }
+ }
+ else
+ {
+ visit( child );
+ }
+ } // end for loop
+
+ return null;
+ }
+}
Added: directory/apacheds/trunk/interceptors/normalization/src/main/java/org/apache/directory/server/core/normalization/FilterNormalizingVisitor.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/interceptors/normalization/src/main/java/org/apache/directory/server/core/normalization/FilterNormalizingVisitor.java?rev=1183537&view=auto
==============================================================================
--- directory/apacheds/trunk/interceptors/normalization/src/main/java/org/apache/directory/server/core/normalization/FilterNormalizingVisitor.java (added)
+++ directory/apacheds/trunk/interceptors/normalization/src/main/java/org/apache/directory/server/core/normalization/FilterNormalizingVisitor.java Fri Oct 14 22:36:08 2011
@@ -0,0 +1,511 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.directory.server.core.normalization;
+
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.directory.shared.ldap.model.entry.StringValue;
+import org.apache.directory.shared.ldap.model.entry.Value;
+import org.apache.directory.shared.ldap.model.exception.LdapException;
+import org.apache.directory.shared.ldap.model.filter.AndNode;
+import org.apache.directory.shared.ldap.model.filter.BranchNode;
+import org.apache.directory.shared.ldap.model.filter.ExprNode;
+import org.apache.directory.shared.ldap.model.filter.ExtensibleNode;
+import org.apache.directory.shared.ldap.model.filter.FilterVisitor;
+import org.apache.directory.shared.ldap.model.filter.LeafNode;
+import org.apache.directory.shared.ldap.model.filter.NotNode;
+import org.apache.directory.shared.ldap.model.filter.PresenceNode;
+import org.apache.directory.shared.ldap.model.filter.SimpleNode;
+import org.apache.directory.shared.ldap.model.filter.SubstringNode;
+import org.apache.directory.shared.ldap.model.schema.AttributeType;
+import org.apache.directory.shared.ldap.model.schema.SchemaManager;
+import org.apache.directory.shared.ldap.model.schema.normalizers.NameComponentNormalizer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * A filter visitor which normalizes leaf node values as it visits them. It also removes
+ * leaf nodes from branches whose attributeType is undefined. It obviously cannot remove
+ * a leaf node from a filter which is only a leaf node. Checks to see if a filter is a
+ * leaf node with undefined attributeTypes should be done outside this visitor.
+ *
+ * Since this visitor may remove filter nodes it may produce negative results on filters,
+ * like NOT branch nodes without a child or AND and OR nodes with one or less children. This
+ * might make some partition implementations choke. To avoid this problem we clean up branch
+ * nodes that don't make sense. For example all BranchNodes without children are just
+ * removed. An AND and OR BranchNode with a single child is replaced with it's child for
+ * all but the topmost branch node which we cannot replace. So again the top most branch
+ * node must be inspected by code outside of this visitor.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class FilterNormalizingVisitor implements FilterVisitor
+{
+ /** logger used by this class */
+ private static final Logger log = LoggerFactory.getLogger( FilterNormalizingVisitor.class );
+
+ /** the name component normalizer used by this visitor */
+ private final NameComponentNormalizer ncn;
+
+ /** the SchemaManager instance used to resolve OIDs for attributeType ids */
+ private final SchemaManager schemaManager;
+
+ /**
+ * Chars which need to be escaped in a filter
+ * '\0' | '(' | ')' | '*' | '\'
+ */
+ private static final boolean[] FILTER_CHAR =
+ { true, false, false, false, false, false, false, false, // 00 -> 07 NULL
+ false, false, false, false, false, false, false, false, // 08 -> 0F
+ false, false, false, false, false, false, false, false, // 10 -> 17
+ false, false, false, false, false, false, false, false, // 18 -> 1F
+ false, false, false, false, false, false, false, false, // 20 -> 27
+ true, true, true, false, false, false, false, false, // 28 -> 2F '(', ')', '*'
+ false, false, false, false, false, false, false, false, // 30 -> 37
+ false, false, false, false, false, false, false, false, // 38 -> 3F
+ false, false, false, false, false, false, false, false, // 40 -> 47
+ false, false, false, false, false, false, false, false, // 48 -> 4F
+ false, false, false, false, false, false, false, false, // 50 -> 57
+ false, false, false, false, true, false, false, false, // 58 -> 5F '\'
+ false, false, false, false, false, false, false, false, // 60 -> 67
+ false, false, false, false, false, false, false, false, // 68 -> 6F
+ false, false, false, false, false, false, false, false, // 70 -> 77
+ false, false, false, false, false, false, false, false // 78 -> 7F
+ };
+
+
+ /**
+ * Check if the given char is a filter escaped char
+ * <filterEscapedChars> ::= '\0' | '(' | ')' | '*' | '\'
+ *
+ * @param c the char we want to test
+ * @return true if the char is a pair char only
+ */
+ public static boolean isFilterChar( char c )
+ {
+ return ( ( ( c | 0x7F ) == 0x7F ) && FILTER_CHAR[c & 0x7f] );
+ }
+
+
+ /**
+ *
+ * Creates a new instance of NormalizingVisitor.
+ *
+ * @param ncn The name component normalizer to use
+ * @param schemaManager The schemaManager
+ */
+ public FilterNormalizingVisitor( NameComponentNormalizer ncn, SchemaManager schemaManager )
+ {
+ this.ncn = ncn;
+ this.schemaManager = schemaManager;
+ }
+
+
+ /**
+ * A private method used to normalize a value. At this point, the value
+ * is a Value<byte[]>, we have to translate it to a Value<String> if its
+ * AttributeType is H-R. Then we have to normalize the value accordingly
+ * to the AttributeType Normalizer.
+ *
+ * @param attribute The attribute's ID
+ * @param value The value to normalize
+ * @return the normalized value
+ */
+ private Value<?> normalizeValue( AttributeType attributeType, Value<?> value )
+ {
+ try
+ {
+ Value<?> normalized = null;
+
+ if ( attributeType.getSyntax().isHumanReadable() )
+ {
+ normalized = new StringValue( ( String ) ncn.normalizeByName( attributeType.getOid(), value.getString() ) );
+ }
+ else
+ {
+ normalized = ( Value<?> ) ncn.normalizeByName( attributeType.getOid(), value.getBytes() );
+ }
+
+ return normalized;
+ }
+ catch ( LdapException ne )
+ {
+ log.warn( "Failed to normalize filter value: {}", ne.getLocalizedMessage(), ne );
+ return null;
+ }
+ }
+
+
+ /**
+ * Visit a PresenceNode. If the attribute exists, the node is returned, otherwise
+ * null is returned.
+ *
+ * @param node the node to visit
+ * @return The visited node
+ */
+ private ExprNode visitPresenceNode( PresenceNode node ) throws LdapException
+ {
+ // still need this check here in case the top level is a leaf node
+ // with an undefined attributeType for its attribute
+ if ( !ncn.isDefined( node.getAttribute() ) )
+ {
+ return null;
+ }
+
+ node.setAttributeType( schemaManager.lookupAttributeTypeRegistry( node.getAttribute() ) );
+
+ return node;
+ }
+
+
+ /**
+ * Visit a SimpleNode. If the attribute exists, the node is returned, otherwise
+ * null is returned. SimpleNodes are :
+ * - ApproximateNode
+ * - EqualityNode
+ * - GreaterEqNode
+ * - LesserEqNode
+ *
+ * @param node the node to visit
+ * @return the visited node
+ */
+ private ExprNode visitSimpleNode( SimpleNode node ) throws LdapException
+ {
+ if ( node.getAttributeType() == null )
+ {
+ // still need this check here in case the top level is a leaf node
+ // with an undefined attributeType for its attribute
+ if ( !ncn.isDefined( node.getAttribute() ) )
+ {
+ return null;
+ }
+
+ node.setAttributeType( schemaManager.lookupAttributeTypeRegistry( node.getAttribute() ) );
+ }
+
+ Value<?> normalized = normalizeValue( node.getAttributeType(), node.getValue() );
+
+ if ( normalized == null )
+ {
+ return null;
+ }
+
+ node.setValue( normalized );
+
+ return node;
+ }
+
+
+ /**
+ * Visit a SubstringNode. If the attribute exists, the node is returned, otherwise
+ * null is returned.
+ *
+ * Normalizing substring value is pretty complex. It's not currently implemented...
+ *
+ * @param node the node to visit
+ * @return the visited node
+ */
+ private ExprNode visitSubstringNode( SubstringNode node ) throws LdapException
+ {
+ // still need this check here in case the top level is a leaf node
+ // with an undefined attributeType for its attribute
+ if ( !ncn.isDefined( node.getAttribute() ) )
+ {
+ return null;
+ }
+
+ node.setAttributeType( schemaManager.lookupAttributeTypeRegistry( node.getAttribute() ) );
+
+ Value<?> normInitial = null;
+
+ if ( node.getInitial() != null )
+ {
+ normInitial = normalizeValue( node.getAttributeType(), new StringValue( node.getInitial() ) );
+
+ if ( normInitial == null )
+ {
+ return null;
+ }
+ }
+
+ List<String> normAnys = null;
+
+ if ( ( node.getAny() != null ) && ( node.getAny().size() != 0 ) )
+ {
+ normAnys = new ArrayList<String>( node.getAny().size() );
+
+ for ( String any : node.getAny() )
+ {
+ Value<?> normAny = normalizeValue( node.getAttributeType(), new StringValue( any ) );
+
+ if ( normAny != null )
+ {
+ normAnys.add( normAny.getString() );
+ }
+ }
+
+ if ( normAnys.size() == 0 )
+ {
+ return null;
+ }
+ }
+
+ Value<?> normFinal = null;
+
+ if ( node.getFinal() != null )
+ {
+ normFinal = normalizeValue( node.getAttributeType(), new StringValue( node.getFinal() ) );
+
+ if ( normFinal == null )
+ {
+ return null;
+ }
+ }
+
+ if ( normInitial != null )
+ {
+ node.setInitial( normInitial.getString() );
+ }
+ else
+ {
+ node.setInitial( null );
+ }
+
+ node.setAny( normAnys );
+
+ if ( normFinal != null )
+ {
+ node.setFinal( normFinal.getString() );
+ }
+ else
+ {
+ node.setFinal( null );
+ }
+
+ return node;
+ }
+
+
+ /**
+ * Visit a ExtensibleNode. If the attribute exists, the node is returned, otherwise
+ * null is returned.
+ *
+ * TODO implement the logic for ExtensibleNode
+ *
+ * @param node the node to visit
+ * @return the visited node
+ */
+ private ExprNode visitExtensibleNode( ExtensibleNode node ) throws LdapException
+ {
+ // still need this check here in case the top level is a leaf node
+ // with an undefined attributeType for its attribute
+ if ( !ncn.isDefined( node.getAttribute() ) )
+ {
+ return null;
+ }
+
+ node.setAttributeType( schemaManager.lookupAttributeTypeRegistry( node.getAttribute() ) );
+
+ return node;
+ }
+
+
+ /**
+ * Visit a BranchNode. BranchNodes are :
+ * - AndNode
+ * - NotNode
+ * - OrNode
+ *
+ * @param node the node to visit
+ * @return the visited node
+ */
+ private ExprNode visitBranchNode( BranchNode node )
+ {
+ // Two differente cases :
+ // - AND or OR
+ // - NOT
+
+ if ( node instanceof NotNode )
+ {
+ // Manage the NOT
+ ExprNode child = node.getFirstChild();
+
+ ExprNode result = ( ExprNode ) visit( child );
+
+ if ( result == null )
+ {
+ return null;
+ }
+ else if ( result instanceof BranchNode )
+ {
+ List<ExprNode> newChildren = new ArrayList<ExprNode>( 1 );
+ newChildren.add( result );
+ node.setChildren( newChildren );
+ return node;
+ }
+ else if ( result instanceof LeafNode)
+ {
+ List<ExprNode> newChildren = new ArrayList<ExprNode>( 1 );
+ newChildren.add( result );
+ node.setChildren( newChildren );
+ return node;
+ }
+ }
+ else
+ {
+ // Manage AND and OR nodes.
+ BranchNode branchNode = node;
+ List<ExprNode> children = node.getChildren();
+
+ // For AND and OR, we may have more than one children.
+ // We may have to remove some of them, so let's create
+ // a new handler to store the correct nodes.
+ List<ExprNode> newChildren = new ArrayList<ExprNode>( children.size() );
+
+ // Now, iterate through all the children
+ for ( int i = 0; i < children.size(); i++ )
+ {
+ ExprNode child = children.get( i );
+
+ ExprNode result = ( ExprNode ) visit( child );
+
+ if ( result != null )
+ {
+ // As the node is correct, add it to the children
+ // list.
+ newChildren.add( result );
+ }
+ }
+
+ if ( ( branchNode instanceof AndNode ) && ( newChildren.size() != children.size() ) )
+ {
+ return null;
+ }
+
+ if ( newChildren.size() == 0 )
+ {
+ // No more children, return null
+ return null;
+ }
+ else if ( newChildren.size() == 1 )
+ {
+ // As we only have one child, return it
+ // to the caller.
+ return newChildren.get( 0 );
+ }
+ else
+ {
+ branchNode.setChildren( newChildren );
+ }
+ }
+
+ return node;
+ }
+
+
+ /**
+ * Visit the tree, normalizing the leaves and recusrsively visit the branches.
+ *
+ * Here are the leaves we are visiting :
+ * - PresenceNode ( attr =* )
+ * - ExtensibleNode ( ? )
+ * - SubStringNode ( attr = *X*Y* )
+ * - ApproximateNode ( attr ~= value )
+ * - EqualityNode ( attr = value )
+ * - GreaterEqNode ( attr >= value )
+ * - LessEqNode ( attr <= value )
+ *
+ * The PresencNode is managed differently from other nodes, as it just check
+ * for the attribute, not the value.
+ *
+ * @param node the node to visit
+ * @return the visited node
+ */
+ public Object visit( ExprNode node )
+ {
+ try
+ {
+ // -------------------------------------------------------------------
+ // Handle PresenceNodes
+ // -------------------------------------------------------------------
+
+ if ( node instanceof PresenceNode )
+ {
+ return visitPresenceNode( ( PresenceNode ) node );
+ }
+
+ // -------------------------------------------------------------------
+ // Handle BranchNodes (AndNode, NotNode and OrNode)
+ // -------------------------------------------------------------------
+
+ else if ( node instanceof BranchNode )
+ {
+ return visitBranchNode( ( BranchNode ) node );
+ }
+
+ // -------------------------------------------------------------------
+ // Handle SimpleNodes (ApproximateNode, EqualityNode, GreaterEqNode,
+ // and LesserEqNode)
+ // -------------------------------------------------------------------
+
+ else if ( node instanceof SimpleNode )
+ {
+ return visitSimpleNode( ( SimpleNode ) node );
+ }
+ else if ( node instanceof ExtensibleNode )
+ {
+ return visitExtensibleNode( ( ExtensibleNode ) node );
+ }
+ else if ( node instanceof SubstringNode )
+ {
+ return visitSubstringNode( ( SubstringNode ) node );
+ }
+ else
+ {
+ return null;
+ }
+ }
+ catch ( LdapException e )
+ {
+ throw new RuntimeException( e );
+ }
+ }
+
+
+ public boolean canVisit( ExprNode node )
+ {
+ return true;
+ }
+
+
+ public boolean isPrefix()
+ {
+ return false;
+ }
+
+
+ public List<ExprNode> getOrder( BranchNode node, List<ExprNode> children )
+ {
+ return children;
+ }
+}
Added: directory/apacheds/trunk/interceptors/normalization/src/main/java/org/apache/directory/server/core/normalization/NormalizationInterceptor.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/interceptors/normalization/src/main/java/org/apache/directory/server/core/normalization/NormalizationInterceptor.java?rev=1183537&view=auto
==============================================================================
--- directory/apacheds/trunk/interceptors/normalization/src/main/java/org/apache/directory/server/core/normalization/NormalizationInterceptor.java (added)
+++ directory/apacheds/trunk/interceptors/normalization/src/main/java/org/apache/directory/server/core/normalization/NormalizationInterceptor.java Fri Oct 14 22:36:08 2011
@@ -0,0 +1,449 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.directory.server.core.normalization;
+
+
+import java.util.List;
+
+import org.apache.directory.server.core.api.DirectoryService;
+import org.apache.directory.server.core.api.filtering.BaseEntryFilteringCursor;
+import org.apache.directory.server.core.api.filtering.EntryFilteringCursor;
+import org.apache.directory.server.core.api.interceptor.BaseInterceptor;
+import org.apache.directory.server.core.api.interceptor.NextInterceptor;
+import org.apache.directory.server.core.api.interceptor.context.AddOperationContext;
+import org.apache.directory.server.core.api.interceptor.context.BindOperationContext;
+import org.apache.directory.server.core.api.interceptor.context.CompareOperationContext;
+import org.apache.directory.server.core.api.interceptor.context.DeleteOperationContext;
+import org.apache.directory.server.core.api.interceptor.context.EntryOperationContext;
+import org.apache.directory.server.core.api.interceptor.context.ListOperationContext;
+import org.apache.directory.server.core.api.interceptor.context.LookupOperationContext;
+import org.apache.directory.server.core.api.interceptor.context.ModifyOperationContext;
+import org.apache.directory.server.core.api.interceptor.context.MoveAndRenameOperationContext;
+import org.apache.directory.server.core.api.interceptor.context.MoveOperationContext;
+import org.apache.directory.server.core.api.interceptor.context.RenameOperationContext;
+import org.apache.directory.server.core.api.interceptor.context.SearchOperationContext;
+import org.apache.directory.server.i18n.I18n;
+import org.apache.directory.shared.ldap.model.cursor.EmptyCursor;
+import org.apache.directory.shared.ldap.model.entry.Entry;
+import org.apache.directory.shared.ldap.model.entry.Modification;
+import org.apache.directory.shared.ldap.model.entry.StringValue;
+import org.apache.directory.shared.ldap.model.entry.Value;
+import org.apache.directory.shared.ldap.model.exception.LdapException;
+import org.apache.directory.shared.ldap.model.exception.LdapInvalidAttributeTypeException;
+import org.apache.directory.shared.ldap.model.filter.ExprNode;
+import org.apache.directory.shared.ldap.model.name.Ava;
+import org.apache.directory.shared.ldap.model.name.Dn;
+import org.apache.directory.shared.ldap.model.name.Rdn;
+import org.apache.directory.shared.ldap.model.schema.AttributeType;
+import org.apache.directory.shared.ldap.model.schema.normalizers.ConcreteNameComponentNormalizer;
+import org.apache.directory.shared.ldap.model.schema.normalizers.NameComponentNormalizer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * A name normalization service. This service makes sure all relative and distinguished
+ * names are normalized before calls are made against the respective interface methods
+ * on {@link DefaultPartitionNexus}.
+ *
+ * The Filters are also normalized.
+ *
+ * If the Rdn AttributeTypes are not present in the entry for an Add request,
+ * they will be added.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class NormalizationInterceptor extends BaseInterceptor
+{
+ /** logger used by this class */
+ private static final Logger LOG = LoggerFactory.getLogger( NormalizationInterceptor.class );
+
+ /** a filter node value normalizer and undefined node remover */
+ private FilterNormalizingVisitor normVisitor;
+
+ /**
+ * Initialize the registries, normalizers.
+ */
+ public void init( DirectoryService directoryService ) throws LdapException
+ {
+ LOG.debug( "Initialiazing the NormalizationInterceptor" );
+
+ super.init( directoryService );
+
+ NameComponentNormalizer ncn = new ConcreteNameComponentNormalizer( schemaManager );
+ normVisitor = new FilterNormalizingVisitor( ncn, schemaManager );
+ }
+
+
+ /**
+ * The destroy method does nothing
+ */
+ public void destroy()
+ {
+ }
+
+
+ // ------------------------------------------------------------------------
+ // Normalize all Name based arguments for ContextPartition interface operations
+ // ------------------------------------------------------------------------
+ /**
+ * {@inheritDoc}
+ */
+ public void add( NextInterceptor nextInterceptor, AddOperationContext addContext ) throws LdapException
+ {
+ addContext.getDn().apply( schemaManager );
+ addContext.getEntry().getDn().apply( schemaManager );
+ addRdnAttributesToEntry( addContext.getDn(), addContext.getEntry() );
+ nextInterceptor.add( addContext );
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public void delete( NextInterceptor nextInterceptor, DeleteOperationContext deleteContext ) throws LdapException
+ {
+ Dn dn = deleteContext.getDn();
+
+ if ( !dn.isSchemaAware() )
+ {
+ dn.apply( schemaManager );
+ }
+
+ nextInterceptor.delete( deleteContext );
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public void modify( NextInterceptor nextInterceptor, ModifyOperationContext modifyContext ) throws LdapException
+ {
+ if ( !modifyContext.getDn().isSchemaAware() )
+ {
+ modifyContext.getDn().apply( schemaManager );
+ }
+
+ if ( modifyContext.getModItems() != null )
+ {
+ for ( Modification modification : modifyContext.getModItems() )
+ {
+ AttributeType attributeType = schemaManager.getAttributeType( modification.getAttribute().getId() );
+ modification.apply( attributeType );
+ }
+ }
+
+ nextInterceptor.modify( modifyContext );
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public void rename( NextInterceptor nextInterceptor, RenameOperationContext renameContext ) throws LdapException
+ {
+ // Normalize the new Rdn and the Dn if needed
+
+ if ( !renameContext.getDn().isSchemaAware() )
+ {
+ renameContext.getDn().apply( schemaManager );
+ }
+
+ renameContext.getNewRdn().apply( schemaManager );
+
+ if ( !renameContext.getNewDn().isSchemaAware() )
+ {
+ renameContext.getNewDn().apply( schemaManager );
+ }
+
+ // Push to the next interceptor
+ nextInterceptor.rename( renameContext );
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public void move( NextInterceptor nextInterceptor, MoveOperationContext moveContext ) throws LdapException
+ {
+ if ( !moveContext.getDn().isSchemaAware() )
+ {
+ moveContext.getDn().apply( schemaManager );
+ }
+
+ if ( !moveContext.getOldSuperior().isSchemaAware() )
+ {
+ moveContext.getOldSuperior().apply( schemaManager );
+ }
+
+ if ( !moveContext.getNewSuperior().isSchemaAware() )
+ {
+ moveContext.getNewSuperior().apply( schemaManager );
+ }
+
+ if ( !moveContext.getNewDn().isSchemaAware() )
+ {
+ moveContext.getNewDn().apply( schemaManager );
+ }
+
+ if ( !moveContext.getRdn().isSchemaAware() )
+ {
+ moveContext.getRdn().apply( schemaManager );
+ }
+
+ nextInterceptor.move( moveContext );
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public void moveAndRename( NextInterceptor nextInterceptor, MoveAndRenameOperationContext moveAndRenameContext )
+ throws LdapException
+ {
+
+ if ( !moveAndRenameContext.getNewRdn().isSchemaAware() )
+ {
+ moveAndRenameContext.getNewRdn().apply( schemaManager );
+ }
+
+ if ( !moveAndRenameContext.getDn().isSchemaAware() )
+ {
+ moveAndRenameContext.getDn().apply( schemaManager );
+ }
+
+ if ( !moveAndRenameContext.getNewDn().isSchemaAware() )
+ {
+ moveAndRenameContext.getNewDn().apply( schemaManager );
+ }
+
+ if ( !moveAndRenameContext.getNewSuperiorDn().isSchemaAware() )
+ {
+ moveAndRenameContext.getNewSuperiorDn().apply( schemaManager );
+ }
+
+ nextInterceptor.moveAndRename( moveAndRenameContext );
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public EntryFilteringCursor search( NextInterceptor nextInterceptor, SearchOperationContext searchContext )
+ throws LdapException
+ {
+ Dn dn = searchContext.getDn();
+
+ if ( !dn.isSchemaAware() )
+ {
+ dn.apply( schemaManager );
+ }
+
+ ExprNode filter = searchContext.getFilter();
+
+ if ( filter == null )
+ {
+ LOG.warn( "undefined filter based on undefined attributeType not evaluted at all. Returning empty enumeration." );
+ return new BaseEntryFilteringCursor( new EmptyCursor<Entry>(), searchContext );
+ }
+
+ // Normalize the filter
+ filter = ( ExprNode ) filter.accept( normVisitor );
+
+ if ( filter == null )
+ {
+ LOG.warn( "undefined filter based on undefined attributeType not evaluted at all. Returning empty enumeration." );
+ return new BaseEntryFilteringCursor( new EmptyCursor<Entry>(), searchContext );
+ }
+ else
+ {
+ searchContext.setFilter( filter );
+
+ // TODO Normalize the returned Attributes, storing the UP attributes to format the returned values.
+ return nextInterceptor.search( searchContext );
+ }
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean hasEntry( NextInterceptor nextInterceptor, EntryOperationContext hasEntryContext ) throws LdapException
+ {
+ hasEntryContext.getDn().apply( schemaManager );
+ return nextInterceptor.hasEntry( hasEntryContext );
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public EntryFilteringCursor list( NextInterceptor nextInterceptor, ListOperationContext listContext )
+ throws LdapException
+ {
+ listContext.getDn().apply( schemaManager );
+ return nextInterceptor.list( listContext );
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ private String[] normalizeAttrsId( String[] attrIds ) throws LdapException
+ {
+ if ( attrIds == null )
+ {
+ return attrIds;
+ }
+
+ String[] normalizedAttrIds = new String[attrIds.length];
+ int pos = 0;
+
+ for ( String id : attrIds )
+ {
+ String oid = schemaManager.lookupAttributeTypeRegistry( id ).getOid();
+ normalizedAttrIds[pos++] = oid;
+ }
+
+ return normalizedAttrIds;
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public Entry lookup( NextInterceptor nextInterceptor, LookupOperationContext lookupContext ) throws LdapException
+ {
+ lookupContext.getDn().apply( schemaManager );
+
+ List<String> attrIds = lookupContext.getAttrsId();
+
+ if ( ( attrIds != null ) && ( attrIds.size() > 0 ) )
+ {
+ // We have to normalize the requested IDs
+ lookupContext.setAttrsId( normalizeAttrsId( lookupContext.getAttrsIdArray() ) );
+ }
+
+ return nextInterceptor.lookup( lookupContext );
+ }
+
+
+ // ------------------------------------------------------------------------
+ // Normalize all Name based arguments for other interface operations
+ // ------------------------------------------------------------------------
+ /**
+ * {@inheritDoc}
+ */
+ public boolean compare( NextInterceptor next, CompareOperationContext compareContext ) throws LdapException
+ {
+ if ( !compareContext.getDn().isSchemaAware() )
+ {
+ compareContext.getDn().apply( schemaManager );
+ }
+
+ // Get the attributeType from the OID
+ try
+ {
+ AttributeType attributeType = schemaManager.lookupAttributeTypeRegistry( compareContext.getOid() );
+
+ // Translate the value from binary to String if the AT is HR
+ if ( attributeType.getSyntax().isHumanReadable() && ( !compareContext.getValue().isHumanReadable() ) )
+ {
+ String value = compareContext.getValue().getString();
+ compareContext.setValue( new StringValue( value ) );
+ }
+
+ compareContext.setAttributeType( attributeType );
+ }
+ catch ( LdapException le )
+ {
+ throw new LdapInvalidAttributeTypeException( I18n.err( I18n.ERR_266, compareContext.getOid() ) );
+ }
+
+ return next.compare( compareContext );
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public void bind( NextInterceptor next, BindOperationContext bindContext ) throws LdapException
+ {
+ bindContext.getDn().apply( schemaManager );
+ next.bind( bindContext );
+ }
+
+
+ /**
+ * Adds missing Rdn's attributes and values to the entry.
+ *
+ * @param dn the Dn
+ * @param entry the entry
+ */
+ private void addRdnAttributesToEntry( Dn dn, Entry entry ) throws LdapException
+ {
+ if ( dn == null || entry == null )
+ {
+ return;
+ }
+
+ Rdn rdn = dn.getRdn();
+
+ // Loop on all the AVAs
+ for ( Ava ava : rdn )
+ {
+ Value<?> value = ava.getNormValue();
+ Value<?> upValue = ava.getUpValue();
+ String upId = ava.getUpType();
+
+ // Check that the entry contains this Ava
+ if ( !entry.contains( upId, value ) )
+ {
+ String message = "The Rdn '" + upId + "=" + upValue + "' is not present in the entry";
+ LOG.warn( message );
+
+ // We don't have this attribute : add it.
+ // Two cases :
+ // 1) The attribute does not exist
+ if ( !entry.containsAttribute( upId ) )
+ {
+ entry.add( upId, value );
+ }
+ // 2) The attribute exists
+ else
+ {
+ AttributeType at = schemaManager.lookupAttributeTypeRegistry( upId );
+
+ // 2.1 if the attribute is single valued, replace the value
+ if ( at.isSingleValued() )
+ {
+ entry.removeAttributes( upId );
+ entry.add( upId, value );
+ }
+ // 2.2 the attribute is multi-valued : add the missing value
+ else
+ {
+ entry.add( upId, value );
+ }
+ }
+ }
+ }
+ }
+}
Added: directory/apacheds/trunk/interceptors/normalization/src/main/java/org/apache/directory/server/core/normalization/UndefinedFilterAttributeException.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/interceptors/normalization/src/main/java/org/apache/directory/server/core/normalization/UndefinedFilterAttributeException.java?rev=1183537&view=auto
==============================================================================
--- directory/apacheds/trunk/interceptors/normalization/src/main/java/org/apache/directory/server/core/normalization/UndefinedFilterAttributeException.java (added)
+++ directory/apacheds/trunk/interceptors/normalization/src/main/java/org/apache/directory/server/core/normalization/UndefinedFilterAttributeException.java Fri Oct 14 22:36:08 2011
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.directory.server.core.normalization;
+
+import org.apache.directory.shared.ldap.model.filter.LeafNode;
+
+
+/**
+ * A runtime exception thrown by visitors to denote the failure
+ * to recognize attributes in a filter expression tree.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class UndefinedFilterAttributeException extends RuntimeException
+{
+ private static final long serialVersionUID = -8073762118319523479L;
+ private final LeafNode node;
+
+
+ public UndefinedFilterAttributeException( LeafNode node )
+ {
+ super();
+ this.node = node;
+ }
+
+
+ public UndefinedFilterAttributeException( LeafNode node, String message )
+ {
+ super( message );
+ this.node = node;
+ }
+
+
+ public UndefinedFilterAttributeException( LeafNode node, String message, Throwable cause )
+ {
+ super( message, cause );
+ this.node = node;
+ }
+
+
+ public UndefinedFilterAttributeException( LeafNode node, Throwable cause )
+ {
+ super( cause );
+ this.node = node;
+ }
+
+
+ public LeafNode getUndefinedFilterNode()
+ {
+ return node;
+ }
+}
Added: directory/apacheds/trunk/interceptors/normalization/src/test/java/org/apache/directory/server/core/normalization/NormalizationVisitorTest.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/interceptors/normalization/src/test/java/org/apache/directory/server/core/normalization/NormalizationVisitorTest.java?rev=1183537&view=auto
==============================================================================
--- directory/apacheds/trunk/interceptors/normalization/src/test/java/org/apache/directory/server/core/normalization/NormalizationVisitorTest.java (added)
+++ directory/apacheds/trunk/interceptors/normalization/src/test/java/org/apache/directory/server/core/normalization/NormalizationVisitorTest.java Fri Oct 14 22:36:08 2011
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.directory.server.core.normalization;
+
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.text.ParseException;
+
+import org.apache.directory.shared.ldap.model.filter.EqualityNode;
+import org.apache.directory.shared.ldap.model.filter.ExprNode;
+import org.apache.directory.shared.ldap.model.filter.FilterParser;
+import org.apache.directory.shared.ldap.model.filter.NotNode;
+import org.apache.directory.shared.ldap.model.filter.PresenceNode;
+import org.apache.directory.shared.ldap.model.schema.SchemaManager;
+import org.apache.directory.shared.ldap.model.schema.normalizers.ConcreteNameComponentNormalizer;
+import org.apache.directory.shared.ldap.model.schema.normalizers.NameComponentNormalizer;
+import org.apache.directory.shared.ldap.schemaloader.JarLdifSchemaLoader;
+import org.apache.directory.shared.ldap.schemamanager.impl.DefaultSchemaManager;
+import org.apache.directory.shared.util.exception.Exceptions;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import com.mycila.junit.concurrent.Concurrency;
+import com.mycila.junit.concurrent.ConcurrentJunitRunner;
+
+
+/**
+ * A class to test the normalizing Visitor
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ *
+ */
+@RunWith(ConcurrentJunitRunner.class)
+@Concurrency()
+public class NormalizationVisitorTest
+{
+ /** a filter node value normalizer and undefined node remover */
+ private static FilterNormalizingVisitor normVisitor;
+
+ /** A reference to the schemaManager */
+ private static SchemaManager schemaManager;
+
+
+ @BeforeClass
+ public static void init() throws Exception
+ {
+ JarLdifSchemaLoader loader = new JarLdifSchemaLoader();
+
+ schemaManager = new DefaultSchemaManager( loader );
+
+ boolean loaded = schemaManager.loadAllEnabled();
+
+ if ( !loaded )
+ {
+ fail( "Schema load failed : " + Exceptions.printErrors(schemaManager.getErrors()) );
+ }
+
+ NameComponentNormalizer ncn = new ConcreteNameComponentNormalizer( schemaManager );
+ normVisitor = new FilterNormalizingVisitor( ncn, schemaManager );
+ }
+
+
+ @Test
+ public void testSimpleFilter() throws ParseException
+ {
+ ExprNode filter = FilterParser.parse( schemaManager, "(ou= test 1 )" );
+ ExprNode result = (ExprNode) filter.accept( normVisitor );
+
+ assertNotNull( result );
+ assertTrue( result instanceof EqualityNode<?>);
+ EqualityNode<?> equalityNode = ( EqualityNode<?> ) result;
+
+ assertEquals( "test 1", equalityNode.getValue().getNormValue() );
+ assertEquals( "2.5.4.11", equalityNode.getAttributeType().getOid() );
+ }
+
+
+ @Test
+ public void testPresenceFilter() throws ParseException
+ {
+ ExprNode filter = FilterParser.parse( schemaManager, "(ou=*)" );
+ ExprNode result = ( ExprNode ) filter.accept( normVisitor );
+
+ assertNotNull( result );
+ assertTrue( result instanceof PresenceNode);
+ PresenceNode presenceNode = ( PresenceNode ) result;
+
+ assertEquals( "2.5.4.11", presenceNode.getAttributeType().getOid() );
+ }
+
+
+ @Test
+ public void testBranchNormalizedVisitor() throws Exception
+ {
+ ExprNode filter = FilterParser.parse( schemaManager,
+ "(!(|(uniqueMember=cn=user1,ou=Test,dc=example,dc=com)(member=cn=user2,ou=Test,dc=example,dc=com)))" );
+ ExprNode result = ( ExprNode ) filter.accept( normVisitor );
+
+ assertNotNull( result );
+ assertTrue( result instanceof NotNode );
+ }
+
+}
Propchange: directory/apacheds/trunk/interceptors/operational/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Fri Oct 14 22:36:08 2011
@@ -0,0 +1,11 @@
+target
+.project
+.classpath
+.settings
+eclipse-classes
+*.log
+*.iml
+*.ipr
+dependency-reduced-pom.xml
+META-INF
+
Added: directory/apacheds/trunk/interceptors/operational/pom.xml
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/interceptors/operational/pom.xml?rev=1183537&view=auto
==============================================================================
--- directory/apacheds/trunk/interceptors/operational/pom.xml (added)
+++ directory/apacheds/trunk/interceptors/operational/pom.xml Fri Oct 14 22:36:08 2011
@@ -0,0 +1,178 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.directory.server</groupId>
+ <artifactId>apacheds-interceptors</artifactId>
+ <version>2.0.0-M4-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>apacheds-interceptors-operational</artifactId>
+ <name>ApacheDS Operational Attribute Interceptor</name>
+ <packaging>jar</packaging>
+
+ <description>
+ Operational Attribute interceptor
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.directory.junit</groupId>
+ <artifactId>junit-addons</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>apacheds-i18n</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>apacheds-core-api</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>apacheds-core-api</artifactId>
+ <classifier>tests</classifier>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>commons-collections</groupId>
+ <artifactId>commons-collections</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>commons-lang</groupId>
+ <artifactId>commons-lang</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.directory.shared</groupId>
+ <artifactId>shared-ldap-client-api</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.directory.shared</groupId>
+ <artifactId>shared-i18n</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.directory.shared</groupId>
+ <artifactId>shared-ldap-codec-standalone</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.directory.shared</groupId>
+ <artifactId>shared-ldap-codec-core</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.directory.shared</groupId>
+ <artifactId>shared-ldap-extras-aci</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.directory.shared</groupId>
+ <artifactId>shared-ldap-extras-trigger</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.directory.shared</groupId>
+ <artifactId>shared-ldap-extras-util</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.directory.shared</groupId>
+ <artifactId>shared-ldap-model</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.directory.shared</groupId>
+ <artifactId>shared-ldap-schema-data</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.directory.shared</groupId>
+ <artifactId>shared-util</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>bouncycastle</groupId>
+ <artifactId>bcprov-jdk15</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>net.sf.ehcache</groupId>
+ <artifactId>ehcache-core</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.directory.shared</groupId>
+ <artifactId>shared-ldap-extras-codec</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <systemPropertyVariables>
+ <workingDirectory>${basedir}/target/server-work</workingDirectory>
+ </systemPropertyVariables>
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-source-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>attach-sources</id>
+ <phase>verify</phase>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+
+ <resources>
+ <resource>
+ <directory>src/main/resources</directory>
+ <filtering>true</filtering>
+ <excludes>
+ <exclude>**/*.gif</exclude>
+ </excludes>
+ </resource>
+ </resources>
+ </build>
+</project>
+