View Javadoc
1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    * 
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   * 
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License.
18   * 
19   */
20  package org.apache.directory.server.core.api.interceptor;
21  
22  
23  import java.util.HashSet;
24  import java.util.Set;
25  
26  import org.apache.directory.api.ldap.model.entry.Entry;
27  import org.apache.directory.api.ldap.model.exception.LdapException;
28  import org.apache.directory.api.ldap.model.schema.AttributeType;
29  import org.apache.directory.api.ldap.model.schema.SchemaManager;
30  import org.apache.directory.server.core.api.DirectoryService;
31  import org.apache.directory.server.core.api.DnFactory;
32  import org.apache.directory.server.core.api.InterceptorEnum;
33  import org.apache.directory.server.core.api.LdapPrincipal;
34  import org.apache.directory.server.core.api.filtering.EntryFilteringCursor;
35  import org.apache.directory.server.core.api.interceptor.context.AddOperationContext;
36  import org.apache.directory.server.core.api.interceptor.context.BindOperationContext;
37  import org.apache.directory.server.core.api.interceptor.context.CompareOperationContext;
38  import org.apache.directory.server.core.api.interceptor.context.DeleteOperationContext;
39  import org.apache.directory.server.core.api.interceptor.context.GetRootDseOperationContext;
40  import org.apache.directory.server.core.api.interceptor.context.HasEntryOperationContext;
41  import org.apache.directory.server.core.api.interceptor.context.LookupOperationContext;
42  import org.apache.directory.server.core.api.interceptor.context.ModifyOperationContext;
43  import org.apache.directory.server.core.api.interceptor.context.MoveAndRenameOperationContext;
44  import org.apache.directory.server.core.api.interceptor.context.MoveOperationContext;
45  import org.apache.directory.server.core.api.interceptor.context.OperationContext;
46  import org.apache.directory.server.core.api.interceptor.context.RenameOperationContext;
47  import org.apache.directory.server.core.api.interceptor.context.SearchOperationContext;
48  import org.apache.directory.server.core.api.interceptor.context.UnbindOperationContext;
49  import org.apache.directory.server.core.api.partition.PartitionNexus;
50  
51  
52  /**
53   * A easy-to-use implementation of {@link Interceptor}.  All methods are
54   * implemented to pass the flow of control to next interceptor by defaults.
55   * Please override the methods you have concern in.
56   *
57   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
58   */
59  public abstract class BaseInterceptor implements Interceptor
60  {
61      /** The interceptor's name. Default to the class name */
62      private String name;
63  
64      /** A reference to the DirectoryService instance */
65      protected DirectoryService directoryService;
66  
67      /** A reference to the SchemaManager instance */
68      protected SchemaManager schemaManager;
69  
70      /** The DN factory */
71      protected DnFactory dnFactory;
72  
73      /** set of operational attribute types used for representing the password policy state of a user entry */
74      protected static final Set<AttributeType> PWD_POLICY_STATE_ATTRIBUTE_TYPES = new HashSet<>();
75  
76      /**
77       * The final interceptor which acts as a proxy in charge to dialog with the nexus partition.
78       */
79      private final Interceptorpi/interceptor/Interceptor.html#Interceptor">Interceptor finalInterceptor = new Interceptor()
80      {
81          private PartitionNexus nexus;
82  
83  
84          public String getName()
85          {
86              return "FINAL";
87          }
88  
89  
90          public void init( DirectoryService directoryService )
91          {
92              this.nexus = directoryService.getPartitionNexus();
93          }
94  
95  
96          public void destroy()
97          {
98              // unused
99          }
100 
101 
102         /**
103          * {@inheritDoc}
104          */
105         public void add( AddOperationContext addContext ) throws LdapException
106         {
107             nexus.add( addContext );
108         }
109 
110 
111         /**
112          * {@inheritDoc}
113          */
114         public void bind( BindOperationContext bindContext ) throws LdapException
115         {
116             // Do nothing here : there is no support for the Bind operation in Partition
117         }
118 
119 
120         /**
121          * {@inheritDoc}
122          */
123         public boolean compare( CompareOperationContext compareContext ) throws LdapException
124         {
125             return nexus.compare( compareContext );
126         }
127 
128 
129         /**
130          * {@inheritDoc}
131          */
132         public void delete( DeleteOperationContext deleteContext ) throws LdapException
133         {
134             nexus.delete( deleteContext );
135         }
136 
137 
138         /**
139          * {@inheritDoc}
140          */
141         public Entry getRootDse( GetRootDseOperationContext getRootDseContext ) throws LdapException
142         {
143             return nexus.getRootDse( getRootDseContext );
144         }
145 
146 
147         /**
148          * {@inheritDoc}
149          */
150         public boolean hasEntry( HasEntryOperationContext hasEntryContext ) throws LdapException
151         {
152             return nexus.hasEntry( hasEntryContext );
153         }
154 
155 
156         /**
157          * {@inheritDoc}
158          */
159         public Entry lookup( LookupOperationContext lookupContext ) throws LdapException
160         {
161             return nexus.lookup( lookupContext );
162         }
163 
164 
165         /**
166          * {@inheritDoc}
167          */
168         public void modify( ModifyOperationContext modifyContext ) throws LdapException
169         {
170             nexus.modify( modifyContext );
171         }
172 
173 
174         /**
175          * {@inheritDoc}
176          */
177         public void move( MoveOperationContext moveContext ) throws LdapException
178         {
179             nexus.move( moveContext );
180         }
181 
182 
183         /**
184          * {@inheritDoc}
185          */
186         public void moveAndRename( MoveAndRenameOperationContext moveAndRenameContext ) throws LdapException
187         {
188             nexus.moveAndRename( moveAndRenameContext );
189         }
190 
191 
192         /**
193          * {@inheritDoc}
194          */
195         public void rename( RenameOperationContext renameContext ) throws LdapException
196         {
197             nexus.rename( renameContext );
198         }
199 
200 
201         /**
202          * {@inheritDoc}
203          */
204         public EntryFilteringCursor search( SearchOperationContext searchContext ) throws LdapException
205         {
206             return nexus.search( searchContext );
207         }
208 
209 
210         /**
211          * {@inheritDoc}
212          */
213         public void unbind( UnbindOperationContext unbindContext ) throws LdapException
214         {
215             nexus.unbind( unbindContext );
216         }
217     };
218 
219 
220     /**
221      * default interceptor name is its class, preventing accidental duplication of interceptors by naming
222      * instances differently
223      * @return (default, class name) interceptor name
224      */
225     public String getName()
226     {
227         return name;
228     }
229 
230 
231     /**
232      * Returns {@link LdapPrincipal} of current context.
233      * 
234      * @param opContext TODO
235      * @return the authenticated principal
236      */
237     public static LdapPrincipal getPrincipal( OperationContext opContext )
238     {
239         return opContext.getSession().getEffectivePrincipal();
240     }
241 
242 
243     /**
244      * Creates a new instance with a default name : the class name itself.
245      */
246     protected BaseInterceptor()
247     {
248         name = getClass().getSimpleName();
249     }
250 
251 
252     /**
253      * Creates a new instance with a given name.
254      * 
255      * @param name the Interceptor name
256      */
257     protected BaseInterceptor( String name )
258     {
259         this.name = name;
260     }
261 
262 
263     /**
264      * Creates a new instance with a given name.
265      * 
266      * @param interceptor the Interceptor type
267      */
268     protected BaseInterceptor( InterceptorEnum interceptor )
269     {
270         this.name = interceptor.getName();
271     }
272 
273 
274     /**
275      * This method does nothing by default.
276      * 
277      * @param directoryService The DirectoryService instance
278      * @throws LdapException If the initialization failed
279      */
280     public void init( DirectoryService directoryService ) throws LdapException
281     {
282         // Initialize the fields that will be used by all the interceptors
283         this.directoryService = directoryService;
284         schemaManager = directoryService.getSchemaManager();
285         dnFactory = directoryService.getDnFactory();
286 
287         finalInterceptor.init( directoryService );
288     }
289 
290 
291     /**
292      * This method does nothing by default.
293      */
294     public void destroy()
295     {
296     }
297 
298 
299     /**
300      * Computes the next interceptor to call for a given operation. If we find none,
301      * we return the proxy to the nexus.
302      * 
303      * @param operationContext The operation context
304      * @return The next interceptor in the list for this operation
305      */
306     protected Interceptor getNextInterceptor( OperationContext operationContext )
307     {
308         String currentInterceptor = operationContext.getNextInterceptor();
309 
310         if ( currentInterceptor.equals( "FINAL" ) )
311         {
312             return finalInterceptor;
313         }
314 
315         return directoryService.getInterceptor( currentInterceptor );
316     }
317 
318 
319     // ------------------------------------------------------------------------
320     // Interceptor's Invoke Method
321     // ------------------------------------------------------------------------
322     /**
323      * {@inheritDoc}
324      */
325     public void add( AddOperationContext addContext ) throws LdapException
326     {
327         // Do nothing
328     }
329 
330 
331     /**
332      * Calls the next interceptor for the add operation.
333      * 
334      * @param addContext The context in which we are executing this operation
335      * @throws LdapException If something went wrong
336      */
337     protected final void next( AddOperationContext addContext ) throws LdapException
338     {
339         Interceptor interceptor = getNextInterceptor( addContext );
340 
341         interceptor.add( addContext );
342     }
343 
344 
345     /**
346      * {@inheritDoc}
347      */
348     public void bind( BindOperationContext bindContext ) throws LdapException
349     {
350         // Do nothing
351     }
352 
353 
354     /**
355      * Calls the next interceptor for the bind operation.
356      * 
357      * @param bindContext The context in which we are executing this operation
358      * @throws LdapException If something went wrong
359      */
360     protected final void next( BindOperationContext bindContext ) throws LdapException
361     {
362         Interceptor interceptor = getNextInterceptor( bindContext );
363 
364         interceptor.bind( bindContext );
365     }
366 
367 
368     public boolean compare( CompareOperationContext compareContext ) throws LdapException
369     {
370         // Return false in any case
371         return false;
372     }
373 
374 
375     /**
376      * Calls the next interceptor for the compare operation.
377      * 
378      * @param compareContext The context in which we are executing this operation
379      * @return a boolean indicating if the comparison is successfull
380      * @throws LdapException If something went wrong
381      */
382     protected final boolean next( CompareOperationContext compareContext ) throws LdapException
383     {
384         Interceptor interceptor = getNextInterceptor( compareContext );
385 
386         return interceptor.compare( compareContext );
387     }
388 
389 
390     /**
391      * {@inheritDoc}
392      */
393     public void delete( DeleteOperationContext deleteContext ) throws LdapException
394     {
395         // Do nothing
396     }
397 
398 
399     /**
400      * Calls the next interceptor for the delete operation.
401      * 
402      * @param deleteContext The context in which we are executing this operation
403      * @throws LdapException If something went wrong
404      */
405     protected final void next( DeleteOperationContext deleteContext ) throws LdapException
406     {
407         Interceptor interceptor = getNextInterceptor( deleteContext );
408 
409         interceptor.delete( deleteContext );
410     }
411 
412 
413     /**
414      * {@inheritDoc}
415      */
416     public Entry getRootDse( GetRootDseOperationContext getRootDseContext ) throws LdapException
417     {
418         // Nothing to do
419         return null;
420     }
421 
422 
423     /**
424      * Calls the next interceptor for the getRootDse operation.
425      * 
426      * @param getRootDseContext The context in which we are executing this operation
427      * @return the rootDSE
428      * @throws LdapException If something went wrong
429      */
430     protected final Entry next( GetRootDseOperationContext getRootDseContext ) throws LdapException
431     {
432         Interceptor interceptor = getNextInterceptor( getRootDseContext );
433 
434         return interceptor.getRootDse( getRootDseContext );
435     }
436 
437 
438     /**
439      * {@inheritDoc}
440      */
441     public boolean hasEntry( HasEntryOperationContext hasEntryContext ) throws LdapException
442     {
443         // Return false in any case
444         return false;
445     }
446 
447 
448     /**
449      * Calls the next interceptor for the hasEntry operation.
450      * 
451      * @param hasEntryContext The context in which we are executing this operation
452      * @return a boolean indicating if the entry exists on the server
453      * @throws LdapException If something went wrong
454      */
455     protected final boolean next( HasEntryOperationContext hasEntryContext ) throws LdapException
456     {
457         Interceptor interceptor = getNextInterceptor( hasEntryContext );
458 
459         return interceptor.hasEntry( hasEntryContext );
460     }
461 
462 
463     /**
464      * {@inheritDoc}
465      */
466     public Entry lookup( LookupOperationContext lookupContext ) throws LdapException
467     {
468         return next( lookupContext );
469     }
470 
471 
472     /**
473      * Calls the next interceptor for the lookup operation.
474      * 
475      * @param lookupContext The context in which we are executing this operation
476      * @return the Entry containing the found entry
477      * @throws LdapException If something went wrong
478      */
479     protected final Entry next( LookupOperationContext lookupContext ) throws LdapException
480     {
481         Interceptor interceptor = getNextInterceptor( lookupContext );
482 
483         return interceptor.lookup( lookupContext );
484     }
485 
486 
487     /**
488      * {@inheritDoc}
489      */
490     public void modify( ModifyOperationContext modifyContext ) throws LdapException
491     {
492         // Nothing to do
493     }
494 
495 
496     /**
497      * Calls the next interceptor for the modify operation.
498      * 
499      * @param modifyContext The context in which we are executing this operation
500      * @throws LdapException If something went wrong
501      */
502     protected final void next( ModifyOperationContext modifyContext ) throws LdapException
503     {
504         Interceptor interceptor = getNextInterceptor( modifyContext );
505 
506         interceptor.modify( modifyContext );
507     }
508 
509 
510     /**
511      * {@inheritDoc}
512      */
513     public void move( MoveOperationContext moveContext ) throws LdapException
514     {
515         // Do nothing
516     }
517 
518 
519     /**
520      * Calls the next interceptor for the move operation.
521      * 
522      * @param moveContext The context in which we are executing this operation
523      * @throws LdapException If something went wrong
524      */
525     protected final void next( MoveOperationContext moveContext ) throws LdapException
526     {
527         Interceptor interceptor = getNextInterceptor( moveContext );
528 
529         interceptor.move( moveContext );
530     }
531 
532 
533     public void moveAndRename( MoveAndRenameOperationContext moveAndRenameContext ) throws LdapException
534     {
535         // Do nothing
536     }
537 
538 
539     /**
540      * Calls the next interceptor for the moveAndRename operation.
541      * 
542      * @param moveAndRenameContext The context in which we are executing this operation
543      * @throws LdapException If something went wrong
544      */
545     protected final void next( MoveAndRenameOperationContext moveAndRenameContext ) throws LdapException
546     {
547         Interceptor interceptor = getNextInterceptor( moveAndRenameContext );
548 
549         interceptor.moveAndRename( moveAndRenameContext );
550     }
551 
552 
553     /**
554      * {@inheritDoc}
555      */
556     public void rename( RenameOperationContext renameContext ) throws LdapException
557     {
558         // Nothing to do
559     }
560 
561 
562     /**
563      * Calls the next interceptor for the rename operation.
564      * 
565      * @param renameContext The context in which we are executing this operation
566      * @throws LdapException If something went wrong
567      */
568     protected final void next( RenameOperationContext renameContext ) throws LdapException
569     {
570         Interceptor interceptor = getNextInterceptor( renameContext );
571 
572         interceptor.rename( renameContext );
573     }
574 
575 
576     /**
577      * {@inheritDoc}
578      */
579     public EntryFilteringCursor search( SearchOperationContext searchContext ) throws LdapException
580     {
581         return null;
582     }
583 
584 
585     /**
586      * Calls the next interceptor for the search operation.
587      * 
588      * @param searchContext The context in which we are executing this operation
589      * @return the cursor containing the found entries
590      * @throws LdapException If something went wrong
591      */
592     protected final EntryFilteringCursor next( SearchOperationContext searchContext ) throws LdapException
593     {
594         Interceptor interceptor = getNextInterceptor( searchContext );
595 
596         return interceptor.search( searchContext );
597     }
598 
599 
600     /**
601      * {@inheritDoc}
602      */
603     public void unbind( UnbindOperationContext unbindContext ) throws LdapException
604     {
605         // Nothing to do
606     }
607 
608 
609     /**
610      * Compute the next interceptor for the unbind operation.
611      * 
612      * @param unbindContext The context in which we are executing this operation
613      * @throws LdapException If something went wrong
614      */
615     protected final void next( UnbindOperationContext unbindContext ) throws LdapException
616     {
617         Interceptor interceptor = getNextInterceptor( unbindContext );
618 
619         interceptor.unbind( unbindContext );
620     }
621 }