Return-Path: Delivered-To: apmail-incubator-directory-cvs-archive@www.apache.org Received: (qmail 55762 invoked from network); 27 Oct 2004 16:04:20 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199) by minotaur-2.apache.org with SMTP; 27 Oct 2004 16:04:20 -0000 Received: (qmail 84986 invoked by uid 500); 27 Oct 2004 16:04:20 -0000 Delivered-To: apmail-incubator-directory-cvs-archive@incubator.apache.org Received: (qmail 84933 invoked by uid 500); 27 Oct 2004 16:04:19 -0000 Mailing-List: contact directory-cvs-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: directory-dev@incubator.apache.org Delivered-To: mailing list directory-cvs@incubator.apache.org Received: (qmail 84915 invoked by uid 99); 27 Oct 2004 16:04:19 -0000 X-ASF-Spam-Status: No, hits=-10.0 required=10.0 tests=ALL_TRUSTED,NO_REAL_NAME X-Spam-Check-By: apache.org Received: from [209.237.227.194] (HELO minotaur.apache.org) (209.237.227.194) by apache.org (qpsmtpd/0.28) with SMTP; Wed, 27 Oct 2004 09:04:18 -0700 Received: (qmail 55705 invoked by uid 65534); 27 Oct 2004 16:04:17 -0000 Date: 27 Oct 2004 16:04:17 -0000 Message-ID: <20041027160417.55694.qmail@minotaur.apache.org> From: akarasulu@apache.org To: directory-cvs@incubator.apache.org Subject: svn commit: rev 55711 - in incubator/directory/eve/trunk/backend/core/src/java/org/apache/eve: . db jndi/ibs X-Virus-Checked: Checked X-Spam-Rating: minotaur-2.apache.org 1.6.2 0/1000/N 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 Apache Directory Project + * @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 Apache Directory Project + * @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; }