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.jndi;
21
22
23 import org.apache.directory.server.core.CoreSession;
24 import org.apache.directory.server.core.DirectoryService;
25 import org.apache.directory.server.core.authn.LdapPrincipal;
26 import org.apache.directory.server.core.entry.ServerEntry;
27 import org.apache.directory.server.core.entry.ServerEntryUtils;
28 import org.apache.directory.server.core.event.DirectoryListener;
29 import org.apache.directory.server.core.event.NotificationCriteria;
30 import org.apache.directory.server.core.interceptor.context.EntryOperationContext;
31 import org.apache.directory.shared.ldap.constants.SchemaConstants;
32 import org.apache.directory.shared.ldap.entry.EntryAttribute;
33 import org.apache.directory.shared.ldap.entry.Modification;
34 import org.apache.directory.shared.ldap.entry.client.ClientBinaryValue;
35 import org.apache.directory.shared.ldap.entry.client.ClientStringValue;
36 import org.apache.directory.shared.ldap.filter.AndNode;
37 import org.apache.directory.shared.ldap.filter.BranchNode;
38 import org.apache.directory.shared.ldap.filter.EqualityNode;
39 import org.apache.directory.shared.ldap.filter.ExprNode;
40 import org.apache.directory.shared.ldap.filter.FilterParser;
41 import org.apache.directory.shared.ldap.filter.PresenceNode;
42 import org.apache.directory.shared.ldap.filter.SearchScope;
43 import org.apache.directory.shared.ldap.filter.SimpleNode;
44 import org.apache.directory.shared.ldap.message.AliasDerefMode;
45 import org.apache.directory.shared.ldap.name.AttributeTypeAndValue;
46 import org.apache.directory.shared.ldap.name.LdapDN;
47 import org.apache.directory.shared.ldap.name.Rdn;
48 import org.apache.directory.shared.ldap.util.AttributeUtils;
49 import org.apache.directory.shared.ldap.util.StringTools;
50
51 import javax.naming.Name;
52 import javax.naming.NamingEnumeration;
53 import javax.naming.NamingException;
54 import javax.naming.Reference;
55 import javax.naming.Referenceable;
56 import javax.naming.directory.Attribute;
57 import javax.naming.directory.Attributes;
58 import javax.naming.directory.DirContext;
59 import javax.naming.directory.InvalidSearchFilterException;
60 import javax.naming.directory.ModificationItem;
61 import javax.naming.directory.SearchControls;
62 import javax.naming.directory.SearchResult;
63 import javax.naming.event.EventDirContext;
64 import javax.naming.event.NamingListener;
65 import javax.naming.spi.DirStateFactory;
66 import javax.naming.spi.DirectoryManager;
67 import java.io.Serializable;
68 import java.text.ParseException;
69 import java.util.ArrayList;
70 import java.util.Hashtable;
71 import java.util.Iterator;
72 import java.util.List;
73
74
75
76
77
78
79
80
81 public abstract class ServerDirContext extends ServerContext implements EventDirContext
82 {
83
84
85
86
87
88
89
90
91
92
93
94
95 public ServerDirContext( DirectoryService service, Hashtable<String, Object> env ) throws Exception
96 {
97 super( service, env );
98 }
99
100
101
102
103
104
105
106
107
108 public ServerDirContext( DirectoryService service, LdapPrincipal principal, Name dn ) throws Exception
109 {
110 super( service, principal, dn );
111 }
112
113
114
115
116
117
118
119 public ServerDirContext( DirectoryService service, CoreSession session, LdapDN bindDn ) throws Exception
120 {
121 super( service, session, bindDn );
122 }
123
124
125
126
127
128 public Attributes getAttributes( String name ) throws NamingException
129 {
130 return getAttributes( new LdapDN( name ) );
131 }
132
133
134
135
136
137 public Attributes getAttributes( Name name ) throws NamingException
138 {
139 Attributes attrs = null;
140
141 try
142 {
143 attrs = ServerEntryUtils.toBasicAttributes( doLookupOperation( buildTarget( name ) ) );
144 }
145 catch ( Exception e )
146 {
147 JndiUtils.wrap( e );
148 }
149
150 return attrs;
151 }
152
153
154
155
156
157
158 public Attributes getAttributes( String name, String[] attrIds ) throws NamingException
159 {
160 return getAttributes( new LdapDN( name ), attrIds );
161 }
162
163
164
165
166
167
168 public Attributes getAttributes( Name name, String[] attrIds ) throws NamingException
169 {
170 Attributes attrs = null;
171 try
172 {
173 attrs = ServerEntryUtils.toBasicAttributes( doLookupOperation( buildTarget( name ), attrIds ) );
174 }
175 catch ( Exception e )
176 {
177 JndiUtils.wrap( e );
178 }
179
180 return attrs;
181 }
182
183
184
185
186
187
188 public void modifyAttributes( String name, int modOp, Attributes attrs ) throws NamingException
189 {
190 modifyAttributes( new LdapDN( name ), modOp, AttributeUtils.toCaseInsensitive( attrs ) );
191 }
192
193
194
195
196
197
198 public void modifyAttributes( Name name, int modOp, Attributes attrs ) throws NamingException
199 {
200 List<ModificationItem> modItems = null;
201
202 if ( attrs != null )
203 {
204 modItems = new ArrayList<ModificationItem>( attrs.size() );
205 NamingEnumeration<? extends Attribute> e = ( NamingEnumeration<? extends Attribute> ) attrs.getAll();
206
207 while ( e.hasMore() )
208 {
209 modItems.add( new ModificationItem( modOp, e.next() ) );
210 }
211 }
212
213 List<Modification> newMods = ServerEntryUtils.convertToServerModification(
214 modItems,
215 getDirectoryService().getRegistries().getAttributeTypeRegistry() );
216
217 try
218 {
219 if ( name instanceof LdapDN )
220 {
221 doModifyOperation( buildTarget( name ), newMods );
222 }
223 else
224 {
225 doModifyOperation( buildTarget( new LdapDN( name ) ), newMods );
226 }
227 }
228 catch( Exception e )
229 {
230 JndiUtils.wrap( e );
231 }
232 }
233
234
235
236
237
238
239 public void modifyAttributes( String name, ModificationItem[] mods ) throws NamingException
240 {
241 modifyAttributes( new LdapDN( name ), mods );
242 }
243
244
245
246
247
248
249 public void modifyAttributes( Name name, ModificationItem[] mods ) throws NamingException
250 {
251 List<Modification> newMods = ServerEntryUtils
252 .toServerModification( mods, getDirectoryService().getRegistries().getAttributeTypeRegistry() );
253 try
254 {
255 doModifyOperation( buildTarget( new LdapDN( name ) ), newMods );
256 }
257 catch ( Exception e )
258 {
259 JndiUtils.wrap( e );
260 }
261 }
262
263
264
265
266
267
268 public void modifyAttributes( Name name, List<ModificationItem> mods ) throws NamingException
269 {
270 List<Modification> newMods = ServerEntryUtils
271 .convertToServerModification( mods,
272 getDirectoryService().getRegistries().getAttributeTypeRegistry() );
273 try
274 {
275 doModifyOperation( buildTarget( new LdapDN( name ) ), newMods );
276 }
277 catch ( Exception e )
278 {
279 JndiUtils.wrap( e );
280 }
281 }
282
283
284
285
286
287
288 public void bind( String name, Object obj, Attributes attrs ) throws NamingException
289 {
290 bind( new LdapDN( name ), obj, AttributeUtils.toCaseInsensitive( attrs ) );
291 }
292
293
294
295
296
297
298 public void bind( Name name, Object obj, Attributes attrs ) throws NamingException
299 {
300 if ( ( null == obj ) && ( null == attrs ) )
301 {
302 throw new NamingException( "Both obj and attrs args are null. "
303 + "At least one of these parameters must not be null." );
304 }
305
306
307 if ( null == attrs )
308 {
309 super.bind( name, obj );
310 return;
311 }
312
313 LdapDN target = buildTarget( name );
314
315 ServerEntry serverEntry = ServerEntryUtils.toServerEntry( AttributeUtils.toCaseInsensitive( attrs ), target,
316 getDirectoryService().getRegistries() );
317
318
319 if ( null == obj )
320 {
321 ServerEntry clone = ( ServerEntry ) serverEntry.clone();
322 try
323 {
324 doAddOperation( target, clone );
325 }
326 catch ( Exception e )
327 {
328 JndiUtils.wrap( e );
329 }
330 return;
331 }
332
333
334 DirStateFactory.Result res = DirectoryManager.getStateToBind( obj, name, this, getEnvironment(), attrs );
335 ServerEntry outServerEntry = ServerEntryUtils.toServerEntry(
336 res.getAttributes(), target, getDirectoryService().getRegistries() );
337
338 if ( outServerEntry != serverEntry )
339 {
340 ServerEntry clone = ( ServerEntry ) serverEntry.clone();
341
342 if ( ( outServerEntry != null ) && ( outServerEntry.size() > 0 ) )
343 {
344 for ( EntryAttribute attribute : outServerEntry )
345 {
346 clone.put( attribute );
347 }
348 }
349
350 try
351 {
352
353 doAddOperation( target, clone );
354 }
355 catch ( Exception e )
356 {
357 JndiUtils.wrap( e );
358 }
359 return;
360 }
361
362
363 if ( obj instanceof Referenceable )
364 {
365 throw new NamingException( "Do not know how to store Referenceables yet!" );
366 }
367
368
369 if ( obj instanceof Reference )
370 {
371
372 throw new NamingException( "Do not know how to store References yet!" );
373 }
374 else if ( obj instanceof Serializable )
375 {
376
377 ServerEntry clone = ( ServerEntry ) serverEntry.clone();
378
379 if ( outServerEntry != null && outServerEntry.size() > 0 )
380 {
381 for ( EntryAttribute attribute : outServerEntry )
382 {
383 clone.put( attribute );
384 }
385 }
386
387
388 JavaLdapSupport.serialize( serverEntry, obj, getDirectoryService().getRegistries() );
389 try
390 {
391
392 doAddOperation( target, clone );
393 }
394 catch ( Exception e )
395 {
396 JndiUtils.wrap( e );
397 }
398 }
399 else if ( obj instanceof DirContext )
400 {
401
402 ServerEntry entry = ServerEntryUtils.toServerEntry( ( ( DirContext ) obj ).getAttributes( "" ), target,
403 getDirectoryService().getRegistries() );
404
405 if ( ( outServerEntry != null ) && ( outServerEntry.size() > 0 ) )
406 {
407 for ( EntryAttribute attribute : outServerEntry )
408 {
409 entry.put( attribute );
410 }
411 }
412
413 try
414 {
415
416 doAddOperation( target, entry );
417 }
418 catch ( Exception e )
419 {
420 JndiUtils.wrap( e );
421 }
422 }
423 else
424 {
425 throw new NamingException( "Can't find a way to bind: " + obj );
426 }
427 }
428
429
430
431
432
433
434 public void rebind( String name, Object obj, Attributes attrs ) throws NamingException
435 {
436 rebind( new LdapDN( name ), obj, AttributeUtils.toCaseInsensitive( attrs ) );
437 }
438
439
440
441
442
443
444 public void rebind( Name name, Object obj, Attributes attrs ) throws NamingException
445 {
446 LdapDN target = buildTarget( name );
447
448 try
449 {
450 if ( getDirectoryService().getOperationManager().hasEntry( new EntryOperationContext( getSession(), target ) ) )
451 {
452 doDeleteOperation( target );
453 }
454 }
455 catch ( Exception e )
456 {
457 JndiUtils.wrap( e );
458 }
459
460 bind( name, obj, AttributeUtils.toCaseInsensitive( attrs ) );
461 }
462
463
464
465
466
467
468 public DirContext createSubcontext( String name, Attributes attrs ) throws NamingException
469 {
470 return createSubcontext( new LdapDN( name ), AttributeUtils.toCaseInsensitive( attrs ) );
471 }
472
473
474
475
476
477
478 public DirContext createSubcontext( Name name, Attributes attrs ) throws NamingException
479 {
480 if ( null == attrs )
481 {
482 return ( DirContext ) super.createSubcontext( name );
483 }
484
485 LdapDN target = buildTarget( name );
486 Rdn rdn = target.getRdn( target.size() - 1 );
487
488 attrs = AttributeUtils.toCaseInsensitive( attrs );
489 Attributes attributes = ( Attributes ) attrs.clone();
490
491 if ( rdn.size() == 1 )
492 {
493 String rdnAttribute = rdn.getUpType();
494 String rdnValue = ( String ) rdn.getValue();
495
496
497 boolean doRdnPut = attributes.get( rdnAttribute ) == null;
498 doRdnPut = doRdnPut || attributes.get( rdnAttribute ).size() == 0;
499
500
501 doRdnPut = doRdnPut || !attributes.get( rdnAttribute ).contains( rdnValue );
502
503 if ( doRdnPut )
504 {
505 attributes.put( rdnAttribute, rdnValue );
506 }
507 }
508 else
509 {
510 for ( Iterator<AttributeTypeAndValue> ii = rdn.iterator(); ii.hasNext();
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560 public DirContext getSchema( Name name ) throws NamingException
561 {
562 throw new UnsupportedOperationException();
563 }
564
565
566
567
568
569 public DirContext getSchema( String name ) throws NamingException
570 {
571 throw new UnsupportedOperationException();
572 }
573
574
575
576
577
578 public DirContext getSchemaClassDefinition( Name name ) throws NamingException
579 {
580 throw new UnsupportedOperationException();
581 }
582
583
584
585
586
587 public DirContext getSchemaClassDefinition( String name ) throws NamingException
588 {
589 throw new UnsupportedOperationException();
590 }
591
592
593
594
595
596
597
598
599
600
601 public NamingEnumeration<SearchResult> search( String name, Attributes matchingAttributes ) throws NamingException
602 {
603 return search( new LdapDN( name ), matchingAttributes, null );
604 }
605
606
607
608
609
610
611 public NamingEnumeration<SearchResult> search( Name name, Attributes matchingAttributes ) throws NamingException
612 {
613 return search( name, AttributeUtils.toCaseInsensitive( matchingAttributes ), null );
614 }
615
616
617
618
619
620
621 public NamingEnumeration<SearchResult> search( String name, Attributes matchingAttributes,
622 String[] attributesToReturn ) throws NamingException
623 {
624 return search( new LdapDN( name ), AttributeUtils.toCaseInsensitive( matchingAttributes ), attributesToReturn );
625 }
626
627
628
629
630
631
632 public NamingEnumeration<SearchResult> search( Name name, Attributes matchingAttributes, String[] attributesToReturn )
633 throws NamingException
634 {
635 SearchControls ctls = new SearchControls();
636 LdapDN target = buildTarget( name );
637
638
639 if ( null != attributesToReturn )
640 {
641 ctls.setReturningAttributes( attributesToReturn );
642 }
643
644
645 matchingAttributes = AttributeUtils.toCaseInsensitive( matchingAttributes );
646
647 if ( ( null == matchingAttributes ) || ( matchingAttributes.size() <= 0 ) )
648 {
649 PresenceNode filter = new PresenceNode( SchemaConstants.OBJECT_CLASS_AT );
650 AliasDerefMode aliasDerefMode = AliasDerefMode.getEnum( getEnvironment() );
651 try
652 {
653 return new NamingEnumerationAdapter (
654 doSearchOperation( target, aliasDerefMode, filter, ctls ) );
655 }
656 catch ( Exception e )
657 {
658 JndiUtils.wrap( e );
659 }
660 }
661
662
663 if ( matchingAttributes.size() == 1 )
664 {
665 NamingEnumeration<? extends Attribute> list = matchingAttributes.getAll();
666 Attribute attr = list.next();
667 list.close();
668
669 if ( attr.size() == 1 )
670 {
671 Object value = attr.get();
672 SimpleNode<?> node;
673
674 if ( value instanceof byte[] )
675 {
676 node = new EqualityNode<byte[]>( attr.getID(), new ClientBinaryValue( ( byte[] ) value ) );
677 }
678 else
679 {
680 node = new EqualityNode<String>( attr.getID(), new ClientStringValue( ( String ) value ) );
681 }
682
683 AliasDerefMode aliasDerefMode = AliasDerefMode.getEnum( getEnvironment() );
684 try
685 {
686 return new NamingEnumerationAdapter (
687 doSearchOperation( target, aliasDerefMode, node, ctls ) );
688 }
689 catch ( Exception e )
690 {
691 JndiUtils.wrap( e );
692 return null;
693 }
694 }
695 }
696
697
698
699
700
701 Attribute attr;
702 SimpleNode node;
703 BranchNode filter = new AndNode();
704 NamingEnumeration<? extends Attribute> list = matchingAttributes.getAll();
705
706
707 while ( list.hasMore() )
708 {
709 attr = list.next();
710
711
712
713
714
715
716 if ( attr.size() == 0 )
717 {
718 filter.addNode( new PresenceNode( attr.getID() ) );
719 continue;
720 }
721
722
723
724
725
726 for ( int ii = 0; ii < attr.size(); ii++ )
727 {
728 Object val = attr.get( ii );
729
730
731 if ( val instanceof String )
732 {
733 node = new EqualityNode<String>( attr.getID(), new ClientStringValue( ( String ) val ) );
734 filter.addNode( node );
735 }
736 }
737 }
738
739 AliasDerefMode aliasDerefMode = AliasDerefMode.getEnum( getEnvironment() );
740 try
741 {
742 return new NamingEnumerationAdapter( doSearchOperation( target, aliasDerefMode, filter, ctls ) );
743 }
744 catch ( Exception e )
745 {
746 JndiUtils.wrap( e );
747 return null;
748 }
749 }
750
751
752
753
754
755
756 public NamingEnumeration<SearchResult> search( String name, String filter, SearchControls cons )
757 throws NamingException
758 {
759 return search( new LdapDN( name ), filter, cons );
760 }
761
762
763
764
765
766
767
768
769
770
771
772
773
774 public NamingEnumeration<SearchResult> search( Name name, ExprNode filter, SearchControls cons )
775 throws NamingException
776 {
777 LdapDN target = buildTarget( name );
778 AliasDerefMode aliasDerefMode = AliasDerefMode.getEnum( getEnvironment() );
779 try
780 {
781 return new NamingEnumerationAdapter( doSearchOperation( target, aliasDerefMode, filter, cons ) );
782 }
783 catch ( Exception e )
784 {
785 JndiUtils.wrap( e );
786 return null;
787 }
788 }
789
790
791
792
793
794
795 public NamingEnumeration<SearchResult> search( Name name, String filter, SearchControls cons )
796 throws NamingException
797 {
798 ExprNode filterNode;
799 LdapDN target = buildTarget( name );
800
801 try
802 {
803 filterNode = FilterParser.parse( filter );
804 }
805 catch ( ParseException pe )
806 {
807 InvalidSearchFilterException isfe = new InvalidSearchFilterException(
808 "Encountered parse exception while parsing the filter: '" + filter + "'" );
809 isfe.setRootCause( pe );
810 throw isfe;
811 }
812
813 AliasDerefMode aliasDerefMode = AliasDerefMode.getEnum( getEnvironment() );
814 try
815 {
816 return new NamingEnumerationAdapter( doSearchOperation( target, aliasDerefMode, filterNode, cons ) );
817 }
818 catch ( Exception e )
819 {
820 JndiUtils.wrap( e );
821 return null;
822 }
823 }
824
825
826
827
828
829
830
831 public NamingEnumeration<SearchResult> search( String name, String filterExpr, Object[] filterArgs,
832 SearchControls cons ) throws NamingException
833 {
834 return search( new LdapDN( name ), filterExpr, filterArgs, cons );
835 }
836
837
838
839
840
841
842
843 public NamingEnumeration<SearchResult> search( Name name, String filterExpr, Object[] filterArgs,
844 SearchControls cons ) throws NamingException
845 {
846 int start;
847 int index;
848
849 StringBuffer buf = new StringBuffer( filterExpr );
850
851
852 for ( int ii = 0; ii < buf.length(); ii++ )
853 {
854 try
855 {
856
857 while ( ii < buf.length() && '{' != buf.charAt( ii ) )
858 {
859 ii++;
860 }
861
862
863 start = ii;
864
865
866 while ( '}' != buf.charAt( ii ) )
867 {
868 ii++;
869 }
870 }
871 catch ( IndexOutOfBoundsException e )
872 {
873
874 break;
875 }
876
877
878 index = Integer.parseInt( buf.substring( start + 1, ii ) );
879
880 if ( filterArgs[index] instanceof String )
881 {
882
883
884
885
886 buf.replace( start, ii + 1, ( String ) filterArgs[index] );
887 }
888 else if ( filterArgs[index] instanceof byte[] )
889 {
890 String hexstr = "#" + StringTools.toHexString( ( byte[] ) filterArgs[index] );
891 buf.replace( start, ii + 1, hexstr );
892 }
893 else
894 {
895
896
897
898
899 buf.replace( start, ii + 1, filterArgs[index].toString() );
900 }
901 }
902
903 return search( name, buf.toString(), cons );
904 }
905
906
907
908
909
910
911
912 public void addNamingListener( Name name, String filterStr, SearchControls searchControls,
913 NamingListener namingListener ) throws NamingException
914 {
915 ExprNode filter;
916
917 try
918 {
919 filter = FilterParser.parse( filterStr );
920 }
921 catch ( Exception e )
922 {
923 NamingException e2 = new NamingException( "could not parse filter: " + filterStr );
924 e2.setRootCause( e );
925 throw e2;
926 }
927
928 try
929 {
930 DirectoryListener listener = new EventListenerAdapter( ( ServerLdapContext ) this, namingListener );
931 NotificationCriteria criteria = new NotificationCriteria();
932 criteria.setFilter( filter );
933 criteria.setScope( SearchScope.getSearchScope( searchControls ) );
934 criteria.setAliasDerefMode( AliasDerefMode.getEnum( getEnvironment() ) );
935 criteria.setBase( buildTarget( name ) );
936
937 getDirectoryService().getEventService().addListener( listener );
938 getListeners().put( namingListener, listener );
939 }
940 catch ( Exception e )
941 {
942 JndiUtils.wrap( e );
943 }
944 }
945
946
947 public void addNamingListener( String name, String filter, SearchControls searchControls,
948 NamingListener namingListener ) throws NamingException
949 {
950 addNamingListener( new LdapDN( name ), filter, searchControls, namingListener );
951 }
952
953
954 public void addNamingListener( Name name, String filterExpr, Object[] filterArgs, SearchControls searchControls,
955 NamingListener namingListener ) throws NamingException
956 {
957 int start;
958 StringBuffer buf = new StringBuffer( filterExpr );
959
960
961 for ( int ii = 0; ii < buf.length(); ii++ )
962 {
963
964 while ( '{' != buf.charAt( ii ) )
965 {
966 ii++;
967 }
968
969
970 start = ii;
971
972
973 while ( '}' != buf.charAt( ii ) )
974 {
975 ii++;
976 }
977
978
979
980
981
982 buf.replace( start, ii + 1, filterArgs[ii].toString() );
983 }
984
985 addNamingListener( name, buf.toString(), searchControls, namingListener );
986 }
987
988
989 public void addNamingListener( String name, String filter, Object[] objects, SearchControls searchControls,
990 NamingListener namingListener ) throws NamingException
991 {
992 addNamingListener( new LdapDN( name ), filter, objects, searchControls, namingListener );
993 }
994 }