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.exception;
21  
22  
23  import org.apache.directory.server.core.DirectoryService;
24  import org.apache.directory.server.core.integ.CiRunner;
25  import static org.apache.directory.server.core.integ.IntegrationUtils.getSystemContext;
26  import org.apache.directory.shared.ldap.constants.SchemaConstants;
27  import org.apache.directory.shared.ldap.exception.LdapContextNotEmptyException;
28  import org.apache.directory.shared.ldap.exception.LdapNameAlreadyBoundException;
29  import org.apache.directory.shared.ldap.exception.LdapNameNotFoundException;
30  import org.apache.directory.shared.ldap.exception.LdapSchemaViolationException;
31  import org.apache.directory.shared.ldap.message.ResultCodeEnum;
32  import static org.junit.Assert.assertTrue;
33  import static org.junit.Assert.assertFalse;
34  import static org.junit.Assert.assertNotNull;
35  import static org.junit.Assert.assertEquals;
36  import static org.junit.Assert.fail;
37  import org.junit.Test;
38  import org.junit.runner.RunWith;
39  
40  import javax.naming.NamingEnumeration;
41  import javax.naming.NamingException;
42  import javax.naming.directory.Attribute;
43  import javax.naming.directory.Attributes;
44  import javax.naming.directory.BasicAttribute;
45  import javax.naming.directory.BasicAttributes;
46  import javax.naming.directory.DirContext;
47  import javax.naming.directory.ModificationItem;
48  import javax.naming.directory.SearchControls;
49  import javax.naming.directory.SearchResult;
50  import javax.naming.ldap.LdapContext;
51  
52  
53  /**
54   * Tests the correct operation of the ServerExceptionService.
55   *
56   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
57   * @version $Rev: 691179 $
58   */
59  @RunWith ( CiRunner.class )
60  public class ExceptionServiceIT
61  {
62      public static DirectoryService service;
63  
64  
65      private DirContext createSubContext( String type, String value ) throws Exception
66      {
67          return createSubContext( getSystemContext( service ), type, value );
68      }
69  
70  
71      private DirContext createSubContext( DirContext ctx, String type, String value ) throws NamingException
72      {
73          Attributes attrs = new BasicAttributes( type, value, true );
74          Attribute attr = new BasicAttribute( "ObjectClass" );
75          attr.add( "top"  );
76          attr.add( "person" );
77          attr.add( "OrganizationalPerson" );
78          attrs.put( attr );
79  
80          attrs.put( "sn", value );
81          attrs.put( "cn", value );
82  
83          return ctx.createSubcontext( type + "=" + value, attrs );
84      }
85  
86  
87      // ------------------------------------------------------------------------
88      // Search Operation Tests
89      // ------------------------------------------------------------------------
90  
91  
92      /**
93       * Test search operation failure when the search base is non-existant.
94       *
95       * @throws NamingException on error
96       */
97      @Test
98      public void testFailSearchNoSuchObject() throws Exception
99      {
100         SearchControls ctls = new SearchControls();
101         try
102         {
103             getSystemContext( service ).search( "ou=blah", "(objectClass=*)", ctls );
104             fail( "Execution should never get here due to exception!" );
105         }
106         catch ( LdapNameNotFoundException e )
107         {
108             assertEquals( "ou=system", e.getResolvedName().toString() );
109             assertEquals( ResultCodeEnum.NO_SUCH_OBJECT, e.getResultCode() );
110         }
111     }
112 
113 
114     /**
115      * Search operation control to test if normal search operations occur
116      * correctly.
117      *
118      * @throws NamingException on error
119      */
120     @Test
121     public void testSearchControl() throws Exception
122     {
123         SearchControls ctls = new SearchControls();
124         NamingEnumeration<SearchResult> list = getSystemContext( service ).search( "ou=users", "(objectClass=*)", ctls );
125 
126         if ( list.hasMore() )
127         {
128             SearchResult result = list.next();
129             assertNotNull( result.getAttributes() );
130             assertEquals( "uid=akarasulu,ou=users,ou=system", result.getName() );
131         }
132 
133         assertFalse( list.hasMore() );
134     }
135 
136 
137     // ------------------------------------------------------------------------
138     // Move Operation Tests
139     // ------------------------------------------------------------------------
140 
141     /**
142      * Test move operation failure when the object moved is non-existant.
143      *
144      * @throws NamingException on error
145      */
146     @Test
147     public void testFailMoveEntryAlreadyExists() throws Exception
148     {
149         LdapContext sysRoot = getSystemContext( service );
150 
151         try
152         {
153             Attributes attrs = new BasicAttributes( "ou", "users", true );
154             Attribute attr = new BasicAttribute( "ObjectClass" );
155             attr.add( "top"  );
156             attr.add( "OrganizationalUnit" );
157             attrs.put( attr );
158 
159             sysRoot.createSubcontext( "ou=users,ou=groups", attrs );
160             sysRoot.rename( "ou=users", "ou=users,ou=groups" );
161             fail( "Execution should never get here due to exception!" );
162         }
163         catch ( LdapNameAlreadyBoundException e )
164         {
165             assertEquals( "ou=users,ou=groups,ou=system", e.getResolvedName().toString() );
166             assertEquals( ResultCodeEnum.ENTRY_ALREADY_EXISTS, e.getResultCode() );
167         }
168 
169         try
170         {
171             Attributes attrs = new BasicAttributes( "ou", "uzerz", true );
172             Attribute attr = new BasicAttribute( "ObjectClass" );
173             attr.add( "top"  );
174             attr.add( "OrganizationalUnit" );
175             attrs.put( attr );
176 
177             sysRoot.createSubcontext( "ou=uzerz,ou=groups", attrs );
178             sysRoot.addToEnvironment( "java.naming.ldap.deleteRDN", "false" );
179             sysRoot.rename( "ou=users", "ou=uzerz,ou=groups" );
180             sysRoot.removeFromEnvironment( "java.naming.ldap.deleteRDN" );
181             fail( "Execution should never get here due to exception!" );
182         }
183         catch ( LdapNameAlreadyBoundException e )
184         {
185             assertEquals( "ou=uzerz,ou=groups,ou=system", e.getResolvedName().toString() );
186             assertEquals( ResultCodeEnum.ENTRY_ALREADY_EXISTS, e.getResultCode() );
187         }
188     }
189 
190 
191     /**
192      * Test move operation failure when the object moved is non-existant.
193 
194      * @throws NamingException on error
195      */
196     @Test
197     public void testFailMoveNoSuchObject() throws Exception
198     {
199         LdapContext sysRoot = getSystemContext( service );
200 
201         try
202         {
203             sysRoot.rename( "ou=blah", "ou=blah,ou=groups" );
204             fail( "Execution should never get here due to exception!" );
205         }
206         catch ( LdapNameNotFoundException e )
207         {
208             assertEquals( "ou=system", e.getResolvedName().toString() );
209             assertEquals( ResultCodeEnum.NO_SUCH_OBJECT, e.getResultCode() );
210         }
211 
212         try
213         {
214             sysRoot.addToEnvironment( "java.naming.ldap.deleteRDN", "false" );
215             sysRoot.rename( "ou=blah", "ou=blah2,ou=groups" );
216             sysRoot.removeFromEnvironment( "java.naming.ldap.deleteRDN" );
217             fail( "Execution should never get here due to exception!" );
218         }
219         catch ( LdapNameNotFoundException e )
220         {
221             assertEquals( "ou=system", e.getResolvedName().toString() );
222             assertEquals( ResultCodeEnum.NO_SUCH_OBJECT, e.getResultCode() );
223         }
224     }
225 
226 
227     /**
228      * Move operation control to test if normal move operations occur
229      * correctly.
230      *
231      * @throws NamingException on error
232      */
233     @Test
234     public void testMoveControl() throws Exception
235     {
236         LdapContext sysRoot = getSystemContext( service );
237 
238         sysRoot.rename( "ou=users", "ou=users,ou=groups" );
239         assertNotNull( sysRoot.lookup( "ou=users,ou=groups" ) );
240 
241         try
242         {
243             sysRoot.lookup( "ou=users" );
244             fail( "Execution should never get here due to exception!" );
245         }
246         catch ( NamingException e )
247         {
248             assertEquals( "ou=system", e.getResolvedName().toString() );
249             assertTrue( e instanceof LdapNameNotFoundException );
250         }
251     }
252 
253 
254     // ------------------------------------------------------------------------
255     // ModifyRdn Operation Tests
256     // ------------------------------------------------------------------------
257 
258 
259     /**
260      * Test modifyRdn operation failure when the object renamed is non-existant.
261      *
262      * @throws NamingException on error
263      */
264     @Test
265     public void testFailModifyRdnEntryAlreadyExists() throws Exception
266     {
267         LdapContext sysRoot = getSystemContext( service );
268 
269         try
270         {
271             sysRoot.rename( "ou=users", "ou=groups" );
272             fail( "Execution should never get here due to exception!" );
273         }
274         catch ( LdapNameAlreadyBoundException e )
275         {
276             assertEquals( "ou=groups,ou=system", e.getResolvedName().toString() );
277             assertEquals( ResultCodeEnum.ENTRY_ALREADY_EXISTS, e.getResultCode() );
278         }
279     }
280 
281 
282     /**
283      * Test modifyRdn operation failure when the object renamed is non-existant.
284      *
285      * @throws NamingException on error
286      */
287     @Test
288     public void testFailModifyRdnNoSuchObject() throws Exception
289     {
290         LdapContext sysRoot = getSystemContext( service );
291 
292         try
293         {
294             sysRoot.rename( "ou=blah", "ou=asdf" );
295             fail( "Execution should never get here due to exception!" );
296         }
297         catch ( LdapNameNotFoundException e )
298         {
299             assertEquals( "ou=system", e.getResolvedName().toString() );
300             assertEquals( ResultCodeEnum.NO_SUCH_OBJECT, e.getResultCode() );
301         }
302     }
303 
304 
305     /**
306      * Modify operation control to test if normal modify operations occur
307      * correctly.
308      *
309      * @throws Exception on error
310      */
311     @Test
312     public void testModifyRdnControl() throws Exception
313     {
314         LdapContext sysRoot = getSystemContext( service );
315 
316         sysRoot.rename( "ou=users", "ou=asdf" );
317         assertNotNull( sysRoot.lookup( "ou=asdf" ) );
318 
319         try
320         {
321             sysRoot.lookup( "ou=users" );
322             fail( "Execution should never get here due to exception!" );
323         }
324         catch ( NamingException e )
325         {
326             assertEquals( "ou=system", e.getResolvedName().toString() );
327             assertTrue( e instanceof LdapNameNotFoundException );
328         }
329     }
330 
331 
332     // ------------------------------------------------------------------------
333     // Modify Operation Tests
334     // ------------------------------------------------------------------------
335 
336 
337     /**
338      * Test modify operation failure when the object modified is non-existant.
339      *
340      * @throws Exception on error
341      */
342     @Test
343     public void testFailModifyNoSuchObject() throws Exception
344     {
345         LdapContext sysRoot = getSystemContext( service );
346 
347         Attributes attrs = new BasicAttributes( true );
348         Attribute ou = new BasicAttribute( "ou" );
349         ou.add( "users" );
350         ou.add( "dummyValue" );
351         attrs.put( ou );
352 
353         try
354         {
355             sysRoot.modifyAttributes( "ou=blah", DirContext.ADD_ATTRIBUTE, attrs );
356             fail( "Execution should never get here due to exception!" );
357         }
358         catch ( LdapNameNotFoundException e )
359         {
360             assertEquals( "ou=system", e.getResolvedName().toString() );
361             assertEquals( ResultCodeEnum.NO_SUCH_OBJECT, e.getResultCode() );
362         }
363 
364         ModificationItem[] mods = new ModificationItem[]
365             { new ModificationItem( DirContext.ADD_ATTRIBUTE, ou ) };
366 
367         try
368         {
369             sysRoot.modifyAttributes( "ou=blah", mods );
370             fail( "Execution should never get here due to exception!" );
371         }
372         catch ( LdapNameNotFoundException e )
373         {
374             assertEquals( "ou=system", e.getResolvedName().toString() );
375             assertEquals( ResultCodeEnum.NO_SUCH_OBJECT, e.getResultCode() );
376         }
377     }
378 
379 
380     /**
381      * Modify operation control to test if normal modify operations occur
382      * correctly.
383      *
384      * @throws Exception on error
385      */
386     @Test
387     public void testModifyControl() throws Exception
388     {
389         LdapContext sysRoot = getSystemContext( service );
390 
391         Attributes attrs = new BasicAttributes( true );
392         Attribute attr = new BasicAttribute( "ou" );
393         attr.add( "dummyValue" );
394         attrs.put( attr );
395         sysRoot.modifyAttributes( "ou=users", DirContext.ADD_ATTRIBUTE, attrs );
396         Attribute ou = sysRoot.getAttributes( "ou=users" ).get( "ou" );
397         assertTrue( ou.contains( "users" ) );
398         assertTrue( ou.contains( "dummyValue" ) );
399 
400         attr = new BasicAttribute( "ou" );
401         attr.add( "another" );
402         ModificationItem[] mods = new ModificationItem[]
403             { new ModificationItem( DirContext.ADD_ATTRIBUTE, attr ) };
404 
405         sysRoot.modifyAttributes( "ou=users", mods );
406         ou = sysRoot.getAttributes( "ou=users" ).get( "ou" );
407         assertTrue( ou.contains( "users" ) );
408         assertTrue( ou.contains( "dummyValue" ) );
409         assertTrue( ou.contains( "another" ) );
410     }
411 
412 
413     // ------------------------------------------------------------------------
414     // Lookup Operation Tests
415     // ------------------------------------------------------------------------
416 
417 
418     /**
419      * Test lookup operation failure when the object looked up is non-existant.
420      *
421      * @throws Exception on error
422      */
423     @Test
424     public void testFailLookupNoSuchObject() throws Exception
425     {
426         LdapContext sysRoot = getSystemContext( service );
427 
428         try
429         {
430             sysRoot.lookup( "ou=blah" );
431             fail( "Execution should never get here due to exception!" );
432         }
433         catch ( LdapNameNotFoundException e )
434         {
435             assertEquals( "ou=system", e.getResolvedName().toString() );
436             assertEquals( ResultCodeEnum.NO_SUCH_OBJECT, e.getResultCode() );
437         }
438     }
439 
440 
441     /**
442      * Lookup operation control to test if normal lookup operations occur
443      * correctly.
444      *
445      * @throws Exception on error
446      */
447     @Test
448     public void testLookupControl() throws Exception
449     {
450         LdapContext sysRoot = getSystemContext( service );
451 
452         LdapContext ctx = ( LdapContext ) sysRoot.lookup( "ou=users" );
453         assertNotNull( ctx );
454         assertEquals( "users", ctx.getAttributes( "" ).get( "ou" ).get() );
455     }
456 
457 
458     // ------------------------------------------------------------------------
459     // List Operation Tests
460     // ------------------------------------------------------------------------
461 
462 
463     /**
464      * Test list operation failure when the base searched is non-existant.
465      *
466      * @throws Exception on error
467      */
468     @Test
469     public void testFailListNoSuchObject() throws Exception
470     {
471         LdapContext sysRoot = getSystemContext( service );
472 
473         try
474         {
475             sysRoot.list( "ou=blah" );
476             fail( "Execution should never get here due to exception!" );
477         }
478         catch ( LdapNameNotFoundException e )
479         {
480             assertEquals( "ou=system", e.getResolvedName().toString() );
481             assertEquals( ResultCodeEnum.NO_SUCH_OBJECT, e.getResultCode() );
482         }
483     }
484 
485 
486     /**
487      * List operation control to test if normal list operations occur correctly.
488      *
489      * @throws Exception on error
490      */
491     @Test
492     public void testListControl() throws Exception
493     {
494         LdapContext sysRoot = getSystemContext( service );
495 
496         NamingEnumeration<?> list = sysRoot.list( "ou=users" );
497 
498         if ( list.hasMore() )
499         {
500             SearchResult result = (SearchResult)list.next();
501             assertNotNull( result.getAttributes() );
502             assertEquals( "uid=akarasulu,ou=users,ou=system", result.getName() );
503         }
504 
505         assertFalse( list.hasMore() );
506     }
507 
508 
509     // ------------------------------------------------------------------------
510     // Add Operation Tests
511     // ------------------------------------------------------------------------
512 
513 
514     /**
515      * Tests for add operation failure when the parent of the entry to add does
516      * not exist.
517      *
518      * @throws Exception on error
519      */
520     @Test
521     public void testFailAddOnAlias() throws Exception
522     {
523         LdapContext sysRoot = getSystemContext( service );
524 
525         Attributes attrs = new BasicAttributes( true );
526         Attribute attr = new BasicAttribute( "objectClass" );
527         attr.add( "top" );
528         attr.add( "alias" );
529         attr.add( SchemaConstants.EXTENSIBLE_OBJECT_OC );
530         attrs.put( attr );
531         attrs.put( "aliasedObjectName", "ou=users,ou=system" );
532 
533         sysRoot.createSubcontext( "cn=toanother", attrs );
534 
535         try
536         {
537             sysRoot.createSubcontext( "ou=blah,cn=toanother" );
538             fail( "Execution should never get here due to exception!" );
539         }
540         catch ( LdapSchemaViolationException e )
541         {
542             assertEquals( ResultCodeEnum.OBJECT_CLASS_VIOLATION, e.getResultCode() );
543         }
544     }
545 
546 
547     /**
548      * Tests for add operation failure when the parent of the entry to add does
549      * not exist.
550      *
551      * @throws Exception on error
552      */
553     @Test
554     public void testFailAddNoSuchEntry() throws Exception
555     {
556         LdapContext sysRoot = getSystemContext( service );
557 
558         try
559         {
560             sysRoot.createSubcontext( "ou=blah,ou=abc" );
561             fail( "Execution should never get here due to exception!" );
562         }
563         catch ( LdapSchemaViolationException e )
564         {
565             assertEquals( ResultCodeEnum.OBJECT_CLASS_VIOLATION, e.getResultCode() );
566         }
567     }
568 
569 
570     /**
571      * Tests for add operation failure when the entry to add already exists.
572      *
573      * @throws Exception on error
574      */
575     @Test
576     public void testFailAddEntryAlreadyExists() throws Exception
577     {
578         createSubContext( "ou", "blah");
579 
580         try
581         {
582             createSubContext( "ou", "blah");
583             fail( "Execution should never get here due to exception!" );
584         }
585         catch ( LdapNameAlreadyBoundException e )
586         {
587             assertEquals( "ou=blah,ou=system", e.getResolvedName().toString() );
588             assertEquals( ResultCodeEnum.ENTRY_ALREADY_EXISTS, e.getResultCode() );
589         }
590     }
591 
592 
593     /**
594      * Add operation control to test if normal add operations occur correctly.
595      *
596      * @throws Exception on error
597      */
598     @Test
599     public void testAddControl() throws Exception
600     {
601         LdapContext sysRoot = getSystemContext( service );
602 
603         DirContext ctx = createSubContext( "ou", "blah");
604         createSubContext( ctx, "ou", "subctx");
605         Object obj = sysRoot.lookup( "ou=subctx,ou=blah" );
606         assertNotNull( obj );
607     }
608 
609 
610     // ------------------------------------------------------------------------
611     // Delete Operation Tests
612     // ------------------------------------------------------------------------
613 
614 
615     /**
616      * Tests for delete failure when the entry to be deleted has child entires.
617      *
618      * @throws Exception on error
619      */
620     @Test
621     public void testFailDeleteNotAllowedOnNonLeaf() throws Exception
622     {
623         LdapContext sysRoot = getSystemContext( service );
624 
625         DirContext ctx = createSubContext( "ou", "blah" );
626         createSubContext( ctx,  "ou", "subctx" );
627 
628         try
629         {
630             sysRoot.destroySubcontext( "ou=blah" );
631             fail( "Execution should never get here due to exception!" );
632         }
633         catch ( LdapContextNotEmptyException e )
634         {
635             assertEquals( "ou=blah,ou=system", e.getResolvedName().toString() );
636             assertEquals( ResultCodeEnum.NOT_ALLOWED_ON_NON_LEAF, e.getResultCode() );
637         }
638     }
639 
640 
641     /**
642      * Tests delete to make sure it fails when we try to delete an entry that
643      * does not exist.
644      *
645      * @throws Exception on error
646      */
647     @Test
648     public void testFailDeleteNoSuchObject() throws Exception
649     {
650         LdapContext sysRoot = getSystemContext( service );
651 
652         try
653         {
654             sysRoot.destroySubcontext( "ou=blah" );
655             fail( "Execution should never get here due to exception!" );
656         }
657         catch ( LdapNameNotFoundException e )
658         {
659             assertEquals( "ou=system", e.getResolvedName().toString() );
660             assertEquals( ResultCodeEnum.NO_SUCH_OBJECT, e.getResultCode() );
661         }
662     }
663 
664 
665     /**
666      * Delete operation control to test if normal delete operations occur.
667      *
668      * @throws Exception on error
669      */
670     @Test
671     public void testDeleteControl() throws Exception
672     {
673         LdapContext sysRoot = getSystemContext( service );
674 
675         createSubContext( "ou", "blah" );
676 
677         Object obj = sysRoot.lookup( "ou=blah" );
678         assertNotNull( obj );
679         sysRoot.destroySubcontext( "ou=blah" );
680 
681         try
682         {
683             sysRoot.lookup( "ou=blah" );
684             fail( "Execution should never get here due to exception!" );
685         }
686         catch ( LdapNameNotFoundException e )
687         {
688             assertEquals( "ou=system", e.getResolvedName().toString() );
689             assertEquals( ResultCodeEnum.NO_SUCH_OBJECT, e.getResultCode() );
690         }
691     }
692 }