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 2004/10/27 18:04:17 UTC

svn commit: rev 55711 - in incubator/directory/eve/trunk/backend/core/src/java/org/apache/eve: . db jndi/ibs

Author: akarasulu
Date: Wed Oct 27 09:04:14 2004
New Revision: 55711

Added:
   incubator/directory/eve/trunk/backend/core/src/java/org/apache/eve/db/ResultFilter.java
   incubator/directory/eve/trunk/backend/core/src/java/org/apache/eve/db/ResultFilteringEnumeration.java
Modified:
   incubator/directory/eve/trunk/backend/core/src/java/org/apache/eve/AbstractContextPartition.java
   incubator/directory/eve/trunk/backend/core/src/java/org/apache/eve/BackingStore.java
   incubator/directory/eve/trunk/backend/core/src/java/org/apache/eve/PartitionNexus.java
   incubator/directory/eve/trunk/backend/core/src/java/org/apache/eve/RootNexus.java
   incubator/directory/eve/trunk/backend/core/src/java/org/apache/eve/jndi/ibs/OperationalAttributeService.java
Log:
Changes ...

 o moved the lookup(Name,String[]) overload back into the BackingStore; this 
   was done because some stores might optimize the values returned instead
   of returning all values; plus this is really a backing store operation
 o implemented lookup(Name,String[]) since it was throwing a NotImpl except.
 o added the concept of a database search result filter for filtering and
   transforming result attributes and values on the way back to the caller
 o added a decorator which applies result filters to enumerations over
   database search reasults
 o used this new filtering enumeration decorator within the OpAttr interceptor
   service to wrap the search NamingEnumeration return value; this way the
   OpAttr interceptor service can filter operational attributes in the result
   being returned to the caller

Todos ...

 o we still need to thoroughly test this code



Modified: incubator/directory/eve/trunk/backend/core/src/java/org/apache/eve/AbstractContextPartition.java
==============================================================================
--- incubator/directory/eve/trunk/backend/core/src/java/org/apache/eve/AbstractContextPartition.java	(original)
+++ incubator/directory/eve/trunk/backend/core/src/java/org/apache/eve/AbstractContextPartition.java	Wed Oct 27 09:04:14 2004
@@ -28,9 +28,11 @@
 import javax.naming.directory.SearchControls;
 import javax.naming.ContextNotEmptyException;
 import javax.naming.directory.ModificationItem;
+import javax.naming.directory.Attribute;
 
 import org.apache.ldap.common.filter.ExprNode;
 import org.apache.ldap.common.schema.AttributeType;
+import org.apache.ldap.common.message.LockableAttributesImpl;
 
 import org.apache.eve.db.Database;
 import org.apache.eve.db.SearchEngine;
@@ -298,6 +300,33 @@
     public Attributes lookup( Name dn ) throws NamingException
     {
         return db.lookup( db.getEntryId( dn.toString() ) );
+    }
+
+
+    /**
+     * @see BackingStore#lookup(Name,String[])
+     */
+    public Attributes lookup( Name dn, String [] attrIds ) throws NamingException
+    {
+        if ( attrIds == null || attrIds.length == 0 )
+        {
+            return lookup( dn );
+        }
+
+        Attributes entry = lookup( dn );
+        Attributes retval = new LockableAttributesImpl();
+
+        for ( int ii = 0; ii < attrIds.length; ii++ )
+        {
+            Attribute attr = entry.get( attrIds[0] );
+
+            if ( attr != null )
+            {
+                retval.put( attr );
+            }
+        }
+
+        return retval;
     }
 
 

Modified: incubator/directory/eve/trunk/backend/core/src/java/org/apache/eve/BackingStore.java
==============================================================================
--- incubator/directory/eve/trunk/backend/core/src/java/org/apache/eve/BackingStore.java	(original)
+++ incubator/directory/eve/trunk/backend/core/src/java/org/apache/eve/BackingStore.java	Wed Oct 27 09:04:14 2004
@@ -137,6 +137,19 @@
     Attributes lookup( Name name ) throws NamingException;
 
     /**
+     * Looks up an entry by distinguished name.  This is a simplified version
+     * of the search operation used to point read an entry used for convenience
+     * with a set of attributes to return.  If the attributes are null or emty
+     * this defaults to the lookup opertion without the attributes.
+     *
+     * @param dn the normalized distinguished name of the object to lookup
+     * @param attrIds the set of attributes to return
+     * @return an Attributes object representing the entry
+     * @throws NamingException if there are any problems
+     */
+    Attributes lookup( Name dn, String [] attrIds ) throws NamingException;
+
+    /**
      * Fast operation to check and see if a particular entry exists.
      *
      * @param name the normalized distinguished/absolute name of the object to

Modified: incubator/directory/eve/trunk/backend/core/src/java/org/apache/eve/PartitionNexus.java
==============================================================================
--- incubator/directory/eve/trunk/backend/core/src/java/org/apache/eve/PartitionNexus.java	(original)
+++ incubator/directory/eve/trunk/backend/core/src/java/org/apache/eve/PartitionNexus.java	Wed Oct 27 09:04:14 2004
@@ -22,7 +22,6 @@
 import javax.naming.Name;
 import javax.naming.NamingException;
 import javax.naming.ldap.LdapContext;
-import javax.naming.directory.Attributes;
 
 
 /**
@@ -94,25 +93,6 @@
      * @throws NamingException if there are any problems
      */
     Iterator listSuffixes( boolean normalized ) throws NamingException;
