View Javadoc

1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *  
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *  
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License. 
18   *  
19   */
20  package org.apache.directory.server.xdbm.search.impl;
21  
22  
23  import javax.naming.directory.SearchControls;
24  
25  import org.apache.directory.shared.ldap.filter.AndNode;
26  import org.apache.directory.shared.ldap.filter.BranchNode;
27  import org.apache.directory.shared.ldap.filter.ExprNode;
28  import org.apache.directory.shared.ldap.filter.ScopeNode;
29  import org.apache.directory.shared.ldap.filter.SearchScope;
30  import org.apache.directory.shared.ldap.message.AliasDerefMode;
31  import org.apache.directory.shared.ldap.name.LdapDN;
32  import org.apache.directory.server.xdbm.*;
33  import org.apache.directory.server.xdbm.search.Optimizer;
34  import org.apache.directory.server.xdbm.search.SearchEngine;
35  import org.apache.directory.server.xdbm.search.Evaluator;
36  import org.apache.directory.server.core.entry.ServerEntry;
37  
38  
39  /**
40   * Given a search filter and a scope the search engine identifies valid
41   * candidate entries returning their ids.
42   * 
43   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
44   * @version $Rev: 683760 $
45   */
46  public class DefaultSearchEngine implements SearchEngine<ServerEntry>
47  {
48      /** the Optimizer used by this DefaultSearchEngine */
49      private final Optimizer optimizer;
50      /** the Database this DefaultSearchEngine operates on */
51      private final Store<ServerEntry> db;
52      /** creates Cursors over entries satisfying filter expressions */
53      private final CursorBuilder cursorBuilder;
54      /** creates evaluators which check to see if candidates satisfy a filter expression */
55      private final EvaluatorBuilder evaluatorBuilder;
56  
57  
58      // ------------------------------------------------------------------------
59      // C O N S T R U C T O R S
60      // ------------------------------------------------------------------------
61      
62  
63      /**
64       * Creates a DefaultSearchEngine for searching a Database without setting
65       * up the database.
66       * @param db the btree based partition
67       * @param cursorBuilder an expression cursor builder
68       * @param evaluatorBuilder an expression evaluator builder
69       * @param optimizer an optimizer to use during search
70       */
71      public DefaultSearchEngine( Store<ServerEntry> db,
72                                  CursorBuilder cursorBuilder, EvaluatorBuilder evaluatorBuilder, Optimizer optimizer )
73      {
74          this.db = db;
75          this.optimizer = optimizer;
76          this.cursorBuilder = cursorBuilder;
77          this.evaluatorBuilder = evaluatorBuilder;
78      }
79  
80  
81      /**
82       * Gets the optimizer for this DefaultSearchEngine.
83       *
84       * @return the optimizer
85       */
86      public Optimizer getOptimizer()
87      {
88          return optimizer;
89      }
90  
91  
92      /**
93       * @see SearchEngine#cursor(LdapDN, AliasDerefMode, ExprNode, SearchControls)
94       */
95      public IndexCursor<Long,ServerEntry> cursor( LdapDN base, AliasDerefMode aliasDerefMode, ExprNode filter,
96                                                       SearchControls searchCtls ) throws Exception
97      {
98          LdapDN effectiveBase;
99          Long baseId = db.getEntryId( base.toString() );
100         String aliasedBase = db.getAliasIndex().reverseLookup( baseId );
101 
102         // --------------------------------------------------------------------
103         // Determine the effective base with aliases
104         // --------------------------------------------------------------------
105 
106         /*
107          * If the base is not an alias or if alias dereferencing does not
108          * occur on finding the base then we set the effective base to the
109          * given base.
110          */
111         if ( ( null == aliasedBase ) || ! aliasDerefMode.isDerefFindingBase() )
112         {
113             effectiveBase = base;
114         }
115 
116         /*
117          * If the base is an alias and alias dereferencing does occur on
118          * finding the base then we set the effective base to the alias target
119          * got from the alias index.
120          */
121         else
122         {
123             effectiveBase = new LdapDN( aliasedBase );
124         }
125         
126         // --------------------------------------------------------------------
127         // Specifically Handle Object Level Scope
128         // --------------------------------------------------------------------
129 
130         if ( searchCtls.getSearchScope() == SearchControls.OBJECT_SCOPE )
131         {
132             Long effectiveBaseId = baseId;
133             if ( effectiveBase != base )
134             {
135                 effectiveBaseId = db.getEntryId( effectiveBase.toNormName() ); 
136             }
137             
138             IndexEntry<Long, ServerEntry> indexEntry = new ForwardIndexEntry<Long, ServerEntry>();
139             indexEntry.setId( effectiveBaseId );
140             optimizer.annotate( filter );
141             Evaluator<? extends ExprNode, ServerEntry> evaluator = evaluatorBuilder.build( filter );
142             
143             if ( evaluator.evaluate( indexEntry ) )
144             {
145                 return new SingletonIndexCursor<Long,ServerEntry>( indexEntry );
146             }
147             else
148             {
149                 return new EmptyIndexCursor<Long, ServerEntry>();
150             }
151         }
152         
153         // Add the scope node using the effective base to the filter
154         BranchNode root = new AndNode();
155         ExprNode node = new ScopeNode( aliasDerefMode, effectiveBase.toString(), 
156             SearchScope.getSearchScope( searchCtls ) );
157         root.getChildren().add( node );
158         root.getChildren().add( filter );
159 
160         // Annotate the node with the optimizer and return search enumeration.
161         optimizer.annotate( root );
162         return ( IndexCursor<Long, ServerEntry> ) cursorBuilder.build( root );
163     }
164 
165 
166     /**
167      * @see SearchEngine#evaluator(ExprNode)
168      */
169     public Evaluator<? extends ExprNode, ServerEntry> evaluator( ExprNode filter )
170         throws Exception
171     {
172         return evaluatorBuilder.build( filter );
173     }
174 }