1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.ldap.server.partition;
18
19
20 import java.util.*;
21
22 import javax.naming.Context;
23 import javax.naming.Name;
24 import javax.naming.NamingEnumeration;
25 import javax.naming.NamingException;
26 import javax.naming.ServiceUnavailableException;
27 import javax.naming.directory.Attributes;
28 import javax.naming.directory.ModificationItem;
29 import javax.naming.directory.SearchControls;
30 import javax.naming.directory.DirContext;
31 import javax.naming.event.EventContext;
32 import javax.naming.event.NamingListener;
33 import javax.naming.ldap.LdapContext;
34
35 import org.apache.ldap.common.filter.ExprNode;
36 import org.apache.ldap.server.DirectoryServiceConfiguration;
37 import org.apache.ldap.server.DirectoryService;
38 import org.apache.ldap.server.configuration.DirectoryPartitionConfiguration;
39 import org.apache.ldap.server.event.EventService;
40 import org.apache.ldap.server.interceptor.InterceptorChain;
41 import org.apache.ldap.server.invocation.Invocation;
42 import org.apache.ldap.server.invocation.InvocationStack;
43
44
45 /***
46 * A decorator that wraps other {@link DirectoryPartitionNexus} to enable
47 * {@link InterceptorChain} and {@link InvocationStack} support.
48 * All {@link Invocation}s made to this nexus is automatically pushed to
49 * {@link InvocationStack} of the current thread, and popped when
50 * the operation ends. All invocations are filtered by {@link InterceptorChain}.
51 *
52 * @author The Apache Directory Project
53 * @version $Rev: 326825 $, $Date: 2005-10-20 01:09:43 -0400 (Thu, 20 Oct 2005) $
54 */
55 public class DirectoryPartitionNexusProxy extends DirectoryPartitionNexus
56 {
57 /*** safe to use set of bypass instructions to lookup raw entries */
58 public static final Collection LOOKUP_BYPASS;
59 /*** safe to use set of bypass instructions to getMatchedDn */
60 public static final Collection GETMATCHEDDN_BYPASS;
61 /*** Bypass String to use when ALL interceptors should be skipped */
62 public static final String BYPASS_ALL = "*";
63 /*** Bypass String to use when ALL interceptors should be skipped */
64 public static final Collection BYPASS_ALL_COLLECTION = Collections.singleton( BYPASS_ALL );
65 /*** Integer const for DirContext.ADD_ATTRIBUTE */
66 private static final Integer ADD_MODOP = new Integer( DirContext.ADD_ATTRIBUTE );
67 /*** Integer const for DirContext.REMOVE_ATTRIBUTE */
68 private static final Integer REMOVE_MODOP = new Integer( DirContext.REMOVE_ATTRIBUTE );
69 /*** Integer const for DirContext.REPLACE_ATTRIBUTE */
70 private static final Integer REPLACE_MODOP = new Integer( DirContext.REPLACE_ATTRIBUTE );
71
72 private final Context caller;
73 private final DirectoryService service;
74 private final DirectoryServiceConfiguration configuration;
75
76
77 static
78 {
79 Collection c = new HashSet();
80 c.add( "normalizationService" );
81 c.add( "authenticationService" );
82 c.add( "authorizationService" );
83 c.add( "oldAuthorizationService" );
84 c.add( "schemaService" );
85 c.add( "subentryService" );
86 c.add( "operationalAttributeService" );
87 c.add( "eventService" );
88 LOOKUP_BYPASS = Collections.unmodifiableCollection( c );
89
90 c = new HashSet();
91 c.add( "authenticationService" );
92 c.add( "authorizationService" );
93 c.add( "oldAuthorizationService" );
94 c.add( "schemaService" );
95 c.add( "subentryService" );
96 c.add( "operationalAttributeService" );
97 c.add( "eventService" );
98 GETMATCHEDDN_BYPASS = Collections.unmodifiableCollection( c );
99 }
100
101
102 /***
103 * Creates a new instance.
104 *
105 * @param caller a JNDI {@link Context} object that will call this proxy
106 * @param service a JNDI service
107 */
108 public DirectoryPartitionNexusProxy( Context caller, DirectoryService service )
109 {
110 this.caller = caller;
111 this.service = service;
112 this.configuration = service.getConfiguration();
113 }
114
115 public LdapContext getLdapContext() {
116 return this.configuration.getPartitionNexus().getLdapContext();
117 }
118
119 public void init( DirectoryServiceConfiguration factoryCfg, DirectoryPartitionConfiguration cfg )
120 {
121 }
122
123 public void destroy()
124 {
125 }
126
127 public DirectoryPartition getSystemPartition()
128 {
129 return this.configuration.getPartitionNexus().getSystemPartition();
130 }
131
132 public Name getSuffix( boolean normalized ) throws NamingException
133 {
134 return this.configuration.getPartitionNexus().getSuffix( normalized );
135 }
136
137 public void sync() throws NamingException {
138 this.service.sync();
139 }
140
141 public void close() throws NamingException {
142 this.service.shutdown();
143 }
144
145 public boolean isInitialized() {
146 return this.service.isStarted();
147 }
148
149
150 public Name getMatchedName( Name dn, boolean normalized ) throws NamingException
151 {
152 return getMatchedName( dn, normalized, null );
153 }
154
155
156 public Name getMatchedName( Name dn, boolean normalized, Collection bypass ) throws NamingException
157 {
158 ensureStarted();
159 InvocationStack stack = InvocationStack.getInstance();
160 Object[] args = new Object[] { dn, normalized? Boolean.TRUE : Boolean.FALSE };
161 stack.push( new Invocation( this, caller, "getMatchedDn", args, bypass ) );
162 try
163 {
164 return this.configuration.getInterceptorChain().getMatchedName( dn, normalized );
165 }
166 finally
167 {
168 stack.pop();
169 }
170 }
171
172
173 public Name getSuffix( Name dn, boolean normalized) throws NamingException
174 {
175 return getSuffix( dn, normalized, null );
176 }
177
178
179 public Name getSuffix( Name dn, boolean normalized, Collection bypass ) throws NamingException
180 {
181 ensureStarted();
182 InvocationStack stack = InvocationStack.getInstance();
183 Object[] args = new Object[] { dn, normalized? Boolean.TRUE : Boolean.FALSE };
184 stack.push( new Invocation( this, caller, "getSuffix", args, bypass ) );
185 try
186 {
187 return this.configuration.getInterceptorChain().getSuffix( dn, normalized );
188 }
189 finally
190 {
191 stack.pop();
192 }
193 }
194
195
196 public Iterator listSuffixes( boolean normalized ) throws NamingException
197 {
198 return listSuffixes( normalized, null );
199 }
200
201
202 public Iterator listSuffixes( boolean normalized, Collection bypass ) throws NamingException
203 {
204 ensureStarted();
205 InvocationStack stack = InvocationStack.getInstance();
206 Object[] args = new Object[] { normalized? Boolean.TRUE : Boolean.FALSE };
207 stack.push( new Invocation( this, caller, "listSuffixes", args, bypass ) );
208 try
209 {
210 return this.configuration.getInterceptorChain().listSuffixes( normalized );
211 }
212 finally
213 {
214 stack.pop();
215 }
216 }
217
218
219 public boolean compare( Name name, String oid, Object value ) throws NamingException
220 {
221 return compare( name, oid, value, null );
222 }
223
224
225 public boolean compare( Name name, String oid, Object value, Collection bypass ) throws NamingException
226 {
227 ensureStarted();
228 InvocationStack stack = InvocationStack.getInstance();
229 stack.push( new Invocation( this, caller, "compare", new Object[] { name, oid, value }, bypass ) );
230 try
231 {
232 return this.configuration.getInterceptorChain().compare( name, oid, value );
233 }
234 finally
235 {
236 stack.pop();
237 }
238 }
239
240
241 public void delete( Name name ) throws NamingException
242 {
243 delete( name, null );
244 }
245
246
247 public void delete( Name name, Collection bypass ) throws NamingException
248 {
249 ensureStarted();
250 InvocationStack stack = InvocationStack.getInstance();
251 stack.push( new Invocation( this, caller, "delete", new Object[] { name }, bypass ) );
252 try
253 {
254 this.configuration.getInterceptorChain().delete( name );
255 }
256 finally
257 {
258 stack.pop();
259 }
260 }
261
262
263 public void add( String upName, Name normName, Attributes entry ) throws NamingException
264 {
265 add( upName, normName, entry, null );
266 }
267
268
269 public void add( String upName, Name normName, Attributes entry, Collection bypass ) throws NamingException
270 {
271 ensureStarted();
272 InvocationStack stack = InvocationStack.getInstance();
273 stack.push( new Invocation( this, caller, "add", new Object[] { upName, normName, entry }, bypass ) );
274 try
275 {
276 this.configuration.getInterceptorChain().add( upName, normName, entry );
277 }
278 finally
279 {
280 stack.pop();
281 }
282 }
283
284
285 public void modify( Name name, int modOp, Attributes mods ) throws NamingException
286 {
287 modify( name, modOp, mods, null );
288 }
289
290
291 public void modify( Name name, int modOp, Attributes mods, Collection bypass ) throws NamingException
292 {
293 ensureStarted();
294 InvocationStack stack = InvocationStack.getInstance();
295 Integer modOpObj;
296
297 switch( modOp )
298 {
299 case( DirContext.ADD_ATTRIBUTE ):
300 modOpObj = ADD_MODOP;
301 break;
302 case( DirContext.REMOVE_ATTRIBUTE ):
303 modOpObj = REMOVE_MODOP;
304 break;
305 case( DirContext.REPLACE_ATTRIBUTE ):
306 modOpObj = REPLACE_MODOP;
307 break;
308 default:
309 throw new IllegalArgumentException( "bad modification operation value: " + modOp );
310 }
311
312 stack.push( new Invocation( this, caller, "modify", new Object[] { name, modOpObj, mods }, bypass ) );
313 try
314 {
315 this.configuration.getInterceptorChain().modify( name, modOp, mods );
316 }
317 finally
318 {
319 stack.pop();
320 }
321 }
322
323
324 public void modify( Name name, ModificationItem[] mods ) throws NamingException
325 {
326 modify( name, mods, null );
327 }
328
329
330 public void modify( Name name, ModificationItem[] mods, Collection bypass ) throws NamingException
331 {
332 ensureStarted();
333 InvocationStack stack = InvocationStack.getInstance();
334 stack.push( new Invocation( this, caller, "modify", new Object[] { name, mods }, bypass ) );
335 try
336 {
337 this.configuration.getInterceptorChain().modify( name, mods );
338 }
339 finally
340 {
341 stack.pop();
342 }
343 }
344
345
346 public NamingEnumeration list( Name base ) throws NamingException
347 {
348 return list( base, null );
349 }
350
351
352 public NamingEnumeration list( Name base, Collection bypass ) throws NamingException
353 {
354 ensureStarted();
355 InvocationStack stack = InvocationStack.getInstance();
356 stack.push( new Invocation( this, caller, "list", new Object[] { base }, bypass ) );
357 try
358 {
359 return this.configuration.getInterceptorChain().list( base );
360 }
361 finally
362 {
363 stack.pop();
364 }
365 }
366
367
368 public NamingEnumeration search( Name base, Map env, ExprNode filter, SearchControls searchCtls )
369 throws NamingException
370 {
371 return search( base, env, filter, searchCtls, null );
372 }
373
374
375 public NamingEnumeration search( Name base, Map env, ExprNode filter, SearchControls searchCtls, Collection bypass )
376 throws NamingException
377 {
378 ensureStarted();
379 InvocationStack stack = InvocationStack.getInstance();
380 stack.push( new Invocation( this, caller, "search", new Object[] { base, env, filter, searchCtls }, bypass ) );
381 try
382 {
383 return this.configuration.getInterceptorChain().search( base, env, filter, searchCtls );
384 }
385 finally
386 {
387 stack.pop();
388 }
389 }
390
391
392 public Attributes lookup( Name name ) throws NamingException
393 {
394 return lookup( name, ( Collection ) null );
395 }
396
397
398 public Attributes lookup( Name name, Collection bypass ) throws NamingException
399 {
400 ensureStarted();
401 InvocationStack stack = InvocationStack.getInstance();
402 stack.push( new Invocation( this, caller, "lookup", new Object[] { name }, bypass ) );
403 try
404 {
405 return this.configuration.getInterceptorChain().lookup( name );
406 }
407 finally
408 {
409 stack.pop();
410 }
411 }
412
413
414 public Attributes lookup( Name dn, String[] attrIds ) throws NamingException
415 {
416 return lookup( dn, attrIds, null );
417 }
418
419
420 public Attributes lookup( Name dn, String[] attrIds, Collection bypass ) throws NamingException
421 {
422 ensureStarted();
423 InvocationStack stack = InvocationStack.getInstance();
424 stack.push( new Invocation( this, caller, "lookup", new Object[] { dn, attrIds }, bypass ) );
425 try
426 {
427 return this.configuration.getInterceptorChain().lookup( dn, attrIds );
428 }
429 finally
430 {
431 stack.pop();
432 }
433 }
434
435
436 public boolean hasEntry( Name name ) throws NamingException
437 {
438 return hasEntry( name, null );
439 }
440
441
442 public boolean hasEntry( Name name, Collection bypass ) throws NamingException
443 {
444 ensureStarted();
445 InvocationStack stack = InvocationStack.getInstance();
446 stack.push( new Invocation( this, caller, "hasEntry", new Object[] { name }, bypass ) );
447 try
448 {
449 return this.configuration.getInterceptorChain().hasEntry( name );
450 }
451 finally
452 {
453 stack.pop();
454 }
455 }
456
457
458 public boolean isSuffix( Name name ) throws NamingException
459 {
460 return isSuffix( name, null );
461 }
462
463
464 public boolean isSuffix( Name name, Collection bypass ) throws NamingException
465 {
466 ensureStarted();
467 InvocationStack stack = InvocationStack.getInstance();
468 stack.push( new Invocation( this, caller, "isSuffix", new Object[] { name }, bypass ) );
469 try
470 {
471 return this.configuration.getInterceptorChain().isSuffix( name );
472 }
473 finally
474 {
475 stack.pop();
476 }
477 }
478
479
480 public void modifyRn( Name name, String newRn, boolean deleteOldRn ) throws NamingException
481 {
482 modifyRn( name, newRn, deleteOldRn, null );
483 }
484
485
486 public void modifyRn( Name name, String newRn, boolean deleteOldRn, Collection bypass ) throws NamingException
487 {
488 ensureStarted();
489 InvocationStack stack = InvocationStack.getInstance();
490 Object[] args = new Object[] { name, newRn, deleteOldRn? Boolean.TRUE : Boolean.FALSE };
491 stack.push( new Invocation( this, caller, "modifyRn", args, bypass ) );
492 try
493 {
494 this.configuration.getInterceptorChain().modifyRn( name, newRn, deleteOldRn );
495 }
496 finally
497 {
498 stack.pop();
499 }
500 }
501
502
503 public void move( Name oriChildName, Name newParentName ) throws NamingException
504 {
505 move( oriChildName, newParentName, null );
506 }
507
508
509 public void move( Name oriChildName, Name newParentName, Collection bypass ) throws NamingException
510 {
511 ensureStarted();
512 InvocationStack stack = InvocationStack.getInstance();
513 stack.push( new Invocation( this, caller, "move", new Object[] { oriChildName, newParentName }, bypass ) );
514 try
515 {
516 this.configuration.getInterceptorChain().move( oriChildName, newParentName );
517 }
518 finally
519 {
520 stack.pop();
521 }
522 }
523
524
525 public void move( Name oriChildName, Name newParentName, String newRn, boolean deleteOldRn ) throws NamingException
526 {
527 move( oriChildName, newParentName, newRn, deleteOldRn, null );
528 }
529
530
531 public void move( Name oriChildName, Name newParentName, String newRn, boolean deleteOldRn, Collection bypass )
532 throws NamingException
533 {
534 ensureStarted();
535 InvocationStack stack = InvocationStack.getInstance();
536 Object[] args = new Object[] { oriChildName, newParentName, newRn, deleteOldRn? Boolean.TRUE : Boolean.FALSE };
537 stack.push( new Invocation( this, caller, "move", args, bypass ) );
538 try
539 {
540 this.configuration.getInterceptorChain().move( oriChildName, newParentName, newRn, deleteOldRn );
541 }
542 finally
543 {
544 stack.pop();
545 }
546 }
547
548
549 public Attributes getRootDSE() throws NamingException
550 {
551 return getRootDSE( null );
552 }
553
554
555 public Attributes getRootDSE( Collection bypass ) throws NamingException
556 {
557 ensureStarted();
558 InvocationStack stack = InvocationStack.getInstance();
559 stack.push( new Invocation( this, caller, "getRootDSE", null, bypass ) );
560 try
561 {
562 return this.configuration.getInterceptorChain().getRootDSE();
563 }
564 finally
565 {
566 stack.pop();
567 }
568 }
569
570
571 public void addContextPartition( DirectoryPartitionConfiguration config ) throws NamingException
572 {
573 addContextPartition( config, null );
574 }
575
576
577 public void addContextPartition( DirectoryPartitionConfiguration config, Collection bypass ) throws NamingException
578 {
579 ensureStarted();
580 InvocationStack stack = InvocationStack.getInstance();
581 stack.push( new Invocation( this, caller, "addContextPartition", new Object[] { config }, bypass ) );
582 try
583 {
584 this.configuration.getInterceptorChain().addContextPartition( config );
585 }
586 finally
587 {
588 stack.pop();
589 }
590 }
591
592
593 public void removeContextPartition( Name suffix ) throws NamingException
594 {
595 removeContextPartition( suffix, null );
596 }
597
598
599 public void removeContextPartition( Name suffix, Collection bypass ) throws NamingException
600 {
601 ensureStarted();
602 InvocationStack stack = InvocationStack.getInstance();
603 stack.push( new Invocation( this, caller, "removeContextPartition", new Object[] { suffix }, bypass ) );
604 try
605 {
606 this.configuration.getInterceptorChain().removeContextPartition( suffix );
607 }
608 finally
609 {
610 stack.pop();
611 }
612 }
613
614
615 private void ensureStarted() throws ServiceUnavailableException
616 {
617 if( !service.isStarted() )
618 {
619 throw new ServiceUnavailableException( "Directory service is not started." );
620 }
621 }
622
623
624
625
626
627
628
629
630
631
632
633
634
635 public void addNamingListener( EventContext ctx, Name name, ExprNode filter, SearchControls searchControls,
636 NamingListener namingListener ) throws NamingException
637 {
638 InterceptorChain chain = this.configuration.getInterceptorChain();
639 EventService interceptor = ( EventService ) chain.get( "eventService" );
640 interceptor.addNamingListener( ctx, name, filter, searchControls, namingListener );
641 }
642
643
644 public void removeNamingListener( EventContext ctx, NamingListener namingListener ) throws NamingException
645 {
646 InterceptorChain chain = this.configuration.getInterceptorChain();
647 EventService interceptor = ( EventService ) chain.get( "eventService" );
648 interceptor.removeNamingListener( ctx, namingListener );
649 }
650 }