-
-    /**
-     * Looks up an entry by distinguished name.  This is a simplified version 
-     * of the search operation used to point read an entry used for convenience
-     * with a set of attributes to return.  If the attributes are null or emty
-     * this defaults to the lookup opertion without the attributes.
-     * 
-     * NOTE: This method is here in the nexus and not within the Backend 
-     * interface.  This is due to the fact that attribute selection by name 
-     * using the second parameter attrIds will be implemented after the call
-     * to a backend.  Hence selection of the correct set of attributes to return
-     * is not a responsibility of a Backend module.
-     *
-     * @param dn the normalized distinguished name of the object to lookup
-     * @param attrIds the set of attributes to return
-     * @return an Attributes object representing the entry
-     * @throws NamingException if there are any problems
-     */
-    Attributes lookup( Name dn, String [] attrIds ) throws NamingException;
 
     /**
      * Registers an ContextPartition with this BackendManager.  Called by each

Modified: incubator/directory/eve/trunk/backend/core/src/java/org/apache/eve/RootNexus.java
==============================================================================
--- incubator/directory/eve/trunk/backend/core/src/java/org/apache/eve/RootNexus.java	(original)
+++ incubator/directory/eve/trunk/backend/core/src/java/org/apache/eve/RootNexus.java	Wed Oct 27 09:04:14 2004
@@ -220,21 +220,22 @@
 
 
     /**
-     * @see BackingStore#lookup(Name)
+     * @see BackingStore#lookup(javax.naming.Name)
      */
-    public Attributes lookup( Name dn, String [] attrIds ) throws NamingException
+    public Attributes lookup( Name dn )  throws NamingException
     {
-        throw new NotImplementedException();
+        ContextPartition backend = getBackend( dn );
+        return backend.lookup( dn );
     }
 
 
     /**
-     * @see BackingStore#lookup(javax.naming.Name)
+     * @see BackingStore#lookup(javax.naming.Name, String[])
      */
-    public Attributes lookup( Name dn )  throws NamingException
+    public Attributes lookup( Name dn, String[] attrIds )  throws NamingException
     {
         ContextPartition backend = getBackend( dn );
-        return backend.lookup( dn );
+        return backend.lookup( dn, attrIds );
     }
 
 

Added: incubator/directory/eve/trunk/backend/core/src/java/org/apache/eve/db/ResultFilter.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/trunk/backend/core/src/java/org/apache/eve/db/ResultFilter.java	Wed Oct 27 09:04:14 2004
@@ -0,0 +1,43 @@
+/*
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed 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.eve.db;
+
+
+import javax.naming.NamingException;
+
+
+/**
+ * A filter is used to modify search results while they are being returned from
+ * naming enumerations containing DbSearchResults.  These filters are used in
+ * conjunction with a {@link ResultFilteringEnumeration}.  Multiple filters can
+ * be applied one after the other and hence they are stackable.
+ *
+ * @author <a href="mailto:directory-dev@incubator.apache.org">Apache Directory Project</a>
+ * @version $Rev$
+ */
+public interface ResultFilter
+{
+    /**
+     * Filters the contents of search results on the way out the door to client
+     * callers.  These filters can and do produce side-effects on the results if
+     * if need be the attributes or names within the result should be cloned.
+     *
+     * @return true if the result is to be returned, false if it is to be
+     * discarded from the result set
+     */
+    boolean accept( DbSearchResult result ) throws NamingException;
+}

