1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.directory.server.core.normalization;
21
22
23 import org.apache.directory.api.ldap.model.constants.SchemaConstants;
24 import org.apache.directory.api.ldap.model.cursor.EmptyCursor;
25 import org.apache.directory.api.ldap.model.entry.Entry;
26 import org.apache.directory.api.ldap.model.entry.Modification;
27 import org.apache.directory.api.ldap.model.entry.Value;
28 import org.apache.directory.api.ldap.model.exception.LdapException;
29 import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeTypeException;
30 import org.apache.directory.api.ldap.model.filter.AndNode;
31 import org.apache.directory.api.ldap.model.filter.BranchNode;
32 import org.apache.directory.api.ldap.model.filter.EqualityNode;
33 import org.apache.directory.api.ldap.model.filter.ExprNode;
34 import org.apache.directory.api.ldap.model.filter.LeafNode;
35 import org.apache.directory.api.ldap.model.filter.NotNode;
36 import org.apache.directory.api.ldap.model.filter.ObjectClassNode;
37 import org.apache.directory.api.ldap.model.filter.OrNode;
38 import org.apache.directory.api.ldap.model.filter.PresenceNode;
39 import org.apache.directory.api.ldap.model.filter.UndefinedNode;
40 import org.apache.directory.api.ldap.model.name.Ava;
41 import org.apache.directory.api.ldap.model.name.Dn;
42 import org.apache.directory.api.ldap.model.name.Rdn;
43 import org.apache.directory.api.ldap.model.schema.AttributeType;
44 import org.apache.directory.api.ldap.model.schema.normalizers.ConcreteNameComponentNormalizer;
45 import org.apache.directory.api.ldap.model.schema.normalizers.NameComponentNormalizer;
46 import org.apache.directory.server.core.api.DirectoryService;
47 import org.apache.directory.server.core.api.InterceptorEnum;
48 import org.apache.directory.server.core.api.filtering.EntryFilteringCursorImpl;
49 import org.apache.directory.server.core.api.filtering.EntryFilteringCursor;
50 import org.apache.directory.server.core.api.interceptor.BaseInterceptor;
51 import org.apache.directory.server.core.api.interceptor.context.AddOperationContext;
52 import org.apache.directory.server.core.api.interceptor.context.CompareOperationContext;
53 import org.apache.directory.server.core.api.interceptor.context.DeleteOperationContext;
54 import org.apache.directory.server.core.api.interceptor.context.HasEntryOperationContext;
55 import org.apache.directory.server.core.api.interceptor.context.LookupOperationContext;
56 import org.apache.directory.server.core.api.interceptor.context.ModifyOperationContext;
57 import org.apache.directory.server.core.api.interceptor.context.MoveAndRenameOperationContext;
58 import org.apache.directory.server.core.api.interceptor.context.MoveOperationContext;
59 import org.apache.directory.server.core.api.interceptor.context.RenameOperationContext;
60 import org.apache.directory.server.core.api.interceptor.context.SearchOperationContext;
61 import org.apache.directory.server.core.api.normalization.FilterNormalizingVisitor;
62 import org.apache.directory.server.i18n.I18n;
63 import org.slf4j.Logger;
64 import org.slf4j.LoggerFactory;
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79 public class NormalizationInterceptor extends BaseInterceptor
80 {
81
82 private static final Logger LOG = LoggerFactory.getLogger( NormalizationInterceptor.class );
83
84
85 private FilterNormalizingVisitor normVisitor;
86
87
88
89
90
91 public NormalizationInterceptor()
92 {
93 super( InterceptorEnum.NORMALIZATION_INTERCEPTOR );
94 }
95
96
97
98
99
100 @Override
101 public void init( DirectoryService directoryService ) throws LdapException
102 {
103 LOG.debug( "Initialiazing the NormalizationInterceptor" );
104
105 super.init( directoryService );
106
107 NameComponentNormalizer ncn = new ConcreteNameComponentNormalizer( schemaManager );
108 normVisitor = new FilterNormalizingVisitor( ncn, schemaManager );
109 }
110
111
112
113
114
115 @Override
116 public void destroy()
117 {
118 }
119
120
121
122
123
124
125
126
127 @Override
128 public void add( AddOperationContext addContext ) throws LdapException
129 {
130 Dn addDn = addContext.getDn();
131
132 if ( !addDn.isSchemaAware() )
133 {
134 addContext.setDn( new Dn( schemaManager, addDn ) );
135 }
136
137 Dn entryDn = addContext.getEntry().getDn();
138
139 if ( !entryDn.isSchemaAware() )
140 {
141 addContext.getEntry().setDn( new Dn( schemaManager, entryDn ) );
142 }
143
144 addRdnAttributesToEntry( addContext.getDn(), addContext.getEntry() );
145
146 next( addContext );
147 }
148
149
150
151
152
153 @Override
154 public boolean compare( CompareOperationContext compareContext ) throws LdapException
155 {
156 Dn dn = compareContext.getDn();
157
158 if ( !dn.isSchemaAware() )
159 {
160 compareContext.setDn( new Dn( schemaManager, dn ) );
161 }
162
163
164 try
165 {
166 AttributeType attributeType = schemaManager.lookupAttributeTypeRegistry( compareContext.getOid() );
167
168
169 if ( attributeType.getSyntax().isHumanReadable() && ( !compareContext.getValue().isHumanReadable() ) )
170 {
171 compareContext.setValue( compareContext.getValue() );
172 }
173
174 compareContext.setAttributeType( attributeType );
175 }
176 catch ( LdapException le )
177 {
178 throw new LdapInvalidAttributeTypeException( I18n.err( I18n.ERR_266, compareContext.getOid() ) );
179 }
180
181 return next( compareContext );
182 }
183
184
185
186
187
188 @Override
189 public void delete( DeleteOperationContext deleteContext ) throws LdapException
190 {
191 Dn dn = deleteContext.getDn();
192
193 if ( !dn.isSchemaAware() )
194 {
195 deleteContext.setDn( new Dn( schemaManager, dn ) );
196 }
197
198 next( deleteContext );
199 }
200
201
202
203
204
205 @Override
206 public boolean hasEntry( HasEntryOperationContext hasEntryContext ) throws LdapException
207 {
208 Dn dn = hasEntryContext.getDn();
209
210 if ( !dn.isSchemaAware() )
211 {
212 hasEntryContext.setDn( new Dn( schemaManager, dn ) );
213 }
214
215 return next( hasEntryContext );
216 }
217
218
219
220
221
222 @Override
223 public Entry lookup( LookupOperationContext lookupContext ) throws LdapException
224 {
225 Dn dn = lookupContext.getDn();
226
227 if ( !dn.isSchemaAware() )
228 {
229 lookupContext.setDn( new Dn( schemaManager, dn ) );
230 }
231
232 return next( lookupContext );
233 }
234
235
236
237
238
239 @Override
240 public void modify( ModifyOperationContext modifyContext ) throws LdapException
241 {
242 Dn dn = modifyContext.getDn();
243
244 if ( !dn.isSchemaAware() )
245 {
246 modifyContext.setDn( new Dn( schemaManager, dn ) );
247 }
248
249 if ( modifyContext.getModItems() != null )
250 {
251 for ( Modification modification : modifyContext.getModItems() )
252 {
253 AttributeType attributeType = schemaManager.getAttributeType( modification.getAttribute().getId() );
254 modification.apply( attributeType );
255 }
256 }
257
258 next( modifyContext );
259 }
260
261
262
263
264
265 @Override
266 public void move( MoveOperationContext moveContext ) throws LdapException
267 {
268 Dn moveDn = moveContext.getDn();
269
270 if ( !moveDn.isSchemaAware() )
271 {
272 moveContext.setDn( new Dn( schemaManager, moveDn ) );
273 }
274
275 Dn oldSuperiorDn = moveContext.getOldSuperior();
276
277 if ( !oldSuperiorDn.isSchemaAware() )
278 {
279 moveContext.setOldSuperior( new Dn( schemaManager, oldSuperiorDn ) );
280 }
281
282 Dn newSuperiorDn = moveContext.getNewSuperior();
283
284 if ( !newSuperiorDn.isSchemaAware() )
285 {
286 moveContext.setNewSuperior( new Dn( schemaManager, newSuperiorDn ) );
287 }
288
289 Dn newDn = moveContext.getNewDn();
290
291 if ( !newDn.isSchemaAware() )
292 {
293 moveContext.setNewDn( new Dn( schemaManager, newDn ) );
294 }
295
296 Rdn rdn = moveContext.getRdn();
297
298 if ( !rdn.isSchemaAware() )
299 {
300 moveContext.setRdn( new Rdn( schemaManager, rdn ) );
301 }
302
303 next( moveContext );
304 }
305
306
307
308
309
310 @Override
311 public void moveAndRename( MoveAndRenameOperationContext moveAndRenameContext ) throws LdapException
312 {
313 Rdn newRdn = moveAndRenameContext.getNewRdn();
314
315 if ( !newRdn.isSchemaAware() )
316 {
317 moveAndRenameContext.setNewRdn( new Rdn( schemaManager, newRdn ) );
318 }
319
320 Dn dn = moveAndRenameContext.getDn();
321
322 if ( !dn.isSchemaAware() )
323 {
324 moveAndRenameContext.setDn( new Dn( schemaManager, dn ) );
325 }
326
327 Dn newDn = moveAndRenameContext.getNewDn();
328
329 if ( !newDn.isSchemaAware() )
330 {
331 moveAndRenameContext.setNewDn( new Dn( schemaManager, newDn ) );
332 }
333
334 Dn newSuperiorDn = moveAndRenameContext.getNewSuperiorDn();
335
336 if ( !newSuperiorDn.isSchemaAware() )
337 {
338 moveAndRenameContext.setNewSuperiorDn( new Dn( schemaManager, newSuperiorDn ) );
339 }
340
341 next( moveAndRenameContext );
342 }
343
344
345
346
347
348 @Override
349 public void rename( RenameOperationContext renameContext ) throws LdapException
350 {
351
352 Dn dn = renameContext.getDn();
353
354 if ( !dn.isSchemaAware() )
355 {
356 renameContext.setDn( new Dn( schemaManager, dn ) );
357 }
358
359 Rdn newRdn = renameContext.getNewRdn();
360
361 if ( !newRdn.isSchemaAware() )
362 {
363 renameContext.setNewRdn( new Rdn( schemaManager, newRdn ) );
364 }
365
366 Dn newDn = renameContext.getNewDn();
367
368 if ( !newDn.isSchemaAware() )
369 {
370 renameContext.setNewDn( new Dn( schemaManager, newDn ) );
371 }
372
373
374 next( renameContext );
375 }
376
377
378
379
380
381 @Override
382 public EntryFilteringCursor search( SearchOperationContext searchContext ) throws LdapException
383 {
384 Dn dn = searchContext.getDn();
385
386 if ( !dn.isSchemaAware() )
387 {
388 searchContext.setDn( new Dn( schemaManager, dn ) );
389 }
390
391 ExprNode filter = searchContext.getFilter();
392
393 if ( filter == null )
394 {
395 LOG.warn( "undefined filter based on undefined attributeType not evaluted at all. Returning empty enumeration." );
396 return new EntryFilteringCursorImpl( new EmptyCursor<Entry>(), searchContext, schemaManager );
397 }
398
399
400 filter = ( ExprNode ) filter.accept( normVisitor );
401
402 if ( filter == null )
403 {
404 LOG.warn( "undefined filter based on undefined attributeType not evaluted at all. Returning empty enumeration." );
405 return new EntryFilteringCursorImpl( new EmptyCursor<Entry>(), searchContext, schemaManager );
406 }
407
408
409 ExprNode modifiedFilter = removeObjectClass( filter );
410
411 searchContext.setFilter( modifiedFilter );
412
413
414 return next( searchContext );
415 }
416
417
418
419
420
421 private ExprNode handleAndNode( ExprNode node )
422 {
423 int nbNodes = 0;
424 AndNode newAndNode = new AndNode();
425
426 for ( ExprNode child : ( ( BranchNode ) node ).getChildren() )
427 {
428 ExprNode modifiedNode = removeObjectClass( child );
429
430 if ( !( modifiedNode instanceof ObjectClassNode ) )
431 {
432 newAndNode.addNode( modifiedNode );
433 nbNodes++;
434 }
435
436 if ( modifiedNode instanceof UndefinedNode )
437 {
438
439 return UndefinedNode.UNDEFINED_NODE;
440 }
441 }
442
443 switch ( nbNodes )
444 {
445 case 0:
446
447 return ObjectClassNode.OBJECT_CLASS_NODE;
448
449 case 1:
450
451 return newAndNode.getFirstChild();
452
453 default:
454 return newAndNode;
455 }
456 }
457
458
459
460
461
462 private ExprNode handleNotNode( ExprNode node )
463 {
464 for ( ExprNode child : ( ( BranchNode ) node ).getChildren() )
465 {
466 ExprNode modifiedNode = removeObjectClass( child );
467
468 if ( modifiedNode instanceof ObjectClassNode )
469 {
470
471 return UndefinedNode.UNDEFINED_NODE;
472 }
473
474 if ( modifiedNode instanceof UndefinedNode )
475 {
476
477 return ObjectClassNode.OBJECT_CLASS_NODE;
478 }
479 }
480
481 return node;
482 }
483
484
485
486
487
488 private ExprNode handleOrNode( ExprNode node )
489 {
490 for ( ExprNode child : ( ( BranchNode ) node ).getChildren() )
491 {
492 ExprNode modifiedNode = removeObjectClass( child );
493
494 if ( modifiedNode instanceof ObjectClassNode )
495 {
496
497 return ObjectClassNode.OBJECT_CLASS_NODE;
498 }
499 }
500
501 return node;
502 }
503
504
505
506
507
508 private ExprNode removeObjectClass( ExprNode node )
509 {
510 if ( node instanceof LeafNode )
511 {
512 LeafNode leafNode = ( LeafNode ) node;
513
514 if ( leafNode.getAttributeType() == directoryService.getAtProvider().getObjectClass() )
515 {
516 if ( leafNode instanceof PresenceNode )
517 {
518
519 return ObjectClassNode.OBJECT_CLASS_NODE;
520 }
521 else if ( leafNode instanceof EqualityNode )
522 {
523 Value value = ( ( EqualityNode<String> ) leafNode ).getValue();
524
525 if ( value.equals( SchemaConstants.TOP_OC ) )
526 {
527
528 return ObjectClassNode.OBJECT_CLASS_NODE;
529 }
530 }
531 }
532 }
533
534
535
536
537
538 if ( node instanceof AndNode )
539 {
540 return handleAndNode( node );
541 }
542 else if ( node instanceof OrNode )
543 {
544 return handleOrNode( node );
545 }
546 else if ( node instanceof NotNode )
547 {
548 return handleNotNode( node );
549 }
550 else
551 {
552
553 return node;
554 }
555 }
556
557
558
559
560
561
562
563
564
565
566
567 private void addRdnAttributesToEntry( Dn dn, Entry entry ) throws LdapException
568 {
569 if ( dn == null || entry == null )
570 {
571 return;
572 }
573
574 Rdn rdn = dn.getRdn();
575
576
577 for ( Ava ava : rdn )
578 {
579 Value value = ava.getValue();
580 String upValue = ava.getValue().getString();
581 String upId = ava.getType();
582
583
584 if ( !entry.contains( upId, value ) )
585 {
586 String message = "The Rdn '" + upId + "=" + upValue + "' is not present in the entry";
587 LOG.warn( message );
588
589
590
591
592 if ( !entry.containsAttribute( upId ) )
593 {
594 entry.add( upId, upValue );
595 }
596
597 else
598 {
599 AttributeType at = schemaManager.lookupAttributeTypeRegistry( upId );
600
601
602 if ( at.isSingleValued() )
603 {
604 entry.removeAttributes( upId );
605 entry.add( upId, upValue );
606 }
607
608 else
609 {
610 entry.add( upId, upValue );
611 }
612 }
613 }
614 }
615 }
616 }