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