Added: incubator/directory/eve/trunk/backend/core/src/java/org/apache/eve/db/ResultFilteringEnumeration.java
==============================================================================
--- (empty file)
+++ incubator/directory/eve/trunk/backend/core/src/java/org/apache/eve/db/ResultFilteringEnumeration.java	Wed Oct 27 09:04:14 2004
@@ -0,0 +1,237 @@
+/*
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed 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.eve.db;
+
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Collections;
+
+import javax.naming.NamingException;
+import javax.naming.NamingEnumeration;
+
+
+/**
+ * A enumeration decorator which filters database search results as they are
+ * being enumerated back to the client caller.
+ *
+ * @see ResultFilter
+ * @author <a href="mailto:directory-dev@incubator.apache.org">Apache Directory Project</a>
+ * @version $Rev$
+ */
+public class ResultFilteringEnumeration implements NamingEnumeration
+{
+    /** the list of filters to be applied */
+    private final ArrayList filters;
+    /** the underlying decorated enumeration */
+    private final NamingEnumeration decorated;
+
+    /** the first accepted search result that is prefetched */
+    private DbSearchResult prefetched;
+    /** flag storing closed state of this naming enumeration */
+    private boolean isClosed = false;
+
+
+    // ------------------------------------------------------------------------
+    // C O N S T R U C T O R S
+    // ------------------------------------------------------------------------
+
+
+    /**
+     * Creates a new database result filtering enumeration to decorate an
+     * underlying enumeration.
+     *
+     * @param decorated the underlying decorated enumeration
+     */
+    public ResultFilteringEnumeration( NamingEnumeration decorated )
+            throws NamingException
+    {
+        this.filters = new ArrayList();
+        this.decorated = decorated;
+
+        if ( ! decorated.hasMore() )
+        {
+            close();
+            return;
+        }
+
+        prefetch();
+    }
+
+
+    // ------------------------------------------------------------------------
+    // New ResultFilter management methods
+    // ------------------------------------------------------------------------
+
+
+    /**
+     * Adds a database search result filter to this filtering enumeration at
+     * the very end of the filter list.  Filters are applied in the order of
+     * addition.
+     *
+     * @param filter a filter to apply to the results
+     * @return the result of {@link List#add(Object)}
+     */
+    public boolean addResultFilter( ResultFilter filter )
+    {
+        return filters.add( filter );
+    }
+
+
+    /**
+     * Removes a database search result filter from the filter list of this
+     * filtering enumeration.
+     *
+     * @param filter a filter to remove from the filter list
+     * @return the result of {@link List#remove(Object)}
+     */
+    public boolean removeResultFilter( ResultFilter filter )
+    {
+        return filters.remove( filter );
+    }
+
+
+    /**
+     * Gets an unmodifiable list of filters.
+     *
+     * @return the result of {@link Collections#unmodifiableList(List)}
+     */
+    public List getFilters()
+    {
+        return Collections.unmodifiableList( filters );
+    }
+
+
+    // ------------------------------------------------------------------------
+    // NamingEnumeration Methods
+    // ------------------------------------------------------------------------
+
+
+    public void close() throws NamingException
+    {
+        isClosed = true;
+        decorated.close();
+    }
+
+
+    public boolean hasMore()
+    {
+        return !isClosed;
+    }
+
+
+    public Object next() throws NamingException
+    {
+        DbSearchResult retVal = this.prefetched;
+        prefetch();
+        return retVal;
+    }
+
+
+    // ------------------------------------------------------------------------
+    // Enumeration Methods
+    // ------------------------------------------------------------------------
+
+
+    public boolean hasMoreElements()
+    {
+        return !isClosed;
+    }
+
+
+    public Object nextElement()
+    {
+        DbSearchResult retVal = this.prefetched;
+
+        try
+        {
+            prefetch();
+        }
+        catch ( NamingException e )
+        {
+            e.printStackTrace();
+        }
+
+        return retVal;
+    }
+
+
+    // ------------------------------------------------------------------------
+    // Private utility methods
+    // ------------------------------------------------------------------------
+
+
+    /**
+     * Keeps getting results from the underlying decorated filter and applying
+     * the filters until a result is accepted by all and set as the prefetced
+     * result to return on the next() result request.  If no prefetched value
+     * can be found before exhausting the decorated enumeration, then this and
+     * the underlying enumeration is closed.
+     *
+     * @throws NamingException if there are problems getting results from the
+     * underlying enumeration
+     */
+    private void prefetch() throws NamingException
+    {
+        DbSearchResult tmp = null;
+
+        while( decorated.hasMore() )
+        {
+            boolean accepted = true;
+            tmp = ( DbSearchResult ) decorated.next();
+
+            // don't waste using a for loop if we got 0 or 1 element
+            if ( filters.isEmpty() )
+            {
+                this.prefetched = tmp;
+                return;
+            }
+            else if ( filters.size() == 1 )
+            {
+                accepted = ( ( ResultFilter ) filters.get( 0 ) ).accept( tmp );
+                this.prefetched = tmp;
+                return;
+            }
+
+            // apply all filters shorting their application on result denials
+            for ( int ii = 0; ii < filters.size(); ii ++ )
+            {
+                ResultFilter filter = ( ResultFilter ) filters.get( ii );
+                accepted &= filter.accept( tmp );
+
+                if ( ! accepted )
+                {
+                    continue;
+                }
+            }
+
+            /*
+             * If we get here then a result has been accepted by all the
+             * filters so we set the result as the prefetched value to return
+             * on the following call to the next() or nextElement() methods
+             */
+            this.prefetched = tmp;
+            return;
+        }
+
+        /*
+         * If we get here then no result was found to be accepted by all
+         * filters before we exhausted the decorated enumeration so we close
+         */
+        close();
+    }
+}

