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