You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by ak...@apache.org on 2005/10/25 06:20:35 UTC
svn commit: r328253 - in /directory/apacheds/trunk:
core/src/main/java/org/apache/ldap/server/normalization/
main/src/test/org/apache/ldap/server/
Author: akarasulu
Date: Mon Oct 24 21:20:27 2005
New Revision: 328253
URL: http://svn.apache.org/viewcvs?rev=328253&view=rev
Log:
changes ...
VNV = ValueNormalizationVisitor
NS = NormalizationService
o made the VNV prune away bogus leaves that contain undefined attributes
instead of throwing an exception - even branches may now be pruned if
they are left bare or with a single node in case of AND/OR branches
o cleaned up NS considerably
- parser need not be synchronized anymore since the parse method is
synchronized
- removed unnecesary constructs in inner class when I added the attribute
type registry as a member to the NS class
- doco for members
- logger added
o added code in search() method of NS to check if the pruned filter makes sense
if not it is altered. i.e. if it is a leaf node and undefined an
EmptyEnumeration is returned and likewise if the filter is a branch node
without children. If the filter is an AND or OR node and has one child
the child is returned instead of the filter node.
o added test cases which failed before the changes and pass now with changes
Modified:
directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/normalization/NormalizationService.java
directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/normalization/ValueNormalizingVisitor.java
directory/apacheds/trunk/main/src/test/org/apache/ldap/server/MiscTest.java
Modified: directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/normalization/NormalizationService.java
URL: http://svn.apache.org/viewcvs/directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/normalization/NormalizationService.java?rev=328253&r1=328252&r2=328253&view=diff
==============================================================================
--- directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/normalization/NormalizationService.java (original)
+++ directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/normalization/NormalizationService.java Mon Oct 24 21:20:27 2005
@@ -27,15 +27,20 @@
import javax.naming.directory.SearchControls;
import org.apache.ldap.common.filter.ExprNode;
+import org.apache.ldap.common.filter.LeafNode;
+import org.apache.ldap.common.filter.BranchNode;
import org.apache.ldap.common.name.DnParser;
import org.apache.ldap.common.name.NameComponentNormalizer;
import org.apache.ldap.common.schema.AttributeType;
+import org.apache.ldap.common.util.EmptyEnumeration;
import org.apache.ldap.server.DirectoryServiceConfiguration;
import org.apache.ldap.server.configuration.InterceptorConfiguration;
import org.apache.ldap.server.interceptor.BaseInterceptor;
import org.apache.ldap.server.interceptor.NextInterceptor;
import org.apache.ldap.server.partition.DirectoryPartitionNexus;
import org.apache.ldap.server.schema.AttributeTypeRegistry;
+import org.slf4j.LoggerFactory;
+import org.slf4j.Logger;
/**
@@ -48,22 +53,27 @@
*/
public class NormalizationService extends BaseInterceptor
{
+ /** logger used by this class */
+ private static final Logger log = LoggerFactory.getLogger( NormalizationService.class );
+
+ /** the parser used for normalizing distinguished names */
private DnParser parser;
+ /** a filter node value normalizer and undefined node remover */
private ValueNormalizingVisitor visitor;
+ /** the attributeType registry used for normalization and determining if some filter nodes are undefined */
+ private AttributeTypeRegistry registry;
public void init( DirectoryServiceConfiguration factoryCfg, InterceptorConfiguration cfg ) throws NamingException
{
- AttributeTypeRegistry attributeRegistry = factoryCfg.getGlobalRegistries().getAttributeTypeRegistry();
- NameComponentNormalizer ncn = new PerComponentNormalizer( attributeRegistry );
+ registry = factoryCfg.getGlobalRegistries().getAttributeTypeRegistry();
+ NameComponentNormalizer ncn = new PerComponentNormalizer();
parser = new DnParser( ncn );
visitor = new ValueNormalizingVisitor( ncn );
}
- public void destroy()
- {
- }
+ public void destroy() {}
// ------------------------------------------------------------------------
@@ -73,149 +83,130 @@
public void add( NextInterceptor nextInterceptor, String upName, Name normName, Attributes attrs ) throws NamingException
{
- synchronized( parser )
- {
- normName = parser.parse( normName.toString() );
- }
-
+ normName = parser.parse( normName.toString() );
nextInterceptor.add( upName, normName, attrs );
}
public void delete( NextInterceptor nextInterceptor, Name name ) throws NamingException
{
- synchronized( parser )
- {
- name = parser.parse( name.toString() );
- }
-
+ name = parser.parse( name.toString() );
nextInterceptor.delete( name );
}
public void modify( NextInterceptor nextInterceptor, Name name, int modOp, Attributes attrs ) throws NamingException
{
- synchronized( parser )
- {
- name = parser.parse( name.toString() );
- }
-
+ name = parser.parse( name.toString() );
nextInterceptor.modify( name, modOp, attrs );
}
public void modify( NextInterceptor nextInterceptor, Name name, ModificationItem[] items ) throws NamingException
{
- synchronized( parser )
- {
- name = parser.parse( name.toString() );
- }
-
+ name = parser.parse( name.toString() );
nextInterceptor.modify( name, items );
}
public void modifyRn( NextInterceptor nextInterceptor, Name name, String newRn, boolean deleteOldRn ) throws NamingException
{
- synchronized( parser )
- {
- name = parser.parse( name.toString() );
- }
-
+ name = parser.parse( name.toString() );
nextInterceptor.modifyRn( name, newRn, deleteOldRn );
}
public void move( NextInterceptor nextInterceptor, Name name, Name newParentName ) throws NamingException
{
- synchronized( parser )
- {
- name = parser.parse( name.toString() );
- newParentName = parser.parse( newParentName.toString() );
- }
-
+ name = parser.parse( name.toString() );
+ newParentName = parser.parse( newParentName.toString() );
nextInterceptor.move( name, newParentName );
}
public void move( NextInterceptor nextInterceptor, Name name, Name newParentName, String newRn, boolean deleteOldRn ) throws NamingException
{
- synchronized( parser )
- {
- name = parser.parse( name.toString() );
-
- newParentName = parser.parse( newParentName.toString() );
- }
-
+ name = parser.parse( name.toString() );
+ newParentName = parser.parse( newParentName.toString() );
nextInterceptor.move( name, newParentName, newRn, deleteOldRn );
}
public NamingEnumeration search( NextInterceptor nextInterceptor,
- Name base, Map env, ExprNode filter,
- SearchControls searchCtls ) throws NamingException
+ Name base, Map env, ExprNode filter,
+ SearchControls searchCtls ) throws NamingException
{
- synchronized( parser )
+ base = parser.parse( base.toString() );
+
+ if ( filter.isLeaf() )
{
- base = parser.parse( base.toString() );
+ LeafNode ln = ( LeafNode ) filter;
+ if ( ! registry.hasAttributeType( ln.getAttribute() ) )
+ {
+ StringBuffer buf = new StringBuffer();
+ buf.append( "undefined filter based on undefined attributeType '" );
+ buf.append( ln.getAttribute() );
+ buf.append( "' not evaluted at all. Returning empty enumeration." );
+ log.warn( buf.toString() );
+ return new EmptyEnumeration();
+ }
}
filter.accept( visitor );
+
+ // check that after pruning we have valid branch node at the top
+ if ( ! filter.isLeaf() )
+ {
+ BranchNode child = ( BranchNode ) filter;
+
+ // if the remaining filter branch node has no children return an empty enumeration
+ if ( child.getChildren().size() == 0 )
+ {
+ log.warn( "Undefined branchnode filter without child nodes not evaluted at all. Returning empty enumeration." );
+ return new EmptyEnumeration();
+ }
+
+ // now for AND & OR nodes with a single child left replace them with their child
+ if ( child.getChildren().size() == 1 && child.getOperator() != BranchNode.NOT )
+ {
+ filter = child.getChild();
+ }
+ }
return nextInterceptor.search( base, env, filter, searchCtls );
}
public boolean hasEntry( NextInterceptor nextInterceptor, Name name ) throws NamingException
{
- synchronized( parser )
- {
- name = parser.parse( name.toString() );
- }
-
+ name = parser.parse( name.toString() );
return nextInterceptor.hasEntry( name );
}
public boolean isSuffix( NextInterceptor nextInterceptor, Name name ) throws NamingException
{
- synchronized( parser )
- {
- name = parser.parse( name.toString() );
- }
-
+ name = parser.parse( name.toString() );
return nextInterceptor.isSuffix( name );
}
public NamingEnumeration list( NextInterceptor nextInterceptor, Name base ) throws NamingException
{
- synchronized( parser )
- {
- base = parser.parse( base.toString() );
- }
-
+ base = parser.parse( base.toString() );
return nextInterceptor.list( base );
}
public Attributes lookup( NextInterceptor nextInterceptor, Name name ) throws NamingException
{
- synchronized( parser )
- {
- name = parser.parse( name.toString() );
- }
-
+ name = parser.parse( name.toString() );
return nextInterceptor.lookup( name );
}
public Attributes lookup( NextInterceptor nextInterceptor, Name name, String[] attrIds ) throws NamingException
{
- synchronized( parser )
- {
- name = parser.parse( name.toString() );
- }
-
+ name = parser.parse( name.toString() );
return nextInterceptor.lookup( name, attrIds );
}
@@ -227,36 +218,22 @@
public Name getMatchedName( NextInterceptor nextInterceptor, Name name, boolean normalized ) throws NamingException
{
- synchronized( parser )
- {
- name = parser.parse( name.toString() );
- }
-
+ name = parser.parse( name.toString() );
return nextInterceptor.getMatchedName( name, normalized );
}
public Name getSuffix( NextInterceptor nextInterceptor, Name name, boolean normalized ) throws NamingException
{
- synchronized( parser )
- {
- name = parser.parse( name.toString() );
- }
-
+ name = parser.parse( name.toString() );
return nextInterceptor.getSuffix( name, normalized );
}
public boolean compare( NextInterceptor next, Name name, String oid, Object value ) throws NamingException
{
- Name normalized;
-
- synchronized( parser )
- {
- normalized = parser.parse( name.toString() );
- }
-
- return next.compare( normalized, oid, value );
+ name = parser.parse( name.toString() );
+ return next.compare( name, oid, value );
}
@@ -266,22 +243,6 @@
*/
private class PerComponentNormalizer implements NameComponentNormalizer
{
- /** the attribute type registry we use to lookup component normalizers */
- private final AttributeTypeRegistry registry;
-
-
- /**
- * Creates a name component normalizer that looks up normalizers using
- * an AttributeTypeRegistry.
- *
- * @param registry the attribute type registry to get normalizers
- */
- public PerComponentNormalizer( AttributeTypeRegistry registry )
- {
- this.registry = registry;
- }
-
-
public String normalizeByName( String name, String value ) throws NamingException
{
AttributeType type = registry.lookup( name );
@@ -298,7 +259,7 @@
public boolean isDefined( String id )
{
- return this.registry.hasAttributeType( id );
+ return registry.hasAttributeType( id );
}
}
}
Modified: directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/normalization/ValueNormalizingVisitor.java
URL: http://svn.apache.org/viewcvs/directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/normalization/ValueNormalizingVisitor.java?rev=328253&r1=328252&r2=328253&view=diff
==============================================================================
--- directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/normalization/ValueNormalizingVisitor.java (original)
+++ directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/normalization/ValueNormalizingVisitor.java Mon Oct 24 21:20:27 2005
@@ -17,10 +17,7 @@
package org.apache.ldap.server.normalization;
-import org.apache.ldap.common.filter.FilterVisitor;
-import org.apache.ldap.common.filter.ExprNode;
-import org.apache.ldap.common.filter.BranchNode;
-import org.apache.ldap.common.filter.SimpleNode;
+import org.apache.ldap.common.filter.*;
import org.apache.ldap.common.name.NameComponentNormalizer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -30,14 +27,27 @@
/**
- * A filter visitor which normalizes leaf node values as it visits them.
+ * 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 branchnode 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>
* @version $Rev$
*/
public class ValueNormalizingVisitor implements FilterVisitor
{
+ /** logger used by this class */
private final static Logger log = LoggerFactory.getLogger( ValueNormalizingVisitor.class );
+ /** the name component normalizer used by this visitor */
private final NameComponentNormalizer ncn;
@@ -52,11 +62,17 @@
if ( node instanceof SimpleNode )
{
SimpleNode snode = ( SimpleNode ) node;
- String normalized = null;
+ String normalized;
try
{
- if ( Character.isDigit( snode.getAttribute().charAt( 0 ) ) )
+ // still need this check here in case the top level is a leaf node
+ // with an undefined attributeType for its attribute
+ if ( ! ncn.isDefined( snode.getAttribute() ) )
+ {
+ normalized = snode.getValue();
+ }
+ else if ( Character.isDigit( snode.getAttribute().charAt( 0 ) ) )
{
normalized = ncn.normalizeByOid( snode.getAttribute(), snode.getValue() );
}
@@ -75,13 +91,78 @@
return;
}
- if (node instanceof BranchNode)
+ if ( node instanceof BranchNode )
{
BranchNode bnode = ( BranchNode ) node;
- final int size = bnode.getChildren().size();
- for ( int ii = 0; ii < size ; ii++ )
+ StringBuffer buf = null;
+ for ( int ii = 0; ii < bnode.getChildren().size() ; ii++ )
+ {
+ // before visiting each node let's check to make sure non-branch children use
+ // attributes that are defined in the system, if undefined nodes are removed
+ ExprNode child = ( ExprNode ) bnode.getChildren().get( ii );
+ if ( child.isLeaf() )
+ {
+ LeafNode ln = ( LeafNode ) child;
+ if ( ! ncn.isDefined( ln.getAttribute() ) )
+ {
+ if ( buf == null )
+ {
+ buf = new StringBuffer();
+ }
+ else
+ {
+ buf.setLength( 0 );
+ }
+ buf.append( "Removing leaf node based on undefined attribute '" );
+ buf.append( ln.getAttribute() );
+ buf.append( "' from filter." );
+ log.warn( buf.toString() );
+
+ // remove the child at ii
+ bnode.getChildren().remove( child );
+ ii--; // decrement so we can evaluate next child which has shifted to ii
+ continue;
+ }
+ }
+
+ visit( child );
+ }
+
+ // now see if any branch child nodes are damaged (NOT without children,
+ // AND/OR with one or less children) and repair them by removing branch
+ // nodes without children and replacing branch nodes like AND/OR with
+ // their single child if other branch nodes do not remain.
+ for ( int ii = 0; ii < bnode.getChildren().size() ; ii++ )
{
- visit( ( ExprNode ) bnode.getChildren().get( ii ) );
+ ExprNode unknown = ( ExprNode ) bnode.getChildren().get( ii );
+ if ( !unknown.isLeaf() )
+ {
+ BranchNode child = ( BranchNode ) unknown;
+
+ // remove child branch node that has no children left
+ if ( child.getChildren().size() == 0 )
+ {
+ // remove the child at ii
+ bnode.getChildren().remove( child );
+ ii--; // decrement so we can evaluate next child which has shifted to ii
+ continue;
+ }
+
+ // now for AND & OR nodes with a single child left replace them
+ // with their child at the same index they AND/OR node was in
+ if ( child.getChildren().size() == 1 && child.getOperator() != BranchNode.NOT )
+ {
+ bnode.getChildren().remove( child );
+ if ( ii >= bnode.getChildren().size() )
+ {
+ bnode.getChildren().add( child.getChild() );
+ }
+ else
+ {
+ bnode.getChildren().add( ii, child.getChild() );
+ }
+ }
+ }
}
}
}
Modified: directory/apacheds/trunk/main/src/test/org/apache/ldap/server/MiscTest.java
URL: http://svn.apache.org/viewcvs/directory/apacheds/trunk/main/src/test/org/apache/ldap/server/MiscTest.java?rev=328253&r1=328252&r2=328253&view=diff
==============================================================================
--- directory/apacheds/trunk/main/src/test/org/apache/ldap/server/MiscTest.java (original)
+++ directory/apacheds/trunk/main/src/test/org/apache/ldap/server/MiscTest.java Mon Oct 24 21:20:27 2005
@@ -18,6 +18,7 @@
import org.apache.ldap.server.configuration.MutableDirectoryPartitionConfiguration;
+import org.apache.ldap.common.util.EmptyEnumeration;
import java.util.Hashtable;
import java.util.Set;
@@ -230,5 +231,27 @@
InitialDirContext userCtx = new InitialDirContext( env );
assertNotNull( userCtx );
+ }
+
+
+ /**
+ * Tests to make sure undefined attributes in filter assertions are pruned and do not
+ * result in exceptions.
+ */
+ public void testBogusAttributeInSearchFilter() throws Exception
+ {
+ SearchControls cons = new SearchControls();
+ NamingEnumeration e = sysRoot.search( "", "(bogusAttribute=abc123)", cons );
+ assertNotNull( e );
+ assertEquals( e.getClass(), EmptyEnumeration.class );
+ e = sysRoot.search( "", "(!(bogusAttribute=abc123))", cons );
+ assertNotNull( e );
+ assertEquals( e.getClass(), EmptyEnumeration.class );
+ e = sysRoot.search( "", "(& (bogusAttribute=abc123)(bogusAttribute=abc123) )", cons );
+ assertNotNull( e );
+ assertEquals( e.getClass(), EmptyEnumeration.class );
+ e = sysRoot.search( "", "(& (bogusAttribute=abc123)(ou=abc123) )", cons );
+ assertNotNull( e );
+ assertFalse( e.getClass().equals( EmptyEnumeration.class ) );
}
}