Modified: incubator/directory/eve/trunk/backend/core/src/java/org/apache/eve/jndi/ibs/OperationalAttributeService.java
==============================================================================
--- incubator/directory/eve/trunk/backend/core/src/java/org/apache/eve/jndi/ibs/OperationalAttributeService.java	(original)
+++ incubator/directory/eve/trunk/backend/core/src/java/org/apache/eve/jndi/ibs/OperationalAttributeService.java	Wed Oct 27 09:04:14 2004
@@ -17,18 +17,23 @@
 package org.apache.eve.jndi.ibs;
 
 
+import java.util.Map;
 import javax.naming.Name;
 import javax.naming.NamingException;
 import javax.naming.Context;
 import javax.naming.directory.*;
 
 import org.apache.eve.RootNexus;
+import org.apache.eve.db.SearchResultEnumeration;
+import org.apache.eve.db.DbSearchResult;
+import org.apache.eve.db.ResultFilteringEnumeration;
+import org.apache.eve.db.ResultFilter;
 import org.apache.eve.jndi.Invocation;
 import org.apache.eve.jndi.BaseInterceptor;
 import org.apache.eve.jndi.InvocationStateEnum;
-import org.apache.eve.schema.AttributeTypeRegistry;
 
 import org.apache.ldap.common.util.DateUtils;
+import org.apache.ldap.common.filter.ExprNode;
 
 
 /**
@@ -60,9 +65,6 @@
     /**
      * Adds extra operational attributes to the entry before it is added.
      *
-     * @todo add mechanism to find the identity of the caller so we can
-     * properly set the owner/modifier of the entry
-     *
      * @see BaseInterceptor#add(String, Name, Attributes)
      */
     protected void add( String upName, Name normName, Attributes entry ) throws NamingException
@@ -171,7 +173,8 @@
     }
 
 
-    protected void move( Name oriChildName, Name newParentName, String newRdn, boolean deleteOldRdn ) throws NamingException
+    protected void move( Name oriChildName, Name newParentName, String newRdn,
+                         boolean deleteOldRdn ) throws NamingException
     {
         Invocation invocation = getInvocation();
 
@@ -189,6 +192,57 @@
 
             nexus.modify( newParentName, DirContext.REPLACE_ATTRIBUTE, attributes );
         }
+    }
+
+
+    protected void lookup( Name dn ) throws NamingException
+    {
+        Invocation invocation = getInvocation();
+
+        if ( invocation.getState() == InvocationStateEnum.POSTINVOCATION )
+        {
+            filter( ( Attributes ) invocation.getReturnValue() );
+        }
+    }
+
+
+    protected void search( Name base, Map env, ExprNode filter,
+                           SearchControls searchControls )
+            throws NamingException
+    {
+        Invocation invocation = getInvocation();
+
+        if ( invocation.getState() == InvocationStateEnum.POSTINVOCATION )
+        {
+            SearchResultEnumeration enum ;
+            ResultFilteringEnumeration retval;
+            enum = ( SearchResultEnumeration ) invocation.getReturnValue();
+            retval = new ResultFilteringEnumeration( enum );
+            retval.addResultFilter( new ResultFilter() {
+                public boolean accept( DbSearchResult result )
+                {
+                    return filter( result.getAttributes() );
+                }
+            } );
+            invocation.setReturnValue( retval );
+        }
+    }
+
+
+    /**
+     * Filters out the operational attributes within a search results
+     * attributes.  The attributes are directly modified.
+     *
+     * @param attributes the resultant attributes to filter
+     * @return true always
+     */
+    private boolean filter( Attributes attributes )
+    {
+        attributes.remove( "creatorsName" );
+        attributes.remove( "modifiersName" );
+        attributes.remove( "createTimestamp" );
+        attributes.remove( "modifyTimestamp" );
+        return true;
     }