| /* |
| * 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.partition.impl.btree; |
| |
| |
| import java.util.HashSet; |
| import java.util.Iterator; |
| import java.util.NoSuchElementException; |
| import java.util.Set; |
| |
| import javax.naming.NamingEnumeration; |
| import javax.naming.NamingException; |
| |
| import org.apache.directory.server.core.entry.DefaultServerEntry; |
| import org.apache.directory.server.core.entry.ServerAttribute; |
| import org.apache.directory.server.core.entry.ServerEntry; |
| import org.apache.directory.server.core.entry.ServerSearchResult; |
| import org.apache.directory.server.core.enumeration.SearchResultEnumeration; |
| import org.apache.directory.server.schema.registries.Registries; |
| import org.apache.directory.shared.ldap.constants.SchemaConstants; |
| import org.apache.directory.shared.ldap.entry.EntryAttribute; |
| import org.apache.directory.shared.ldap.name.LdapDN; |
| import org.apache.directory.shared.ldap.schema.AttributeType; |
| import org.apache.directory.shared.ldap.schema.UsageEnum; |
| |
| |
| /** |
| * An enumeration that transforms another underlying enumeration over a set of |
| * IndexRecords into an enumeration over a set of SearchResults. Note that the |
| * SearchResult created may not be complete and other parts of the system may |
| * modify it before return. This enumeration simply creates a new copy of the |
| * entry to return stuffing it with the attributes that were specified. This is |
| * all that it does now but this may change later. |
| * |
| * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> |
| * @version $Rev$ |
| */ |
| public class BTreeSearchResultEnumeration implements SearchResultEnumeration |
| { |
| /** Database used to lookup entries from */ |
| private BTreePartition partition = null; |
| /** the attributes to return */ |
| private final String[] attrIds; |
| /** underlying enumeration over IndexRecords */ |
| private final NamingEnumeration<IndexRecord> underlying; |
| |
| private boolean attrIdsHasStar = false; |
| private boolean attrIdsHasPlus = false; |
| private Registries registries = null; |
| |
| |
| /** |
| * using the search parameters supplied to a search call. |
| * Creates an enumeration that returns entries packaged within SearchResults |
| * |
| * @param attrIds the returned attributes |
| * @param underlying the enumeration over IndexRecords |
| */ |
| public BTreeSearchResultEnumeration( String[] attrIds, NamingEnumeration<IndexRecord> underlying, BTreePartition db, |
| Registries registries) |
| { |
| this.partition = db; |
| this.attrIds = attrIds; |
| this.underlying = underlying; |
| this.attrIdsHasStar = containsStar( attrIds ); |
| this.attrIdsHasPlus = containsPlus( attrIds ); |
| this.registries = registries; |
| } |
| |
| |
| /** |
| * @see javax.naming.NamingEnumeration#close() |
| */ |
| public void close() throws NamingException |
| { |
| underlying.close(); |
| } |
| |
| |
| /** |
| * @see javax.naming.NamingEnumeration#hasMore() |
| */ |
| public boolean hasMore() throws NamingException |
| { |
| return underlying.hasMore(); |
| } |
| |
| |
| /** |
| * @see javax.naming.NamingEnumeration#next() |
| */ |
| public ServerSearchResult next() throws NamingException |
| { |
| IndexRecord rec = underlying.next(); |
| ServerEntry entry = rec.getEntry(); |
| |
| if ( null == entry ) |
| { |
| entry = partition.lookup( (Long)rec.getEntryId() ); |
| rec.setEntry( entry ); |
| entry = (ServerEntry)entry.clone(); |
| } |
| |
| LdapDN dn = entry.getDn(); |
| |
| if ( ( attrIds == null ) || ( attrIdsHasPlus && attrIdsHasStar ) ) |
| { |
| } |
| else if ( attrIdsHasPlus ) |
| { |
| entry = new DefaultServerEntry( registries, dn ); |
| |
| // add all listed attributes |
| for ( String attrId:attrIds ) |
| { |
| if ( attrId.equals( SchemaConstants.ALL_OPERATIONAL_ATTRIBUTES ) ) |
| { |
| continue; |
| } |
| // there is no attribute by that name in the entry so we continue |
| if ( null == rec.getEntry().get( attrId ) ) |
| { |
| continue; |
| } |
| |
| ServerAttribute attr = ( ServerAttribute ) rec.getEntry().get( attrId ).clone(); |
| |
| entry.put( attr ); |
| } |
| |
| // add all operational attributes |
| for ( EntryAttribute attribute:rec.getEntry() ) |
| { |
| AttributeType attrType = ((ServerAttribute)attribute).getAttributeType(); |
| |
| if ( attrType.getUsage() == UsageEnum.USER_APPLICATIONS ) |
| { |
| continue; |
| } |
| |
| ServerAttribute attr = (ServerAttribute)attribute.clone(); |
| entry.put( attr ); |
| } |
| } |
| else if ( attrIdsHasStar ) |
| { |
| entry = new DefaultServerEntry( registries, dn ); |
| |
| // add all listed operational attributes |
| for ( String attrId:attrIds ) |
| { |
| if ( attrId.equals( SchemaConstants.ALL_USER_ATTRIBUTES ) ) |
| { |
| continue; |
| } |
| // there is no attribute by that name in the entry so we continue |
| if ( null == rec.getEntry().get( attrId ) ) |
| { |
| continue; |
| } |
| |
| // clone attribute to stuff into the new resultant entry |
| ServerAttribute attr = ( ServerAttribute ) rec.getEntry().get( attrId ).clone(); |
| entry.put( attr ); |
| } |
| |
| // add all user attributes |
| for ( EntryAttribute attribute:rec.getEntry() ) |
| { |
| AttributeType attrType = ((ServerAttribute)attribute).getAttributeType(); |
| |
| if ( attrType.getUsage() == UsageEnum.USER_APPLICATIONS ) |
| { |
| ServerAttribute attr = ( ServerAttribute ) rec.getEntry().get( attrType ).clone(); |
| entry.put( attr ); |
| } |
| } |
| } |
| else |
| { |
| Set<EntryAttribute> entryAttrs = new HashSet<EntryAttribute>(); |
| |
| for ( EntryAttribute entryAttribute:entry ) |
| { |
| entryAttrs.add( entryAttribute ); |
| } |
| //entry = new DefaultServerEntry( registries, dn ); |
| |
| //ServerEntry attrs = rec.getEntry(); |
| |
| for ( String attrId:attrIds ) |
| { |
| if ( SchemaConstants.NO_ATTRIBUTE.equals( attrId ) ) |
| { |
| break; |
| } |
| |
| EntryAttribute attr = entry.get( registries.getAttributeTypeRegistry().lookup( attrId ) ); |
| |
| // there is no attribute by that name in the entry so we continue |
| if ( null == attr ) |
| { |
| // May be it's because the attributeType is a inherited one? |
| Iterator<AttributeType> descendants = registries.getAttributeTypeRegistry().descendants( attrId ); |
| |
| while ( descendants.hasNext() ) |
| { |
| AttributeType atype = descendants.next(); |
| |
| attr = entry.get( atype ); |
| |
| if ( attr != null ) |
| { |
| // we may have more than one descendant, like sn and cn |
| // for name, so add all of them |
| //entry.put( (ServerAttribute)attr.clone() ); |
| entryAttrs.remove( attr ); |
| } |
| } |
| } |
| else |
| { |
| // clone attribute to stuff into the new resultant entry |
| //entry.put( (ServerAttribute)attr.clone() ); |
| entryAttrs.remove( attr ); |
| } |
| } |
| |
| for ( EntryAttribute entryAttribute:entryAttrs ) |
| { |
| entry.remove( entryAttribute ); |
| } |
| } |
| |
| |
| BTreeSearchResult result = new BTreeSearchResult( (Long)rec.getEntryId(), dn, null, entry ); |
| result.setRelative( false ); |
| return result; |
| } |
| |
| |
| private boolean containsStar( String[] ids ) |
| { |
| if ( ids == null ) |
| { |
| return false; |
| } |
| |
| for ( int ii = ids.length - 1; ii >= 0; ii-- ) |
| { |
| if ( ids[ii].trim().equals( SchemaConstants.ALL_USER_ATTRIBUTES ) ) |
| { |
| return true; |
| } |
| } |
| |
| return false; |
| } |
| |
| |
| private boolean containsPlus( String[] ids ) |
| { |
| if ( ids == null ) |
| { |
| return false; |
| } |
| |
| for ( int ii = ids.length - 1; ii >= 0; ii-- ) |
| { |
| if ( ids[ii].trim().equals( SchemaConstants.ALL_OPERATIONAL_ATTRIBUTES ) ) |
| { |
| return true; |
| } |
| } |
| |
| return false; |
| } |
| |
| |
| /** |
| * @see java.util.Enumeration#hasMoreElements() |
| */ |
| public boolean hasMoreElements() |
| { |
| return underlying.hasMoreElements(); |
| } |
| |
| |
| /** |
| * @see java.util.Enumeration#nextElement() |
| */ |
| public ServerSearchResult nextElement() |
| { |
| try |
| { |
| return next(); |
| } |
| catch ( NamingException e ) |
| { |
| NoSuchElementException nsee = |
| new NoSuchElementException( "Encountered NamingException on underlying enumeration." ); |
| nsee.initCause( e ); |
| throw nsee; |
| } |
| } |
| } |