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 }