1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.ldap.server.jndi;
18
19
20 import java.io.IOException;
21 import java.io.Serializable;
22 import java.text.ParseException;
23 import java.util.Hashtable;
24
25 import javax.naming.Name;
26 import javax.naming.NamingEnumeration;
27 import javax.naming.NamingException;
28 import javax.naming.Reference;
29 import javax.naming.Referenceable;
30 import javax.naming.directory.Attribute;
31 import javax.naming.directory.Attributes;
32 import javax.naming.directory.DirContext;
33 import javax.naming.directory.InvalidSearchFilterException;
34 import javax.naming.directory.ModificationItem;
35 import javax.naming.directory.SearchControls;
36 import javax.naming.event.EventDirContext;
37 import javax.naming.event.NamingListener;
38 import javax.naming.ldap.Control;
39 import javax.naming.spi.DirStateFactory;
40 import javax.naming.spi.DirectoryManager;
41
42 import org.apache.ldap.common.filter.BranchNode;
43 import org.apache.ldap.common.filter.ExprNode;
44 import org.apache.ldap.common.filter.FilterParserImpl;
45 import org.apache.ldap.common.filter.PresenceNode;
46 import org.apache.ldap.common.filter.SimpleNode;
47 import org.apache.ldap.common.name.LdapName;
48 import org.apache.ldap.common.util.NamespaceTools;
49 import org.apache.ldap.server.DirectoryService;
50 import org.apache.ldap.server.authn.LdapPrincipal;
51 import org.apache.ldap.server.partition.DirectoryPartitionNexus;
52 import org.apache.ldap.server.partition.DirectoryPartitionNexusProxy;
53
54
55 /***
56 * The DirContext implementation for the Server Side JNDI LDAP provider.
57 *
58 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
59 * @version $Rev: 326410 $
60 */
61 public abstract class ServerDirContext extends ServerContext implements EventDirContext
62 {
63
64
65
66
67
68 /***
69 * Creates a new ServerDirContext by reading the PROVIDER_URL to resolve the
70 * distinguished name for this context.
71 *
72 * @param service the parent service that manages this context
73 * @param env the environment used for this context
74 * @throws NamingException if something goes wrong
75 */
76 public ServerDirContext( DirectoryService service, Hashtable env ) throws NamingException
77 {
78 super( service, env );
79 }
80
81
82 /***
83 * Creates a new ServerDirContext with a distinguished name which is used to
84 * set the PROVIDER_URL to the distinguished name for this context.
85 *
86 * @param principal the principal which is propagated
87 * @param nexusProxy the intercepting proxy to the nexus
88 * @param env the environment properties used by this context
89 * @param dn the distinguished name of this context
90 */
91 protected ServerDirContext( LdapPrincipal principal, DirectoryPartitionNexus nexusProxy, Hashtable env, Name dn )
92 {
93 super( principal, nexusProxy, env, dn );
94 }
95
96
97
98
99
100
101
102 /***
103 * @see javax.naming.directory.DirContext#getAttributes(java.lang.String)
104 */
105 public Attributes getAttributes( String name ) throws NamingException
106 {
107 return getAttributes( new LdapName( name ) );
108 }
109
110
111 /***
112 * @see javax.naming.directory.DirContext#getAttributes(javax.naming.Name)
113 */
114 public Attributes getAttributes( Name name ) throws NamingException
115 {
116 return getNexusProxy().lookup( buildTarget( name ) );
117 }
118
119
120 /***
121 * @see javax.naming.directory.DirContext#getAttributes(java.lang.String,
122 * java.lang.String[])
123 */
124 public Attributes getAttributes( String name, String[] attrIds ) throws NamingException
125 {
126 return getAttributes( new LdapName( name ), attrIds );
127 }
128
129
130 /***
131 * @see javax.naming.directory.DirContext#getAttributes(javax.naming.Name,
132 * java.lang.String[])
133 */
134 public Attributes getAttributes( Name name, String[] attrIds ) throws NamingException
135 {
136 return getNexusProxy().lookup( buildTarget( name ), attrIds );
137 }
138
139
140 /***
141 * @see javax.naming.directory.DirContext#modifyAttributes(java.lang.String,
142 * int, javax.naming.directory.Attributes)
143 */
144 public void modifyAttributes( String name, int modOp, Attributes attrs ) throws NamingException
145 {
146 modifyAttributes( new LdapName( name ), modOp, attrs );
147 }
148
149
150 /***
151 * @see javax.naming.directory.DirContext#modifyAttributes(
152 * javax.naming.Name,int, javax.naming.directory.Attributes)
153 */
154 public void modifyAttributes( Name name, int modOp, Attributes attrs ) throws NamingException
155 {
156 getNexusProxy().modify( buildTarget( name ), modOp, attrs );
157 }
158
159
160 /***
161 * @see javax.naming.directory.DirContext#modifyAttributes(java.lang.String,
162 * javax.naming.directory.ModificationItem[])
163 */
164 public void modifyAttributes( String name, ModificationItem[] mods ) throws NamingException
165 {
166 modifyAttributes( new LdapName( name ), mods );
167 }
168
169
170 /***
171 * @see javax.naming.directory.DirContext#modifyAttributes(
172 * javax.naming.Name, javax.naming.directory.ModificationItem[])
173 */
174 public void modifyAttributes( Name name, ModificationItem[] mods ) throws NamingException
175 {
176 getNexusProxy().modify( buildTarget( name ), mods );
177 }
178
179
180 /***
181 * @see javax.naming.directory.DirContext#bind(java.lang.String,
182 * java.lang.Object, javax.naming.directory.Attributes)
183 */
184 public void bind( String name, Object obj, Attributes attrs ) throws NamingException
185 {
186 bind( new LdapName( name ), obj, attrs );
187 }
188
189
190 /***
191 * @see javax.naming.directory.DirContext#bind(javax.naming.Name,
192 * java.lang.Object, javax.naming.directory.Attributes)
193 */
194 public void bind( Name name, Object obj, Attributes attrs ) throws NamingException
195 {
196 if ( null == obj && null == attrs )
197 {
198 throw new NamingException( "Both obj and attrs args are null. "
199 + "At least one of these parameters must not be null." );
200 }
201
202
203 if ( null == attrs )
204 {
205 super.bind( name, obj );
206
207 return;
208 }
209
210
211 if ( null == obj )
212 {
213 Attributes clone = ( Attributes ) attrs.clone();
214
215 Name target = buildTarget( name );
216
217 getNexusProxy().add( target.toString(), target, clone );
218
219 return;
220 }
221
222
223 DirStateFactory.Result res = DirectoryManager.getStateToBind( obj, name, this, getEnvironment(), attrs );
224
225 Attributes outAttrs = res.getAttributes();
226
227 if ( outAttrs != attrs )
228 {
229 Name target = buildTarget( name );
230
231 Attributes attributes = ( Attributes ) attrs.clone();
232
233 if ( outAttrs != null && outAttrs.size() > 0 )
234 {
235 NamingEnumeration list = outAttrs.getAll();
236
237 while ( list.hasMore() )
238 {
239 attributes.put( ( Attribute ) list.next() );
240 }
241 }
242
243 getNexusProxy().add( target.toString(), target, attributes );
244
245 return;
246 }
247
248
249 if ( obj instanceof Referenceable )
250 {
251 obj = ( ( Referenceable ) obj ).getReference();
252
253 throw new NamingException( "Do not know how to store Referenceables yet!" );
254 }
255
256
257 if ( obj instanceof Reference )
258 {
259
260
261 throw new NamingException( "Do not know how to store References yet!" );
262 }
263 else if ( obj instanceof Serializable )
264 {
265
266
267 Attributes attributes = ( Attributes ) attrs.clone();
268
269 if ( outAttrs != null && outAttrs.size() > 0 )
270 {
271 NamingEnumeration list = outAttrs.getAll();
272
273 while ( list.hasMore() )
274 {
275 attributes.put( ( Attribute ) list.next() );
276 }
277 }
278
279 Name target = buildTarget( name );
280
281
282
283 JavaLdapSupport.serialize( attributes, obj );
284
285 getNexusProxy().add( target.toString(), target, attributes );
286 }
287 else if ( obj instanceof DirContext )
288 {
289
290
291 Attributes attributes = ( ( DirContext ) obj ).getAttributes( "" );
292
293 if ( outAttrs != null && outAttrs.size() > 0 )
294 {
295 NamingEnumeration list = outAttrs.getAll();
296
297 while ( list.hasMore() )
298 {
299 attributes.put( ( Attribute ) list.next() );
300 }
301 }
302
303 Name target = buildTarget( name );
304
305 getNexusProxy().add( target.toString(), target, attributes );
306 }
307 else
308 {
309 throw new NamingException( "Can't find a way to bind: " + obj );
310 }
311 }
312
313
314 /***
315 * @see javax.naming.directory.DirContext#rebind(java.lang.String,
316 * java.lang.Object, javax.naming.directory.Attributes)
317 */
318 public void rebind( String name, Object obj, Attributes attrs ) throws NamingException
319 {
320 rebind( new LdapName( name ), obj, attrs );
321 }
322
323
324 /***
325 * @see javax.naming.directory.DirContext#rebind(javax.naming.Name,
326 * java.lang.Object, javax.naming.directory.Attributes)
327 */
328 public void rebind( Name name, Object obj, Attributes attrs ) throws NamingException
329 {
330 Name target = buildTarget( name );
331
332 if ( getNexusProxy().hasEntry( target ) )
333 {
334 getNexusProxy().delete( target );
335 }
336
337 bind( name, obj, attrs );
338 }
339
340
341 /***
342 * @see javax.naming.directory.DirContext#createSubcontext(java.lang.String,
343 * javax.naming.directory.Attributes)
344 */
345 public DirContext createSubcontext( String name, Attributes attrs ) throws NamingException
346 {
347 return createSubcontext( new LdapName( name ), attrs );
348 }
349
350
351 /***
352 * @see javax.naming.directory.DirContext#createSubcontext(
353 * javax.naming.Name, javax.naming.directory.Attributes)
354 */
355 public DirContext createSubcontext( Name name, Attributes attrs ) throws NamingException
356 {
357 if ( null == attrs )
358 {
359 return ( DirContext ) super.createSubcontext( name );
360 }
361
362 LdapName target = buildTarget( name );
363
364 String rdn = name.get( name.size() - 1 );
365
366 String rdnAttribute = NamespaceTools.getRdnAttribute( rdn );
367
368 String rdnValue = NamespaceTools.getRdnValue( rdn );
369
370
371 Attributes attributes = ( Attributes ) attrs.clone();
372
373 boolean doRdnPut = attributes.get( rdnAttribute ) == null;
374
375 doRdnPut = doRdnPut || attributes.get( rdnAttribute ).size() == 0;
376
377 doRdnPut = doRdnPut || ! attributes.get( rdnAttribute ).contains( rdnValue );
378
379 if ( doRdnPut )
380 {
381 attributes.put( rdnAttribute, rdnValue );
382 }
383
384
385 getNexusProxy().add( target.toString(), target, attributes );
386
387
388 ServerLdapContext ctx = new ServerLdapContext( getPrincipal(), getNexusProxy(), getEnvironment(), target );
389
390 Control [] controls = ( ( ServerLdapContext ) this ).getRequestControls();
391
392 if ( controls != null )
393 {
394 controls = ( Control[] ) controls.clone();
395 }
396 else
397 {
398 controls = new Control[0];
399 }
400
401 ctx.setRequestControls( controls );
402
403 return ctx;
404 }
405
406
407 /***
408 * Presently unsupported operation!
409 */
410 public DirContext getSchema( Name name ) throws NamingException
411 {
412 throw new UnsupportedOperationException();
413 }
414
415
416 /***
417 * Presently unsupported operation!
418 */
419 public DirContext getSchema( String name ) throws NamingException
420 {
421 throw new UnsupportedOperationException();
422 }
423
424
425 /***
426 * Presently unsupported operation!
427 */
428 public DirContext getSchemaClassDefinition( Name name ) throws NamingException
429 {
430 throw new UnsupportedOperationException();
431 }
432
433
434 /***
435 * Presently unsupported operation!
436 */
437 public DirContext getSchemaClassDefinition( String name ) throws NamingException
438 {
439 throw new UnsupportedOperationException();
440 }
441
442
443
444
445
446
447
448 /***
449 * @see javax.naming.directory.DirContext#search(java.lang.String,
450 * javax.naming.directory.Attributes)
451 */
452 public NamingEnumeration search( String name, Attributes matchingAttributes )
453 throws NamingException
454 {
455 return search( new LdapName( name ), matchingAttributes, null );
456 }
457
458
459 /***
460 * @see javax.naming.directory.DirContext#search(javax.naming.Name,
461 * javax.naming.directory.Attributes)
462 */
463 public NamingEnumeration search( Name name, Attributes matchingAttributes )
464 throws NamingException
465 {
466 return search( name, matchingAttributes, null );
467 }
468
469
470 /***
471 * @see javax.naming.directory.DirContext#search(java.lang.String,
472 * javax.naming.directory.Attributes, java.lang.String[])
473 */
474 public NamingEnumeration search( String name, Attributes matchingAttributes, String[] attributesToReturn ) throws NamingException
475 {
476 return search( new LdapName( name ), matchingAttributes, attributesToReturn );
477 }
478
479
480 /***
481 * @see javax.naming.directory.DirContext#search(javax.naming.Name,
482 * javax.naming.directory.Attributes, java.lang.String[])
483 */
484 public NamingEnumeration search( Name name, Attributes matchingAttributes, String[] attributesToReturn ) throws NamingException
485 {
486 SearchControls ctls = new SearchControls();
487
488 LdapName target = buildTarget( name );
489
490
491 if ( null != attributesToReturn )
492 {
493 ctls.setReturningAttributes( attributesToReturn );
494 }
495
496
497 if ( null == matchingAttributes || matchingAttributes.size() <= 0 )
498 {
499 PresenceNode filter = new PresenceNode( "objectClass" );
500
501 return getNexusProxy().search( target , getEnvironment(), filter, ctls );
502 }
503
504
505
506
507
508 Attribute attr;
509 SimpleNode node;
510 BranchNode filter = new BranchNode( BranchNode.AND );
511 NamingEnumeration list = matchingAttributes.getAll();
512
513
514 while ( list.hasMore() )
515 {
516 attr = ( Attribute ) list.next();
517
518
519
520
521
522
523 if ( attr.size() == 0 )
524 {
525 filter.addNode( new PresenceNode( attr.getID() ) );
526
527 continue;
528 }
529
530
531
532
533
534 for ( int ii = 0; ii < attr.size(); ii++ )
535 {
536 Object val = attr.get( ii );
537
538
539 if ( val instanceof String )
540 {
541 node = new SimpleNode( attr.getID(), ( String ) val, SimpleNode.EQUALITY );
542
543 filter.addNode( node );
544 }
545 }
546 }
547
548 return getNexusProxy().search( target , getEnvironment(), filter, ctls );
549 }
550
551
552 /***
553 * @see javax.naming.directory.DirContext#search(java.lang.String,
554 * java.lang.String, javax.naming.directory.SearchControls)
555 */
556 public NamingEnumeration search( String name, String filter, SearchControls cons )
557 throws NamingException
558 {
559 return search( new LdapName( name ), filter, cons );
560 }
561
562
563 /***
564 * A search overload that is used for optimizing search handling in the
565 * LDAP protocol provider which deals with an ExprNode instance rather than
566 * a String for the filter.
567 *
568 * @param name the relative name of the object serving as the search base
569 * @param filter the search filter as an expression tree
570 * @param cons the search controls to use
571 * @return an enumeration over the SearchResults
572 * @throws NamingException if there are problems performing the search
573 */
574 public NamingEnumeration search( Name name, ExprNode filter, SearchControls cons ) throws NamingException
575 {
576 LdapName target = buildTarget( name );
577 return getNexusProxy().search( target, getEnvironment(), filter, cons );
578 }
579
580
581 /***
582 * @see javax.naming.directory.DirContext#search(javax.naming.Name,
583 * java.lang.String, javax.naming.directory.SearchControls)
584 */
585 public NamingEnumeration search( Name name, String filter, SearchControls cons )
586 throws NamingException
587 {
588 ExprNode filterNode;
589
590 LdapName target = buildTarget( name );
591
592 try
593 {
594 filterNode = filterParser.parse( filter );
595 }
596 catch ( ParseException pe )
597 {
598 InvalidSearchFilterException isfe =
599 new InvalidSearchFilterException (
600 "Encountered parse exception while parsing the filter: '"
601 + filter + "'" );
602
603 isfe.setRootCause( pe );
604
605 throw isfe;
606 }
607 catch ( IOException ioe )
608 {
609 NamingException ne = new NamingException(
610 "Parser failed with IO exception on filter: '"
611 + filter + "'" );
612 ne.setRootCause( ioe );
613 throw ne;
614 }
615
616 return getNexusProxy().search( target , getEnvironment(), filterNode, cons );
617 }
618
619
620 /***
621 * @see javax.naming.directory.DirContext#search(java.lang.String,
622 * java.lang.String, java.lang.Object[],
623 * javax.naming.directory.SearchControls)
624 */
625 public NamingEnumeration search( String name, String filterExpr,
626 Object[] filterArgs, SearchControls cons ) throws NamingException
627 {
628 return search( new LdapName( name ), filterExpr, filterArgs, cons );
629 }
630
631
632 /***
633 * @see javax.naming.directory.DirContext#search(javax.naming.Name,
634 * java.lang.String, java.lang.Object[],
635 * javax.naming.directory.SearchControls)
636 */
637 public NamingEnumeration search( Name name, String filterExpr, Object[] filterArgs, SearchControls cons ) throws NamingException
638 {
639 int start;
640 int index;
641
642 StringBuffer buf = new StringBuffer( filterExpr );
643
644
645 for ( int ii = 0; ii < buf.length(); ii++ )
646 {
647 try
648 {
649
650 while ( ii < buf.length() && '{' != buf.charAt( ii ) )
651 {
652 ii++;
653 }
654
655
656 start = ii;
657
658
659 while ( '}' != buf.charAt( ii ) )
660 {
661 ii++;
662 }
663 }
664 catch (IndexOutOfBoundsException e)
665 {
666
667 break;
668 }
669
670
671 index = Integer.parseInt(buf.substring(start + 1, ii));
672
673
674
675
676
677 buf.replace( start, ii + 1, filterArgs[index].toString() );
678 }
679
680 return search( name, buf.toString(), cons );
681 }
682
683
684
685
686
687
688
689 FilterParserImpl filterParser = new FilterParserImpl();
690
691 public void addNamingListener( Name name, String filterStr, SearchControls searchControls,
692 NamingListener namingListener )
693 throws NamingException
694 {
695 ExprNode filter;
696
697 try
698 {
699 filter = filterParser.parse( filterStr );
700 }
701 catch ( Exception e )
702 {
703 NamingException e2 = new NamingException( "could not parse filter: " + filterStr );
704 e2.setRootCause( e );
705 throw e2;
706 }
707
708 ( ( DirectoryPartitionNexusProxy ) getNexusProxy() )
709 .addNamingListener( this, buildTarget( name ), filter, searchControls, namingListener );
710 getListeners().add( namingListener );
711 }
712
713
714 public void addNamingListener( String name, String filter, SearchControls searchControls, NamingListener namingListener )
715 throws NamingException
716 {
717 addNamingListener( new LdapName( name ), filter, searchControls, namingListener );
718 }
719
720
721 public void addNamingListener( Name name, String filterExpr, Object[] filterArgs, SearchControls searchControls,
722 NamingListener namingListener ) throws NamingException
723 {
724 int start;
725
726 StringBuffer buf = new StringBuffer( filterExpr );
727
728
729 for ( int ii = 0; ii < buf.length(); ii++ )
730 {
731
732 while ( '{' != buf.charAt( ii ) )
733 {
734 ii++;
735 }
736
737
738 start = ii;
739
740
741 while ( '}' != buf.charAt( ii ) )
742 {
743 ii++;
744 }
745
746
747
748
749
750 buf.replace( start, ii + 1, filterArgs[ii].toString() );
751 }
752
753 addNamingListener( name, buf.toString(), searchControls, namingListener );
754 }
755
756
757 public void addNamingListener( String name, String filter, Object[] objects, SearchControls searchControls,
758 NamingListener namingListener ) throws NamingException
759 {
760 addNamingListener( new LdapName( name ), filter, objects, searchControls, namingListener );
761 }
762 }