1   /*
2    *   Copyright 2004 The Apache Software Foundation
3    *
4    *   Licensed under the Apache License, Version 2.0 (the "License");
5    *   you may not use this file except in compliance with the License.
6    *   You may obtain a copy of the License at
7    *
8    *       http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *   Unless required by applicable law or agreed to in writing, software
11   *   distributed under the License is distributed on an "AS IS" BASIS,
12   *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *   See the License for the specific language governing permissions and
14   *   limitations under the License.
15   *
16   */
17  package org.apache.ldap.server.interceptor;
18  
19  
20  import junit.framework.TestCase;
21  import org.apache.ldap.server.DirectoryServiceConfiguration;
22  import org.apache.ldap.server.DirectoryService;
23  import org.apache.ldap.server.DirectoryServiceListener;
24  import org.apache.ldap.server.partition.DirectoryPartitionNexusProxy;
25  import org.apache.ldap.server.jndi.DeadContext;
26  import org.apache.ldap.server.invocation.InvocationStack;
27  import org.apache.ldap.server.invocation.Invocation;
28  import org.apache.ldap.server.configuration.InterceptorConfiguration;
29  import org.apache.ldap.server.configuration.DirectoryPartitionConfiguration;
30  import org.apache.ldap.server.configuration.MutableInterceptorConfiguration;
31  import org.apache.ldap.common.filter.ExprNode;
32  import org.apache.ldap.common.name.LdapName;
33  import org.slf4j.Logger;
34  import org.slf4j.LoggerFactory;
35  
36  import javax.naming.NamingException;
37  import javax.naming.Name;
38  import javax.naming.NamingEnumeration;
39  import javax.naming.Context;
40  import javax.naming.directory.Attributes;
41  import javax.naming.directory.ModificationItem;
42  import javax.naming.directory.SearchControls;
43  import java.util.*;
44  
45  
46  /***
47   * Unit test cases for InterceptorChain methods.
48   *
49   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
50   * @version $Rev$
51   */
52  public class InterceptorChainTest extends TestCase
53  {
54      private final MockInterceptor[] interceptorArray =
55      {
56              new MockInterceptor( "0" ),
57              new MockInterceptor( "1" ),
58              new MockInterceptor( "2" ),
59              new MockInterceptor( "3" ),
60              new MockInterceptor( "4" )
61      };
62      private final static Logger log = LoggerFactory.getLogger( InterceptorChainTest.class );
63      private InterceptorChain chain;
64      private List interceptors = new ArrayList( interceptorArray.length );
65  
66  
67      protected void setUp() throws Exception
68      {
69          chain = new InterceptorChain();
70  
71          for ( int ii = 0; ii < interceptorArray.length; ii++ )
72          {
73              MutableInterceptorConfiguration config = new MutableInterceptorConfiguration();
74              config.setInterceptor( interceptorArray[ii] );
75              config.setName( interceptorArray[ii].getName() );
76              chain.addLast( config );
77          }
78      }
79  
80  
81      protected void tearDown() throws Exception
82      {
83          chain = null;
84          interceptors.clear();
85      }
86  
87  
88      public void testNoBypass() throws NamingException
89      {
90          Name dn = new LdapName( "ou=system" );
91          Context ctx = new DeadContext();
92          DirectoryService ds = new MockDirectoryService();
93          DirectoryPartitionNexusProxy proxy = new DirectoryPartitionNexusProxy( ctx, ds );
94          Invocation i = new Invocation( proxy, ctx, "lookup", new Object[]{ dn } );
95          InvocationStack.getInstance().push( i );
96  
97          try
98          {
99              chain.lookup( dn );
100         }
101         catch( Exception e )
102         {
103         }
104 
105         assertEquals( interceptorArray.length, interceptors.size() );
106         for ( int ii = 0; ii < interceptorArray.length; ii++ )
107         {
108             assertEquals( interceptorArray[ii], interceptors.get( ii ) );
109         }
110     }
111 
112 
113     public void testSingleBypass() throws NamingException
114     {
115         Name dn = new LdapName( "ou=system" );
116         Context ctx = new DeadContext();
117         DirectoryService ds = new MockDirectoryService();
118         DirectoryPartitionNexusProxy proxy = new DirectoryPartitionNexusProxy( ctx, ds );
119         Invocation i = new Invocation( proxy, ctx, "lookup", new Object[]{ dn }, Collections.singleton( "0" ) );
120         InvocationStack.getInstance().push( i );
121 
122         try
123         {
124             chain.lookup( dn );
125         }
126         catch( Exception e )
127         {
128         }
129 
130         assertEquals( interceptorArray.length - 1, interceptors.size() );
131         for ( int ii = 0; ii < interceptorArray.length; ii++ )
132         {
133             if ( ii != 0 )
134             {
135                 assertEquals( interceptorArray[ii], interceptors.get( ii - 1 ) );
136             }
137         }
138         assertFalse( interceptors.contains( interceptorArray[0] ) );
139     }
140 
141 
142     public void testAdjacentDoubleBypass() throws NamingException
143     {
144         Name dn = new LdapName( "ou=system" );
145         Context ctx = new DeadContext();
146         DirectoryService ds = new MockDirectoryService();
147         DirectoryPartitionNexusProxy proxy = new DirectoryPartitionNexusProxy( ctx, ds );
148         Collection bypass = new HashSet();
149         bypass.add( "0" );
150         bypass.add( "1" );
151         Invocation i = new Invocation( proxy, ctx, "lookup", new Object[]{ dn }, bypass );
152         InvocationStack.getInstance().push( i );
153 
154         try
155         {
156             chain.lookup( dn );
157         }
158         catch( Exception e )
159         {
160         }
161 
162         assertEquals( interceptorArray.length - 2, interceptors.size() );
163         for ( int ii = 0; ii < interceptorArray.length; ii++ )
164         {
165             if ( ii != 0 && ii != 1 )
166             {
167                 assertEquals( interceptorArray[ii], interceptors.get( ii - 2 ) );
168             }
169         }
170         assertFalse( interceptors.contains( interceptorArray[0] ) );
171         assertFalse( interceptors.contains( interceptorArray[1] ) );
172     }
173 
174 
175     public void testFrontAndBackDoubleBypass() throws NamingException
176     {
177         Name dn = new LdapName( "ou=system" );
178         Context ctx = new DeadContext();
179         DirectoryService ds = new MockDirectoryService();
180         DirectoryPartitionNexusProxy proxy = new DirectoryPartitionNexusProxy( ctx, ds );
181         Collection bypass = new HashSet();
182         bypass.add( "0" );
183         bypass.add( "4" );
184         Invocation i = new Invocation( proxy, ctx, "lookup", new Object[]{ dn }, bypass );
185         InvocationStack.getInstance().push( i );
186 
187         try
188         {
189             chain.lookup( dn );
190         }
191         catch( Exception e )
192         {
193         }
194 
195         assertEquals( interceptorArray.length - 2, interceptors.size() );
196         assertEquals( interceptorArray[1], interceptors.get( 0 ) );
197         assertEquals( interceptorArray[2], interceptors.get( 1 ) );
198         assertEquals( interceptorArray[3], interceptors.get( 2 ) );
199         assertFalse( interceptors.contains( interceptorArray[0] ) );
200         assertFalse( interceptors.contains( interceptorArray[4] ) );
201     }
202 
203 
204     public void testDoubleBypass() throws NamingException
205     {
206         Name dn = new LdapName( "ou=system" );
207         Context ctx = new DeadContext();
208         DirectoryService ds = new MockDirectoryService();
209         DirectoryPartitionNexusProxy proxy = new DirectoryPartitionNexusProxy( ctx, ds );
210         Collection bypass = new HashSet();
211         bypass.add( "1" );
212         bypass.add( "3" );
213         Invocation i = new Invocation( proxy, ctx, "lookup", new Object[]{ dn }, bypass );
214         InvocationStack.getInstance().push( i );
215 
216         try
217         {
218             chain.lookup( dn );
219         }
220         catch( Exception e )
221         {
222         }
223 
224         assertEquals( interceptorArray.length - 2, interceptors.size() );
225         assertEquals( interceptorArray[0], interceptors.get( 0 ) );
226         assertEquals( interceptorArray[2], interceptors.get( 1 ) );
227         assertEquals( interceptorArray[4], interceptors.get( 2 ) );
228         assertFalse( interceptors.contains( interceptorArray[1] ) );
229         assertFalse( interceptors.contains( interceptorArray[3] ) );
230     }
231 
232 
233     public void testCompleteBypass() throws NamingException
234     {
235         Name dn = new LdapName( "ou=system" );
236         Context ctx = new DeadContext();
237         DirectoryService ds = new MockDirectoryService();
238         DirectoryPartitionNexusProxy proxy = new DirectoryPartitionNexusProxy( ctx, ds );
239         Invocation i = new Invocation( proxy, ctx, "lookup", new Object[]{ dn },
240                 DirectoryPartitionNexusProxy.BYPASS_ALL_COLLECTION );
241         InvocationStack.getInstance().push( i );
242 
243         try
244         {
245             chain.lookup( dn );
246         }
247         catch( Exception e )
248         {
249         }
250 
251         assertEquals( 0, interceptors.size() );
252     }
253 
254 
255     class MockInterceptor implements Interceptor
256     {
257         String name;
258 
259         public MockInterceptor( String name )
260         {
261             this.name = name;
262         }
263 
264 
265         public String getName()
266         {
267             return this.name;
268         }
269 
270 
271         public void init( DirectoryServiceConfiguration factoryCfg, InterceptorConfiguration cfg ) throws NamingException
272         {
273         }
274 
275 
276         public void destroy()
277         {
278         }
279 
280 
281         public Attributes getRootDSE( NextInterceptor next ) throws NamingException
282         {
283             interceptors.add( this );
284             return next.getRootDSE();
285         }
286 
287 
288         public Name getMatchedName( NextInterceptor next, Name name, boolean normalized ) throws NamingException
289         {
290             interceptors.add( this );
291             return next.getMatchedName( name, normalized );
292         }
293 
294 
295         public Name getSuffix( NextInterceptor next, Name name, boolean normalized ) throws NamingException
296         {
297             interceptors.add( this );
298             return next.getSuffix( name, normalized );
299         }
300 
301 
302         public Iterator listSuffixes( NextInterceptor next, boolean normalized ) throws NamingException
303         {
304             interceptors.add( this );
305             return next.listSuffixes( normalized );
306         }
307 
308 
309         public void addContextPartition( NextInterceptor next, DirectoryPartitionConfiguration cfg ) throws NamingException
310         {
311             interceptors.add( this );
312             next.addContextPartition( cfg );
313         }
314 
315 
316         public void removeContextPartition( NextInterceptor next, Name suffix ) throws NamingException
317         {
318             interceptors.add( this );
319             next.removeContextPartition( suffix );
320         }
321 
322 
323         public boolean compare( NextInterceptor next, Name name, String oid, Object value ) throws NamingException
324         {
325             interceptors.add( this );
326             return next.compare( name, oid, value );
327         }
328 
329 
330         public void delete( NextInterceptor next, Name name ) throws NamingException
331         {
332             interceptors.add( this );
333             next.delete( name );
334         }
335 
336 
337         public void add( NextInterceptor next, String userProvidedName, Name normalizedName, Attributes entry ) throws NamingException
338         {
339             interceptors.add( this );
340             next.add( userProvidedName, normalizedName, entry );
341         }
342 
343 
344         public void modify( NextInterceptor next, Name name, int modOp, Attributes attributes ) throws NamingException
345         {
346             interceptors.add( this );
347             next.modify( name, modOp, attributes );
348         }
349 
350 
351         public void modify( NextInterceptor next, Name name, ModificationItem [] items ) throws NamingException
352         {
353             interceptors.add( this );
354             next.modify( name, items );
355         }
356 
357 
358         public NamingEnumeration list( NextInterceptor next, Name baseName ) throws NamingException
359         {
360             interceptors.add( this );
361             return next.list( baseName );
362         }
363 
364 
365         public NamingEnumeration search( NextInterceptor next, Name baseName, Map environment, ExprNode filter, SearchControls searchControls ) throws NamingException
366         {
367             interceptors.add( this );
368             return next.search( baseName, environment, filter, searchControls );
369         }
370 
371 
372         public Attributes lookup( NextInterceptor next, Name name ) throws NamingException
373         {
374             interceptors.add( this );
375             return next.lookup( name );
376         }
377 
378 
379         public Attributes lookup( NextInterceptor next, Name dn, String [] attrIds ) throws NamingException
380         {
381             interceptors.add( this );
382             return next.lookup( dn, attrIds );
383         }
384 
385 
386         public boolean hasEntry( NextInterceptor next, Name name ) throws NamingException
387         {
388             interceptors.add( this );
389             return next.hasEntry( name );
390         }
391 
392 
393         public boolean isSuffix( NextInterceptor next, Name name ) throws NamingException
394         {
395             interceptors.add( this );
396             return next.isSuffix( name );
397         }
398 
399 
400         public void modifyRn( NextInterceptor next, Name name, String newRn, boolean deleteOldRn ) throws NamingException
401         {
402             interceptors.add( this );
403             next.modifyRn( name, newRn, deleteOldRn );
404         }
405 
406 
407         public void move( NextInterceptor next, Name oldName, Name newParentName ) throws NamingException
408         {
409             interceptors.add( this );
410             next.move( oldName, newParentName );
411         }
412 
413 
414         public void move( NextInterceptor next, Name oldName, Name newParentName, String newRn, boolean deleteOldRn ) throws NamingException
415         {
416             interceptors.add( this );
417             next.move( oldName, newParentName, newRn, deleteOldRn );
418         }
419     }
420 
421 
422     class MockDirectoryService extends DirectoryService
423     {
424         public void startup( DirectoryServiceListener listener, Hashtable environment ) throws NamingException
425         {
426             //To change body of implemented methods use File | Settings | File Templates.
427         }
428 
429 
430         public void shutdown() throws NamingException
431         {
432             //To change body of implemented methods use File | Settings | File Templates.
433         }
434 
435 
436         public void sync() throws NamingException
437         {
438             //To change body of implemented methods use File | Settings | File Templates.
439         }
440 
441 
442         public boolean isStarted()
443         {
444             return false;  //To change body of implemented methods use File | Settings | File Templates.
445         }
446 
447 
448         public DirectoryServiceConfiguration getConfiguration()
449         {
450             return null;  //To change body of implemented methods use File | Settings | File Templates.
451         }
452 
453 
454         public Context getJndiContext( String baseName ) throws NamingException
455         {
456             return null;  //To change body of implemented methods use File | Settings | File Templates.
457         }
458 
459 
460         public Context getJndiContext( String principal, byte[] credential, String authentication, String baseName ) throws NamingException
461         {
462             return null;  //To change body of implemented methods use File | Settings | File Templates.
463         }
464     }
465 }