1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.directory.server.core.api.entry;
20
21
22 import java.util.ArrayList;
23 import java.util.HashSet;
24 import java.util.List;
25 import java.util.NoSuchElementException;
26 import java.util.Set;
27
28 import javax.naming.NamingEnumeration;
29 import javax.naming.NamingException;
30 import javax.naming.directory.Attributes;
31 import javax.naming.directory.BasicAttribute;
32 import javax.naming.directory.BasicAttributes;
33 import javax.naming.directory.DirContext;
34 import javax.naming.directory.ModificationItem;
35 import javax.naming.directory.SearchResult;
36
37 import org.apache.directory.api.ldap.model.constants.SchemaConstants;
38 import org.apache.directory.api.ldap.model.entry.Attribute;
39 import org.apache.directory.api.ldap.model.entry.DefaultAttribute;
40 import org.apache.directory.api.ldap.model.entry.DefaultEntry;
41 import org.apache.directory.api.ldap.model.entry.DefaultModification;
42 import org.apache.directory.api.ldap.model.entry.Entry;
43 import org.apache.directory.api.ldap.model.entry.Modification;
44 import org.apache.directory.api.ldap.model.entry.ModificationOperation;
45 import org.apache.directory.api.ldap.model.entry.Value;
46 import org.apache.directory.api.ldap.model.exception.LdapException;
47 import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeTypeException;
48 import org.apache.directory.api.ldap.model.name.Dn;
49 import org.apache.directory.api.ldap.model.schema.AttributeType;
50 import org.apache.directory.api.ldap.model.schema.AttributeTypeOptions;
51 import org.apache.directory.api.ldap.model.schema.SchemaManager;
52 import org.apache.directory.api.ldap.model.schema.SchemaUtils;
53 import org.apache.directory.api.util.EmptyEnumeration;
54 import org.apache.directory.api.util.Strings;
55 import org.apache.directory.server.core.api.interceptor.context.FilteringOperationContext;
56 import org.apache.directory.server.i18n.I18n;
57
58
59
60
61
62
63
64 public final class ServerEntryUtils
65 {
66 private ServerEntryUtils()
67 {
68 }
69
70
71
72
73
74
75
76
77
78
79 public static javax.naming.directory.Attribute toBasicAttribute( Attribute entryAttribute )
80 {
81 AttributeType attributeType = entryAttribute.getAttributeType();
82
83 javax.naming.directory.Attribute attribute = new BasicAttribute( attributeType.getName() );
84
85 for ( Value value : entryAttribute )
86 {
87 if ( attributeType.isHR() )
88 {
89 attribute.add( value.getString() );
90 }
91 else
92 {
93 attribute.add( value.getBytes() );
94 }
95 }
96
97 return attribute;
98 }
99
100
101
102
103
104
105
106
107
108
109 public static Attributes toBasicAttributes( Entry entry )
110 {
111 if ( entry == null )
112 {
113 return null;
114 }
115
116 Attributes attributes = new BasicAttributes( true );
117
118 for ( Attribute attribute : entry.getAttributes() )
119 {
120 AttributeType attributeType = attribute.getAttributeType();
121 Attribute attr = entry.get( attributeType );
122
123
124 if ( attributeType.getOid().equals( SchemaConstants.OBJECT_CLASS_AT_OID ) && attr.size() == 0 )
125 {
126
127 continue;
128 }
129
130 attributes.put( toBasicAttribute( attr ) );
131 }
132
133 return attributes;
134 }
135
136
137
138
139
140
141
142
143
144
145
146 public static Attribute toServerAttribute( javax.naming.directory.Attribute attribute, AttributeType attributeType )
147 throws LdapException
148 {
149 if ( attribute == null )
150 {
151 return null;
152 }
153
154 try
155 {
156 Attribute serverAttribute = new DefaultAttribute( attributeType );
157
158 for ( NamingEnumeration<?> values = attribute.getAll(); values.hasMoreElements(); )
159 {
160 Object value = values.nextElement();
161 int nbAdded = 0;
162
163 if ( value == null )
164 {
165 continue;
166 }
167
168 if ( serverAttribute.isHumanReadable() )
169 {
170 if ( value instanceof String )
171 {
172 nbAdded = serverAttribute.add( ( String ) value );
173 }
174 else if ( value instanceof byte[] )
175 {
176 nbAdded = serverAttribute.add( Strings.utf8ToString( ( byte[] ) value ) );
177 }
178 else
179 {
180 throw new LdapInvalidAttributeTypeException();
181 }
182 }
183 else
184 {
185 if ( value instanceof String )
186 {
187 nbAdded = serverAttribute.add( Strings.getBytesUtf8( ( String ) value ) );
188 }
189 else if ( value instanceof byte[] )
190 {
191 nbAdded = serverAttribute.add( ( byte[] ) value );
192 }
193 else
194 {
195 throw new LdapInvalidAttributeTypeException();
196 }
197 }
198
199 if ( nbAdded == 0 )
200 {
201 throw new LdapInvalidAttributeTypeException();
202 }
203 }
204
205 return serverAttribute;
206 }
207 catch ( NamingException ne )
208 {
209 throw new LdapInvalidAttributeTypeException();
210 }
211 }
212
213
214
215
216
217
218
219
220
221
222
223
224 public static Entry toServerEntry( Attributes attributes, Dn dn, SchemaManager schemaManager )
225 throws LdapInvalidAttributeTypeException
226 {
227 if ( attributes instanceof BasicAttributes )
228 {
229 try
230 {
231 Entry entry = new DefaultEntry( schemaManager, dn );
232
233 for ( NamingEnumeration<? extends javax.naming.directory.Attribute> attrs = attributes.getAll(); attrs
234 .hasMoreElements(); )
235 {
236 javax.naming.directory.Attribute attr = attrs.nextElement();
237
238 String attributeId = attr.getID();
239 String id = SchemaUtils.stripOptions( attributeId );
240 Set<String> options = SchemaUtils.getOptions( attributeId );
241
242 AttributeType attributeType = schemaManager.lookupAttributeTypeRegistry( id );
243 Attribute serverAttribute = ServerEntryUtils.toServerAttribute( attr, attributeType );
244
245 if ( serverAttribute != null )
246 {
247 entry.put( serverAttribute );
248 }
249 }
250
251 return entry;
252 }
253 catch ( LdapException ne )
254 {
255 throw new LdapInvalidAttributeTypeException( ne.getLocalizedMessage() );
256 }
257 }
258 else
259 {
260 return null;
261 }
262 }
263
264
265
266
267
268
269
270
271
272
273
274
275 public static Entry getTargetEntry( Modification mod, Entry entry, SchemaManager schemaManager )
276 throws LdapException
277 {
278 Entry targetEntry = entry.clone();
279 ModificationOperation modOp = mod.getOperation();
280 String id = mod.getAttribute().getUpId();
281 AttributeType attributeType = schemaManager.lookupAttributeTypeRegistry( id );
282
283 switch ( modOp )
284 {
285 case REPLACE_ATTRIBUTE:
286 targetEntry.put( mod.getAttribute() );
287 break;
288
289 case REMOVE_ATTRIBUTE:
290 Attribute toBeRemoved = mod.getAttribute();
291
292 if ( toBeRemoved.size() == 0 )
293 {
294 targetEntry.removeAttributes( id );
295 }
296 else
297 {
298 Attribute existing = targetEntry.get( id );
299
300 if ( existing != null )
301 {
302 for ( Value value : toBeRemoved )
303 {
304 existing.remove( value );
305 }
306 }
307 }
308 break;
309
310 case ADD_ATTRIBUTE:
311 Attribute combined = new DefaultAttribute( id, attributeType );
312 Attribute toBeAdded = mod.getAttribute();
313 Attribute existing = entry.get( id );
314
315 if ( existing != null )
316 {
317 for ( Value value : existing )
318 {
319 combined.add( value );
320 }
321 }
322
323 for ( Value value : toBeAdded )
324 {
325 combined.add( value );
326 }
327
328 targetEntry.put( combined );
329 break;
330
331 default:
332 throw new IllegalStateException( I18n.err( I18n.ERR_464, modOp ) );
333 }
334
335 return targetEntry;
336 }
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352 public static Attribute getUnion( Attribute attr0, Attribute attr1 ) throws LdapException
353 {
354 if ( attr0 == null && attr1 == null )
355 {
356 throw new IllegalArgumentException( I18n.err( I18n.ERR_465 ) );
357 }
358 else if ( attr0 == null )
359 {
360 return attr1.clone();
361 }
362 else if ( attr1 == null )
363 {
364 return attr0.clone();
365 }
366 else if ( !attr0.getAttributeType().equals( attr1.getAttributeType() ) )
367 {
368 throw new IllegalArgumentException( I18n.err( I18n.ERR_466 ) );
369 }
370
371 Attribute attr = attr0.clone();
372
373 for ( Value value : attr1 )
374 {
375 attr.add( value );
376 }
377
378 return attr;
379 }
380
381
382
383
384
385
386
387
388
389 private static Modification toServerModification( ModificationItem modificationImpl, AttributeType attributeType )
390 throws LdapException
391 {
392 ModificationOperation operation;
393
394 switch ( modificationImpl.getModificationOp() )
395 {
396 case DirContext.REMOVE_ATTRIBUTE:
397 operation = ModificationOperation.REMOVE_ATTRIBUTE;
398 break;
399
400 case DirContext.REPLACE_ATTRIBUTE:
401 operation = ModificationOperation.REPLACE_ATTRIBUTE;
402 break;
403
404 case DirContext.ADD_ATTRIBUTE:
405 default:
406 operation = ModificationOperation.ADD_ATTRIBUTE;
407 break;
408
409 }
410
411 return new DefaultModification( operation,
412 ServerEntryUtils.toServerAttribute( modificationImpl.getAttribute(), attributeType ) );
413 }
414
415
416
417
418
419
420
421
422
423
424
425 public static List<Modification> convertToServerModification( List<ModificationItem> modificationItems,
426 SchemaManager schemaManager ) throws LdapException
427 {
428 if ( modificationItems != null )
429 {
430 List<Modification> modifications = new ArrayList<>( modificationItems.size() );
431
432 for ( ModificationItem modificationItem : modificationItems )
433 {
434 AttributeType attributeType = schemaManager.lookupAttributeTypeRegistry( modificationItem
435 .getAttribute().getID() );
436 modifications.add( toServerModification( modificationItem, attributeType ) );
437 }
438
439 return modifications;
440 }
441 else
442 {
443 return null;
444 }
445 }
446
447
448
449
450
451
452
453
454
455 private static Modification toServerModification( Modification modification, AttributeType attributeType )
456 throws LdapException
457 {
458 return new DefaultModification(
459 modification.getOperation(),
460 new DefaultAttribute( attributeType, modification.getAttribute() ) );
461 }
462
463
464
465
466
467
468
469
470
471
472 public static List<Modification> toServerModification( Modification[] modifications,
473 SchemaManager schemaManager ) throws LdapException
474 {
475 if ( modifications != null )
476 {
477 List<Modification> modificationsList = new ArrayList<>();
478
479 for ( Modification modification : modifications )
480 {
481 String attributeId = modification.getAttribute().getUpId();
482 String id = stripOptions( attributeId );
483 modification.getAttribute().setUpId( id );
484 Set<String> options = getOptions( attributeId );
485
486
487
488
489
490 if ( !schemaManager.getAttributeTypeRegistry().contains( id )
491 && modification.getAttribute().size() == 0
492 && modification.getOperation() == ModificationOperation.REPLACE_ATTRIBUTE )
493 {
494
495
496 String message = I18n.err( I18n.ERR_467, id );
497 throw new LdapInvalidAttributeTypeException( message );
498 }
499 else
500 {
501
502 AttributeType attributeType = schemaManager.lookupAttributeTypeRegistry( id );
503 modificationsList.add( toServerModification( modification, attributeType ) );
504 }
505 }
506
507 return modificationsList;
508 }
509 else
510 {
511 return null;
512 }
513 }
514
515
516
517
518
519
520
521
522
523
524 public static List<Modification> toServerModification( ModificationItem[] modifications,
525 SchemaManager schemaManager ) throws LdapException
526 {
527 if ( modifications != null )
528 {
529 List<Modification> modificationsList = new ArrayList<>();
530
531 for ( ModificationItem modification : modifications )
532 {
533 String attributeId = modification.getAttribute().getID();
534 String id = stripOptions( attributeId );
535 Set<String> options = getOptions( attributeId );
536
537
538
539
540
541
542
543
544
545 if ( !schemaManager.getAttributeTypeRegistry().contains( id )
546 && modification.getAttribute().size() == 0
547 && modification.getModificationOp() == DirContext.REPLACE_ATTRIBUTE )
548 {
549 continue;
550 }
551
552
553
554
555
556
557 AttributeType attributeType = schemaManager.lookupAttributeTypeRegistry( id );
558 modificationsList.add( toServerModification( modification, attributeType ) );
559 }
560
561 return modificationsList;
562 }
563 else
564 {
565 return null;
566 }
567 }
568
569
570
571
572
573
574
575
576
577 public static Modification getModificationItem( List<Modification> mods, AttributeType type )
578 {
579 for ( Modification modification : mods )
580 {
581 Attribute attribute = modification.getAttribute();
582
583 if ( attribute.getAttributeType() == type )
584 {
585 return modification;
586 }
587 }
588
589 return null;
590 }
591
592
593
594
595
596
597
598
599
600 public static Attribute getAttribute( List<Modification> mods, AttributeType type )
601 {
602 Modification mod = getModificationItem( mods, type );
603
604 if ( mod != null )
605 {
606 return mod.getAttribute();
607 }
608
609 return null;
610 }
611
612
613
614
615
616
617
618 public static NamingEnumeration<SearchResult> toSearchResultEnum( final NamingEnumeration<ServerSearchResult> result )
619 {
620 if ( result instanceof EmptyEnumeration<?> )
621 {
622 return new EmptyEnumeration<>();
623 }
624
625 return new NamingEnumeration<SearchResult>()
626 {
627 public void close() throws NamingException
628 {
629 result.close();
630 }
631
632
633
634
635
636 public boolean hasMore() throws NamingException
637 {
638 return result.hasMore();
639 }
640
641
642
643
644
645 public SearchResult next() throws NamingException
646 {
647 ServerSearchResult rec = result.next();
648
649 return new SearchResult(
650 rec.getDn().getName(),
651 rec.getObject(),
652 toBasicAttributes( rec.getServerEntry() ),
653 rec.isRelative() );
654 }
655
656
657
658
659
660 public boolean hasMoreElements()
661 {
662 return result.hasMoreElements();
663 }
664
665
666
667
668
669 public SearchResult nextElement()
670 {
671 try
672 {
673 ServerSearchResult rec = result.next();
674
675 return new SearchResult(
676 rec.getDn().getName(),
677 rec.getObject(),
678 toBasicAttributes( rec.getServerEntry() ),
679 rec.isRelative() );
680 }
681 catch ( NamingException ne )
682 {
683 NoSuchElementException nsee =
684 new NoSuchElementException( I18n.err( I18n.ERR_468 ) );
685 nsee.initCause( ne );
686 throw nsee;
687 }
688 }
689 };
690 }
691
692
693
694
695
696
697
698
699
700
701
702 private static String stripOptions( String attributeId )
703 {
704 int optionsPos = attributeId.indexOf( ';' );
705
706 if ( optionsPos != -1 )
707 {
708 return attributeId.substring( 0, optionsPos );
709 }
710 else
711 {
712 return attributeId;
713 }
714 }
715
716
717
718
719
720
721
722
723
724
725 private static Set<String> getOptions( String attributeId )
726 {
727 int optionsPos = attributeId.indexOf( ';' );
728
729 if ( optionsPos != -1 )
730 {
731 Set<String> options = new HashSet<>();
732
733 String[] res = attributeId.substring( optionsPos + 1 ).split( ";" );
734
735 for ( String option : res )
736 {
737 if ( !Strings.isEmpty( option ) )
738 {
739 options.add( option );
740 }
741 }
742
743 return options;
744 }
745 else
746 {
747 return null;
748 }
749 }
750
751
752
753
754
755
756
757
758
759
760 public static void filterContents( SchemaManager schemaManager, FilteringOperationContext operationContext,
761 Entry entry ) throws LdapException
762 {
763 boolean typesOnly = operationContext.isTypesOnly();
764
765 boolean returnAll = ( operationContext.isAllOperationalAttributes() && operationContext.isAllUserAttributes() )
766 && ( !typesOnly );
767
768 if ( returnAll )
769 {
770 return;
771 }
772
773
774 Entry originalEntry = ( ( ClonedServerEntry ) entry ).getOriginalEntry();
775
776 AttributeType entryDnType = schemaManager.lookupAttributeTypeRegistry( SchemaConstants.ENTRY_DN_AT_OID );
777 AttributeType refType = schemaManager.lookupAttributeTypeRegistry( SchemaConstants.REF_AT_OID );
778
779
780 if ( operationContext.isNoAttributes() )
781 {
782 for ( Attribute attribute : originalEntry )
783 {
784 AttributeType attributeType = attribute.getAttributeType();
785
786
787 if ( operationContext.isReferralThrown() && attributeType.equals( refType ) )
788 {
789 continue;
790 }
791
792 entry.remove( entry.get( attributeType ) );
793 }
794
795 entry.removeAttributes( entryDnType );
796
797 return;
798 }
799
800
801
802 if ( operationContext.isAllUserAttributes() )
803 {
804 for ( Attribute attribute : originalEntry )
805 {
806 AttributeType attributeType = attribute.getAttributeType();
807
808
809 if ( operationContext.isReferralThrown() && attributeType.equals( refType ) )
810 {
811 continue;
812 }
813
814 if ( attributeType.isOperational() )
815 {
816 if ( !operationContext.contains( schemaManager, attributeType ) )
817 {
818 entry.removeAttributes( attributeType );
819 }
820 else if ( typesOnly )
821 {
822 entry.get( attributeType ).clear();
823 }
824 }
825 else if ( typesOnly )
826 {
827 entry.get( attributeType ).clear();
828 }
829 }
830
831
832 if ( !operationContext.contains( schemaManager, entryDnType ) )
833 {
834 entry.removeAttributes( entryDnType );
835 }
836
837 return;
838 }
839
840
841
842 if ( operationContext.isAllOperationalAttributes() )
843 {
844 for ( Attribute attribute : originalEntry )
845 {
846 AttributeType attributeType = attribute.getAttributeType();
847
848 if ( attributeType.isUser() )
849 {
850 if ( !operationContext.contains( schemaManager, attributeType ) )
851 {
852 entry.removeAttributes( attributeType );
853 }
854 else if ( typesOnly )
855 {
856 entry.get( attributeType ).clear();
857 }
858 }
859 else if ( typesOnly )
860 {
861 entry.get( attributeType ).clear();
862 }
863 }
864
865 if ( !operationContext.contains( schemaManager, entryDnType ) )
866 {
867 entry.removeAttributes( entryDnType );
868 }
869 else if ( typesOnly )
870 {
871 entry.get( entryDnType ).clear();
872 }
873
874 return;
875 }
876
877
878 if ( operationContext.getReturningAttributes() != null )
879 {
880 for ( Attribute attribute : originalEntry )
881 {
882 AttributeType attributeType = attribute.getAttributeType();
883
884
885 if ( operationContext.isReferralThrown() && attributeType.equals( refType ) )
886 {
887 continue;
888 }
889
890 if ( !operationContext.contains( schemaManager, attributeType ) )
891 {
892 entry.removeAttributes( attributeType );
893 continue;
894 }
895
896 boolean isNotRequested = true;
897
898 for ( AttributeTypeOptions attrOptions : operationContext.getReturningAttributes() )
899 {
900 if ( attrOptions.getAttributeType().equals( attributeType )
901 || attrOptions.getAttributeType().isAncestorOf( attributeType ) )
902 {
903 isNotRequested = false;
904 break;
905 }
906 }
907
908 if ( isNotRequested )
909 {
910 entry.removeAttributes( attributeType );
911 }
912 else if ( typesOnly )
913 {
914 entry.get( attributeType ).clear();
915 }
916 }
917
918 if ( !operationContext.contains( schemaManager, entryDnType ) )
919 {
920 entry.removeAttributes( entryDnType );
921 }
922 else if ( typesOnly )
923 {
924 entry.get( entryDnType ).clear();
925 }
926 }
927 }
928 }