1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.ldap.server.db;
18
19
20 import org.apache.ldap.common.NotImplementedException;
21 import org.apache.ldap.common.filter.*;
22 import org.apache.ldap.common.schema.AttributeType;
23 import org.apache.ldap.common.schema.MatchingRule;
24 import org.apache.ldap.common.schema.Normalizer;
25 import org.apache.ldap.server.schema.AttributeTypeRegistry;
26 import org.apache.ldap.server.schema.OidRegistry;
27
28 import javax.naming.NamingEnumeration;
29 import javax.naming.NamingException;
30 import javax.naming.directory.Attribute;
31 import javax.naming.directory.Attributes;
32 import java.math.BigInteger;
33 import java.util.Comparator;
34
35
36 /***
37 * Evaluates LeafNode assertions on candidates using a database.
38 *
39 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
40 * @version $Rev: 159259 $
41 */
42 public class LeafEvaluator implements Evaluator
43 {
44 /*** equality matching type constant */
45 private static final int EQUALITY_MATCH = 0;
46 /*** ordering matching type constant */
47 private static final int ORDERING_MATCH = 1;
48 /*** substring matching type constant */
49 private static final int SUBSTRING_MATCH = 3;
50
51
52 /*** Database used to evaluate leaf with */
53 private Database db;
54 /*** Oid Registry used to translate attributeIds to OIDs */
55 private OidRegistry oidRegistry;
56 /*** AttributeType registry needed for normalizing and comparing values */
57 private AttributeTypeRegistry attributeTypeRegistry;
58 /*** Substring node evaluator we depend on */
59 private SubstringEvaluator substringEvaluator;
60 /*** ScopeNode evaluator we depend on */
61 private ScopeEvaluator scopeEvaluator;
62
63
64 /***
65 * Creates a leaf expression node evaluator.
66 *
67 * @param db
68 * @param scopeEvaluator
69 * @param substringEvaluator
70 */
71 public LeafEvaluator( Database db, OidRegistry oidRegistry,
72 AttributeTypeRegistry attributeTypeRegistry,
73 ScopeEvaluator scopeEvaluator,
74 SubstringEvaluator substringEvaluator )
75 {
76 this.db = db;
77 this.oidRegistry = oidRegistry;
78 this.attributeTypeRegistry = attributeTypeRegistry;
79 this.scopeEvaluator = scopeEvaluator;
80 this.substringEvaluator = substringEvaluator;
81 }
82
83
84 public ScopeEvaluator getScopeEvaluator()
85 {
86 return scopeEvaluator;
87 }
88
89
90 public SubstringEvaluator getSubstringEvaluator()
91 {
92 return substringEvaluator;
93 }
94
95
96 /***
97 * @see org.apache.ldap.server.db.Evaluator#evaluate(ExprNode, IndexRecord)
98 */
99 public boolean evaluate( ExprNode node, IndexRecord record ) throws NamingException
100 {
101 if ( node instanceof ScopeNode )
102 {
103 return scopeEvaluator.evaluate( node, record );
104 }
105
106 switch( ( ( LeafNode ) node ).getAssertionType() )
107 {
108 case( LeafNode.APPROXIMATE ):
109 return evalEquality( ( SimpleNode ) node, record );
110 case( LeafNode.EQUALITY ):
111 return evalEquality( ( SimpleNode ) node, record );
112 case( LeafNode.EXTENSIBLE ):
113 throw new NotImplementedException();
114 case( LeafNode.GREATEREQ ):
115 return evalGreater( ( SimpleNode ) node, record, true );
116 case( LeafNode.LESSEQ ):
117 return evalGreater( ( SimpleNode ) node, record, false );
118 case( LeafNode.PRESENCE ):
119 String attrId = ( ( PresenceNode ) node ).getAttribute();
120 return evalPresence( attrId, record );
121 case( LeafNode.SUBSTRING ):
122 return substringEvaluator.evaluate( node, record );
123 default:
124 throw new NamingException( "Unrecognized leaf node type: "
125 + ( ( LeafNode ) node ).getAssertionType() );
126 }
127 }
128
129
130 /***
131 * Evaluates a simple greater than or less than attribute value assertion on
132 * a perspective candidate.
133 *
134 * @param node the greater than or less than node to evaluate
135 * @param record the IndexRecord of the perspective candidate
136 * @param isGreater true if it is a greater than or equal to comparison,
137 * false if it is a less than or equal to comparison.
138 * @return the ava evaluation on the perspective candidate
139 * @throws NamingException if there is a database access failure
140 */
141 private boolean evalGreater( SimpleNode node, IndexRecord record,
142 boolean isGreater ) throws NamingException
143 {
144 String attrId = node.getAttribute();
145 BigInteger id = record.getEntryId();
146
147 if ( db.hasUserIndexOn( attrId ) )
148 {
149 Index idx = db.getUserIndex( attrId );
150
151 if ( isGreater )
152 {
153 return idx.hasValue( node.getValue(), id, true );
154 }
155
156 return idx.hasValue( node.getValue(), id, false );
157 }
158
159
160 if ( null == record.getAttributes() )
161 {
162 record.setAttributes( db.lookup( id ) );
163 }
164
165
166 Attribute attr = record.getAttributes().get( attrId );
167
168
169 if ( null == attr )
170 {
171 return false;
172 }
173
174
175
176
177
178 Normalizer normalizer = getNormalizer( attrId );
179 Comparator comparator = getComparator( attrId );
180 Object filterValue = normalizer.normalize( node.getValue() );
181 NamingEnumeration list = attr.getAll();
182
183
184
185
186
187 if ( isGreater )
188 {
189 while ( list.hasMore() )
190 {
191 Object value = normalizer.normalize( list.next() );
192
193
194 if ( 0 >= comparator.compare( value, filterValue ) )
195 {
196 return true;
197 }
198 }
199 }
200 else
201 {
202 while ( list.hasMore() )
203 {
204 Object value = normalizer.normalize( list.next() );
205
206
207 if ( 0 <= comparator.compare( value, filterValue ) )
208 {
209 return true;
210 }
211 }
212 }
213
214
215 return false;
216 }
217
218
219 /***
220 * Evaluates a simple presence attribute value assertion on a perspective
221 * candidate.
222 *
223 * @param attrId the name of the attribute tested for presence
224 * @param rec the IndexRecord of the perspective candidate
225 * @return the ava evaluation on the perspective candidate
226 * @throws NamingException if there is a database access failure
227 */
228 private boolean evalPresence( String attrId, IndexRecord rec )
229 throws NamingException
230 {
231 if ( db.hasUserIndexOn( attrId ) )
232 {
233 Index idx = db.getExistanceIndex();
234 return idx.hasValue( attrId, rec.getEntryId() );
235 }
236
237
238 if ( null == rec.getAttributes() )
239 {
240 rec.setAttributes( db.lookup( rec.getEntryId() ) );
241 }
242
243
244 Attributes attrs = rec.getAttributes();
245
246 if ( attrs == null )
247 {
248 return false;
249 }
250
251 return null != attrs.get( attrId );
252 }
253
254
255 /***
256 * Evaluates a simple equality attribute value assertion on a perspective
257 * candidate.
258 *
259 * @param node the equality node to evaluate
260 * @param rec the IndexRecord of the perspective candidate
261 * @return the ava evaluation on the perspective candidate
262 * @throws NamingException if there is a database access failure
263 */
264 private boolean evalEquality( SimpleNode node, IndexRecord rec )
265 throws NamingException
266 {
267 if ( db.hasUserIndexOn( node.getAttribute() ) )
268 {
269 Index idx = db.getUserIndex( node.getAttribute() );
270 return idx.hasValue( node.getValue(), rec.getEntryId() );
271 }
272
273 Normalizer normalizer = getNormalizer( node.getAttribute() );
274 Comparator comparator = getComparator( node.getAttribute() );
275
276
277
278
279
280
281
282
283
284
285 if ( null == rec.getAttributes() )
286 {
287 rec.setAttributes( db.lookup( rec.getEntryId() ) );
288 }
289
290
291 Attribute attr = rec.getAttributes().get( node.getAttribute() );
292
293
294 if ( null == attr )
295 {
296 return false;
297 }
298
299
300 if ( attr.contains( node.getValue() ) )
301 {
302 return true;
303 }
304
305
306 Object filterValue = normalizer.normalize( node.getValue() );
307
308
309 if ( attr.contains( filterValue ) )
310 {
311 return true;
312 }
313
314
315
316
317
318
319 NamingEnumeration list = attr.getAll();
320 while ( list.hasMore() )
321 {
322 Object value = normalizer.normalize( list.next() );
323
324 if ( 0 == comparator.compare( value, filterValue ) )
325 {
326 return true;
327 }
328 }
329
330
331 return false;
332 }
333
334
335 /***
336 * Gets the comparator for equality matching.
337 *
338 * @param attrId the attribute identifier
339 * @return the comparator for equality matching
340 * @throws NamingException if there is a failure
341 */
342 private Comparator getComparator( String attrId ) throws NamingException
343 {
344 MatchingRule mrule = getMatchingRule( attrId, EQUALITY_MATCH );
345 return mrule.getComparator();
346 }
347
348
349 /***
350 * Gets the normalizer for equality matching.
351 *
352 * @param attrId the attribute identifier
353 * @return the normalizer for equality matching
354 * @throws NamingException if there is a failure
355 */
356 private Normalizer getNormalizer( String attrId ) throws NamingException
357 {
358 MatchingRule mrule = getMatchingRule( attrId, EQUALITY_MATCH );
359 return mrule.getNormalizer();
360 }
361
362
363 /***
364 * Gets the matching rule for an attributeType.
365 *
366 * @param attrId the attribute identifier
367 * @return the matching rule
368 * @throws NamingException if there is a failure
369 */
370 private MatchingRule getMatchingRule( String attrId, int matchType )
371 throws NamingException
372 {
373 MatchingRule mrule = null;
374 String oid = oidRegistry.getOid( attrId );
375 AttributeType type = attributeTypeRegistry.lookup( oid );
376
377 switch( matchType )
378 {
379 case( EQUALITY_MATCH ):
380 mrule = type.getEquality();
381 break;
382 case( SUBSTRING_MATCH ):
383 mrule = type.getSubstr();
384 break;
385 case( ORDERING_MATCH ):
386 mrule = type.getOrdering();
387 break;
388 default:
389 throw new NamingException( "Unknown match type: " + matchType );
390 }
391
392 return mrule;
393 }
394 }