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.schema;
21  
22  
23  import org.apache.directory.server.constants.MetaSchemaConstants;
24  import org.apache.directory.server.core.DirectoryService;
25  import org.apache.directory.server.core.integ.CiRunner;
26  import static org.apache.directory.server.core.integ.IntegrationUtils.getSchemaContext;
27  import org.apache.directory.server.schema.bootstrap.Schema;
28  import org.apache.directory.server.schema.registries.AttributeTypeRegistry;
29  import org.apache.directory.shared.ldap.exception.LdapNameNotFoundException;
30  import org.apache.directory.shared.ldap.exception.LdapOperationNotSupportedException;
31  import org.apache.directory.shared.ldap.message.ResultCodeEnum;
32  import org.apache.directory.shared.ldap.constants.SchemaConstants;
33  import static org.junit.Assert.assertEquals;
34  import static org.junit.Assert.assertTrue;
35  import static org.junit.Assert.assertFalse;
36  import static org.junit.Assert.assertNull;
37  import static org.junit.Assert.assertNotNull;
38  import static org.junit.Assert.fail;
39  import org.junit.Before;
40  import org.junit.Test;
41  import org.junit.runner.RunWith;
42  
43  import javax.naming.NamingException;
44  import javax.naming.directory.Attribute;
45  import javax.naming.directory.Attributes;
46  import javax.naming.directory.BasicAttribute;
47  import javax.naming.directory.BasicAttributes;
48  import javax.naming.directory.DirContext;
49  import javax.naming.directory.ModificationItem;
50  import javax.naming.ldap.LdapContext;
51  import java.util.Map;
52  
53  
54  /**
55   * A test case which tests the correct operation of the schema 
56   * entity handler.  
57   *
58   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
59   * @version $Rev$
60   */
61  @RunWith ( CiRunner.class )
62  public class MetaSchemaHandlerIT
63  {
64      /** the schema to use for this test: one that is not loaded by default */
65      private static final String TEST_SCHEMA = "nis";
66      /** a test attribute in the test schema: uidNumber in nis schema */
67      private static final String TEST_ATTR_OID = "1.3.6.1.1.1.1.0";
68      /** the name of the dummy schema to test metaSchema adds/deletes with */
69      private static final String DUMMY_SCHEMA = "dummy";
70      
71  
72      public static DirectoryService service;
73  
74  
75      private static AttributeTypeRegistry getAttributeTypeRegistry()
76      {
77          return service.getRegistries().getAttributeTypeRegistry();
78      }
79  
80  
81      private static Map<String, Schema> getLoadedSchemas()
82      {
83          return service.getRegistries().getLoadedSchemas();
84      }
85  
86  
87      @Before
88      public void checkSambaSchema() throws Exception
89      {
90          LdapContext schemaRoot = getSchemaContext( service );
91  
92          // check that there is a samba schema installed and that is is disabled
93          Attributes attributes = schemaRoot.getAttributes( "cn=samba" );
94          assertNotNull( attributes );
95          assertTrue( attributes.get( MetaSchemaConstants.M_DISABLED_AT ).contains( "TRUE" ) );
96          attributes = schemaRoot.getAttributes( "ou=attributeTypes,cn=samba" );
97          assertNotNull( attributes );
98          assertTrue( attributes.get( SchemaConstants.OU_AT ).contains( "attributetypes" ) );
99      }
100 
101 
102     // -----------------------------------------------------------------------
103     // Schema Add Tests
104     // -----------------------------------------------------------------------
105 
106     
107     /**
108      * Tests the addition of a new metaSchema object that is disabled 
109      * on addition and has no dependencies.
110      *
111      * @throws Exception on error
112      */
113     @Test
114     public void testAddDisabledSchemaNoDeps() throws Exception
115     {
116         LdapContext schemaRoot = getSchemaContext( service );
117         Attributes dummySchema = new BasicAttributes( "objectClass", "top", true );
118         dummySchema.get( "objectClass" ).add( MetaSchemaConstants.META_SCHEMA_OC );
119         dummySchema.put( "cn", DUMMY_SCHEMA );
120         dummySchema.put( MetaSchemaConstants.M_DISABLED_AT, "TRUE" );
121         schemaRoot.createSubcontext( "cn=" + DUMMY_SCHEMA, dummySchema );
122         
123         assertNull( getLoadedSchemas().get( DUMMY_SCHEMA ) );
124         assertNotNull( schemaRoot.lookup( "cn=" + DUMMY_SCHEMA ) );
125     }
126     
127     
128     /**
129      * Tests the addition of a new metaSchema object that is disabled 
130      * on addition and has dependencies.
131      *
132      * @throws Exception on error
133      */
134     @Test
135     public void testAddDisabledSchemaWithDeps() throws Exception
136     {
137         LdapContext schemaRoot = getSchemaContext( service );
138         Attributes dummySchema = new BasicAttributes( "objectClass", "top", true );
139         dummySchema.get( "objectClass" ).add( MetaSchemaConstants.META_SCHEMA_OC );
140         dummySchema.put( "cn", DUMMY_SCHEMA );
141         dummySchema.put( MetaSchemaConstants.M_DISABLED_AT, "TRUE" );
142         dummySchema.put( MetaSchemaConstants.M_DEPENDENCIES_AT, TEST_SCHEMA );
143         dummySchema.get( MetaSchemaConstants.M_DEPENDENCIES_AT ).add( "core" );
144         schemaRoot.createSubcontext( "cn=" + DUMMY_SCHEMA, dummySchema );
145         
146         assertNull( getLoadedSchemas().get( DUMMY_SCHEMA ) );
147         assertNotNull( schemaRoot.lookup( "cn=" + DUMMY_SCHEMA ) );
148     }
149     
150     
151     /**
152      * Tests the rejection of a new metaSchema object that is disabled 
153      * on addition and has missing dependencies.
154      *
155      * @throws Exception on error
156      */
157     @Test
158     public void testRejectDisabledSchemaAddWithMissingDeps() throws Exception
159     {
160         LdapContext schemaRoot = getSchemaContext( service );
161         Attributes dummySchema = new BasicAttributes( "objectClass", "top", true );
162         dummySchema.get( "objectClass" ).add( MetaSchemaConstants.META_SCHEMA_OC );
163         dummySchema.put( "cn", DUMMY_SCHEMA );
164         dummySchema.put( MetaSchemaConstants.M_DISABLED_AT, "TRUE" );
165         dummySchema.put( MetaSchemaConstants.M_DEPENDENCIES_AT, "missing" );
166         dummySchema.get( MetaSchemaConstants.M_DEPENDENCIES_AT ).add( "core" );
167         
168         try
169         {
170             schemaRoot.createSubcontext( "cn=" + DUMMY_SCHEMA, dummySchema );
171         } 
172         catch( LdapOperationNotSupportedException e )
173         {
174             assertTrue( e.getResultCode().equals( ResultCodeEnum.UNWILLING_TO_PERFORM ) );
175         }
176         
177         assertNull( getLoadedSchemas().get( DUMMY_SCHEMA ) );
178 
179         //noinspection EmptyCatchBlock
180         try
181         {
182             schemaRoot.lookup( "cn=" + DUMMY_SCHEMA );
183             fail( "schema should not be added to schema partition" );
184         }
185         catch( NamingException e )
186         {
187         }
188     }
189     
190     
191     /**
192      * Tests the addition of a new metaSchema object that is enabled 
193      * on addition and has no dependencies.
194      *
195      * @throws Exception on error
196      */
197     @Test
198     public void testAddEnabledSchemaNoDeps() throws Exception
199     {
200         LdapContext schemaRoot = getSchemaContext( service );
201         Attributes dummySchema = new BasicAttributes( "objectClass", "top", true );
202         dummySchema.get( "objectClass" ).add( MetaSchemaConstants.META_SCHEMA_OC );
203         dummySchema.put( "cn", DUMMY_SCHEMA );
204         schemaRoot.createSubcontext( "cn=" + DUMMY_SCHEMA, dummySchema );
205         
206         assertNotNull( getLoadedSchemas().get( DUMMY_SCHEMA ) );
207         assertNotNull( schemaRoot.lookup( "cn=" + DUMMY_SCHEMA ) );
208     }
209     
210     
211     /**
212      * Tests the rejection of a metaSchema object add that is enabled 
213      * on addition yet has disabled dependencies.
214      *
215      * @throws Exception on error
216      */
217     @Test
218     public void testRejectEnabledSchemaAddWithDisabledDeps() throws Exception
219     {
220         LdapContext schemaRoot = getSchemaContext( service );
221         Attributes dummySchema = new BasicAttributes( "objectClass", "top", true );
222         dummySchema.get( "objectClass" ).add( MetaSchemaConstants.META_SCHEMA_OC );
223         dummySchema.put( "cn", DUMMY_SCHEMA );
224         dummySchema.put( MetaSchemaConstants.M_DEPENDENCIES_AT, TEST_SCHEMA );
225         
226         try
227         {
228             schemaRoot.createSubcontext( "cn=" + DUMMY_SCHEMA, dummySchema );
229             fail( "should not be able to add enabled schema with deps on disabled schemas" );
230         }
231         catch( LdapOperationNotSupportedException e )
232         {
233             assertTrue( e.getResultCode().equals( ResultCodeEnum.UNWILLING_TO_PERFORM ) );
234         }
235         
236         assertNull( getLoadedSchemas().get( DUMMY_SCHEMA ) );
237 
238         //noinspection EmptyCatchBlock
239         try
240         {
241             schemaRoot.lookup( "cn=" + DUMMY_SCHEMA );
242             fail( "schema should not be added to schema partition" );
243         }
244         catch( NamingException e )
245         {
246         }
247     }
248 
249     
250     // -----------------------------------------------------------------------
251     // Schema Delete Tests
252     // -----------------------------------------------------------------------
253 
254     
255     /**
256      * Makes sure we can delete schemas that have no dependents.
257      *
258      * @throws Exception on error
259      */
260     @Test
261     public void testDeleteSchemaNoDependents() throws Exception
262     {
263         LdapContext schemaRoot = getSchemaContext( service );
264 
265         // add the dummy schema enabled 
266         testAddEnabledSchemaNoDeps();
267         assertNotNull( getLoadedSchemas().get( DUMMY_SCHEMA ) );
268         
269         // delete it now
270         schemaRoot.destroySubcontext( "cn=" + DUMMY_SCHEMA );
271         assertNull( getLoadedSchemas().get( DUMMY_SCHEMA ) );
272     }
273     
274     
275     /**
276      * Makes sure we can NOT delete schemas that have dependents.
277      *
278      * @throws Exception on error
279      */
280     @Test
281     public void testRejectSchemaDeleteWithDependents() throws Exception
282     {
283         LdapContext schemaRoot = getSchemaContext( service );
284 
285         // add the dummy schema enabled
286         testAddEnabledSchemaNoDeps();
287         assertNotNull( getLoadedSchemas().get( DUMMY_SCHEMA ) );
288         
289         // make the nis schema depend on the dummy schema
290         ModificationItem[] mods = new ModificationItem[1];
291         mods[0] = new ModificationItem( DirContext.ADD_ATTRIBUTE,
292                 new BasicAttribute( MetaSchemaConstants.M_DEPENDENCIES_AT, DUMMY_SCHEMA ) );
293         schemaRoot.modifyAttributes( "cn=" + TEST_SCHEMA, mods );
294         
295         // attempt to delete it now & it should fail
296         try
297         {
298             schemaRoot.destroySubcontext( "cn=" + DUMMY_SCHEMA );
299             fail( "should not be able to delete a schema with dependents" );
300         }
301         catch ( LdapOperationNotSupportedException e )
302         {
303             assertTrue( e.getResultCode().equals( ResultCodeEnum.UNWILLING_TO_PERFORM ) );
304         }
305 
306         assertNotNull( getLoadedSchemas().get( DUMMY_SCHEMA ) );
307     }
308     
309     
310     /**
311      * Tests the rejection of a new metaSchema object that is enabled 
312      * on addition and missing dependencies.
313      *
314      * @throws Exception on error
315      */
316     @Test
317     public void testRejectEnabledSchemaAddWithMisingDeps() throws Exception
318     {
319         LdapContext schemaRoot = getSchemaContext( service );
320 
321         Attributes dummySchema = new BasicAttributes( "objectClass", "top", true );
322         dummySchema.get( "objectClass" ).add( MetaSchemaConstants.META_SCHEMA_OC );
323         dummySchema.put( "cn", DUMMY_SCHEMA );
324         dummySchema.put( MetaSchemaConstants.M_DEPENDENCIES_AT, "missing" );
325         
326         try
327         {
328             schemaRoot.createSubcontext( "cn=" + DUMMY_SCHEMA, dummySchema );
329             fail( "should not be able to add enabled schema with deps on missing schemas" );
330         }
331         catch( LdapOperationNotSupportedException e )
332         {
333             assertTrue( e.getResultCode().equals( ResultCodeEnum.UNWILLING_TO_PERFORM ) );
334         }
335         
336         assertNull( getLoadedSchemas().get( DUMMY_SCHEMA ) );
337 
338         //noinspection EmptyCatchBlock
339         try
340         {
341             schemaRoot.lookup( "cn=" + DUMMY_SCHEMA );
342             fail( "schema should not be added to schema partition" );
343         }
344         catch( NamingException e )
345         {
346         }
347     }
348 
349     
350     // -----------------------------------------------------------------------
351     // Enable/Disable Schema Tests
352     // -----------------------------------------------------------------------
353 
354     
355     private void enableSchema( String schemaName ) throws Exception
356     {
357         LdapContext schemaRoot = getSchemaContext( service );
358 
359         // now enable the test schema
360         ModificationItem[] mods = new ModificationItem[1];
361         Attribute attr = new BasicAttribute( "m-disabled", "FALSE" );
362         mods[0] = new ModificationItem( DirContext.REPLACE_ATTRIBUTE, attr );
363         schemaRoot.modifyAttributes( "cn=" + schemaName, mods );
364     }
365     
366     
367     private void disableSchema( String schemaName ) throws Exception
368     {
369         LdapContext schemaRoot = getSchemaContext( service );
370 
371         // now enable the test schema
372         ModificationItem[] mods = new ModificationItem[1];
373         Attribute attr = new BasicAttribute( "m-disabled", "TRUE" );
374         mods[0] = new ModificationItem( DirContext.REPLACE_ATTRIBUTE, attr );
375         schemaRoot.modifyAttributes( "cn=" + schemaName, mods );
376     }
377     
378     
379     /**
380      * Checks to make sure updates enabling a metaSchema object in
381      * the schema partition triggers the loading of that schema into
382      * the global registries.
383      *
384      * @throws Exception on error
385      */
386     @Test
387     public void testEnableSchema() throws Exception
388     {
389         AttributeTypeRegistry atr = getAttributeTypeRegistry();
390         
391         // check that the nis schema is not loaded
392         assertNull( getLoadedSchemas().get( TEST_SCHEMA ) );
393         
394         // double check and make sure an attribute from that schema is 
395         // not in the AttributeTypeRegistry
396         assertFalse( atr.hasAttributeType( TEST_ATTR_OID ) );
397         
398         // now enable the test schema
399         enableSchema( "nis" );
400         
401         // now test that the schema is loaded 
402         assertNotNull( getLoadedSchemas().get( TEST_SCHEMA ) );
403         
404         // double check and make sure the test attribute from the 
405         // test schema is now loaded and present within the attr registry
406         assertTrue( atr.hasAttributeType( TEST_ATTR_OID ) );
407     }
408 
409 
410     /**
411      * Checks to make sure an attempt to disable a metaSchema fails if 
412      * that schema has dependents which are enabled.
413      *
414      * @throws Exception on error
415      */
416     @Test
417     public void testDisableSchema() throws Exception
418     {
419         // let's enable the test schema
420         testEnableSchema();
421         
422         AttributeTypeRegistry atr = getAttributeTypeRegistry();
423         
424         // check that the nis schema is loaded
425         assertNotNull( getLoadedSchemas().get( TEST_SCHEMA ) );
426         
427         // double check and make sure an attribute from that schema is 
428         // in the AttributeTypeRegistry
429         assertTrue( atr.hasAttributeType( TEST_ATTR_OID ) );
430         
431         // now disable the test schema 
432         disableSchema( "samba" );
433         disableSchema( "nis" );
434         
435         // now test that the schema is NOT loaded 
436         assertNull( getLoadedSchemas().get( TEST_SCHEMA ) );
437         
438         // double check and make sure the test attribute from the test  
439         // schema is now NOT loaded and present within the attr registry
440         assertFalse( atr.hasAttributeType( TEST_ATTR_OID ) );
441     }
442 
443     
444     /**
445      * Checks to make sure updates disabling a metaSchema object in
446      * the schema partition triggers the unloading of that schema from
447      * the global registries.
448      *
449      * @throws Exception on error
450      */
451     @Test
452     public void testDisableSchemaWithEnabledDependents() throws Exception
453     {
454         LdapContext schemaRoot = getSchemaContext( service );
455 
456         // let's enable the test schema and add the dummy schema
457         // as enabled by default and dependends on the test schema
458         
459 //      // enables the test schema and samba
460         testEnableSchema(); 
461         
462         // adds enabled dummy schema that depends on the test schema  
463         Attributes dummySchema = new BasicAttributes( "objectClass", "top", true );
464         dummySchema.get( "objectClass" ).add( MetaSchemaConstants.META_SCHEMA_OC );
465         dummySchema.put( "cn", DUMMY_SCHEMA );
466         dummySchema.put( MetaSchemaConstants.M_DEPENDENCIES_AT, TEST_SCHEMA );
467         schemaRoot.createSubcontext( "cn=" + DUMMY_SCHEMA, dummySchema );
468         
469         // check that the nis schema is loaded and the dummy schema is loaded
470         assertNotNull( getLoadedSchemas().get( TEST_SCHEMA ) );
471         assertNotNull( getLoadedSchemas().get( DUMMY_SCHEMA ) );
472         
473         AttributeTypeRegistry atr = getAttributeTypeRegistry();
474         
475         // double check and make sure an attribute from that schema is 
476         // in the AttributeTypeRegistry
477         assertTrue( atr.hasAttributeType( TEST_ATTR_OID ) );
478         
479         // now try to disable the test schema which should fail 
480         // since it's dependent, the dummy schema, is enabled
481         ModificationItem[] mods = new ModificationItem[1];
482         Attribute attr = new BasicAttribute( "m-disabled", "TRUE" );
483         mods[0] = new ModificationItem( DirContext.REPLACE_ATTRIBUTE, attr );
484         
485         try
486         {
487             schemaRoot.modifyAttributes( "cn=nis", mods );
488             fail( "attempt to disable schema with enabled dependents should fail" );
489         }
490         catch ( LdapOperationNotSupportedException e )
491         {
492             assertTrue( e.getResultCode().equals( ResultCodeEnum.UNWILLING_TO_PERFORM ) );
493         }
494         
495         // now test that both schema are still loaded 
496         assertNotNull( getLoadedSchemas().get( TEST_SCHEMA ) );
497         assertNotNull( getLoadedSchemas().get( DUMMY_SCHEMA ) );
498         
499         // double check and make sure the test attribute from the test  
500         // schema is still loaded and present within the attr registry
501         assertTrue( atr.hasAttributeType( TEST_ATTR_OID ) );
502     }
503     
504     
505     // -----------------------------------------------------------------------
506     // Schema Rename Tests
507     // -----------------------------------------------------------------------
508 
509 
510     /**
511      * Makes sure we can change the name of a schema with entities in it.
512      * Will use the samba schema which comes out of the box and nothing 
513      * depends on.
514      *
515      * @throws Exception on error
516      */
517     @Test
518     public void testSchemaRenameDisabledSchema() throws Exception
519     {
520         LdapContext schemaRoot = getSchemaContext( service );
521         schemaRoot.rename( "cn=samba", "cn=foo" );
522         assertNotNull( schemaRoot.lookup( "cn=foo" ) );
523 
524         // check that there is a samba schema installed and that is is disabled
525         Attributes attributes = schemaRoot.getAttributes( "cn=foo" );
526         assertNotNull( attributes );
527         assertTrue( attributes.get( MetaSchemaConstants.M_DISABLED_AT ).contains( "TRUE" ) );
528         attributes = schemaRoot.getAttributes( "ou=attributeTypes,cn=foo" );
529         assertNotNull( attributes );
530         assertTrue( attributes.get( SchemaConstants.OU_AT ).contains( "attributetypes" ) );
531 
532         //noinspection EmptyCatchBlock
533         try
534         {
535             schemaRoot.lookup( "cn=samba" );
536             fail( "the samba schema should not be present after a rename to foo" );
537         }
538         catch( LdapNameNotFoundException e )
539         {
540         }
541     }
542 
543 
544     /**
545      * Makes sure we can NOT change the name of a schema that has dependents.
546      * Will use the nis schema which comes out of the box and has samba as
547      * it's dependent.
548      *
549      * @throws Exception on error
550      */
551     @Test
552     public void testRejectSchemaRenameWithDeps() throws Exception
553     {
554         LdapContext schemaRoot = getSchemaContext( service );
555         try
556         {
557             schemaRoot.rename( "cn=nis", "cn=foo" );
558             fail( "should not be able to rename nis which has samba as it's dependent" );
559         }
560         catch ( LdapOperationNotSupportedException e )
561         {
562             assertEquals( ResultCodeEnum.UNWILLING_TO_PERFORM, e.getResultCode() );
563         }
564         
565         assertNotNull( schemaRoot.lookup( "cn=nis" ) );
566 
567         //noinspection EmptyCatchBlock
568         try
569         {
570             schemaRoot.lookup( "cn=foo" );
571             fail( "the foo schema should not be present after rejecting the rename" );
572         }
573         catch( LdapNameNotFoundException e )
574         {
575         }
576     }
577 
578 
579     /**
580      * Makes sure we can change the name of a schema with entities in it.
581      * Will use the samba schema which comes out of the box and nothing 
582      * depends on.
583      *
584      * @throws Exception on error
585      */
586     @Test
587     public void testSchemaRenameEnabledSchema() throws Exception
588     {
589         LdapContext schemaRoot = getSchemaContext( service );
590 
591         enableSchema( "samba" );
592         assertTrue( getAttributeTypeRegistry().hasAttributeType( "sambaNTPassword" ) );
593         assertEquals( "samba", getAttributeTypeRegistry().getSchemaName( "sambaNTPassword" ) );
594         
595         schemaRoot.rename( "cn=samba", "cn=foo" );
596         assertNotNull( schemaRoot.lookup( "cn=foo" ) );
597         assertTrue( getAttributeTypeRegistry().hasAttributeType( "sambaNTPassword" ) );
598         assertEquals( "foo", getAttributeTypeRegistry().getSchemaName( "sambaNTPassword" ) );
599 
600         //noinspection EmptyCatchBlock
601         try
602         {
603             schemaRoot.lookup( "cn=samba" );
604             fail( "the samba schema should not be present after a rename to foo" );
605         }
606         catch( LdapNameNotFoundException e )
607         {
608         }
609     }
610 
611 
612     // -----------------------------------------------------------------------
613     // Dependency Modify Tests
614     // -----------------------------------------------------------------------
615 
616 
617     /**
618      * Checks to make sure the addition of an undefined schema to the dependencies 
619      * of an existing schema fail with an UNWILLING_TO_PERFORM result code.
620      *
621      * @throws Exception on error
622      */
623     @Test
624     public void testRejectAddBogusDependency() throws Exception
625     {
626         LdapContext schemaRoot = getSchemaContext( service );
627 
628         ModificationItem[] mods = new ModificationItem[1];
629         Attribute attr = new BasicAttribute( "m-dependencies", "bogus" );
630         mods[0] = new ModificationItem( DirContext.ADD_ATTRIBUTE, attr );
631         
632         try
633         {
634             schemaRoot.modifyAttributes( "cn=" + TEST_SCHEMA, mods );
635             fail( "Should not be able to add bogus dependency to schema" );
636         }
637         catch ( LdapOperationNotSupportedException e )
638         {
639             assertEquals( ResultCodeEnum.UNWILLING_TO_PERFORM, e.getResultCode() );
640         }
641     }
642 
643 
644     /**
645      * Checks to make sure the addition of an defined yet disabled schema to the 
646      * dependencies of an existing enabled schema fails with an UNWILLING_TO_PERFORM 
647      * result code.  You must enable the dependency to add it or disable the schema 
648      * depending on it to add it.
649      *
650      * @throws Exception on error
651      */
652     @Test
653     public void testRejectAddOfDisabledDependencyToEnabledSchema() throws Exception
654     {
655         LdapContext schemaRoot = getSchemaContext( service );
656         enableSchema( TEST_SCHEMA );
657         ModificationItem[] mods = new ModificationItem[1];
658         Attribute attr = new BasicAttribute( "m-dependencies", "mozilla" );
659         mods[0] = new ModificationItem( DirContext.ADD_ATTRIBUTE, attr );
660         
661         try
662         {
663             schemaRoot.modifyAttributes( "cn=" + TEST_SCHEMA, mods );
664             fail( "Should not be able to add disabled dependency to schema" );
665         }
666         catch ( LdapOperationNotSupportedException e )
667         {
668             assertEquals( ResultCodeEnum.UNWILLING_TO_PERFORM, e.getResultCode() );
669         }
670     }
671 
672 
673     /**
674      * Checks to make sure the addition of an defined yet disabled schema to the 
675      * dependencies of an existing disabled schema succeeds. 
676      *
677      * @throws Exception on error
678      */
679     @Test
680     public void testAddOfDisabledDependencyToDisabledSchema() throws Exception
681     {
682         LdapContext schemaRoot = getSchemaContext( service );
683         ModificationItem[] mods = new ModificationItem[1];
684         Attribute attr = new BasicAttribute( "m-dependencies", "mozilla" );
685         mods[0] = new ModificationItem( DirContext.ADD_ATTRIBUTE, attr );
686         schemaRoot.modifyAttributes( "cn=" + TEST_SCHEMA, mods );
687         Attributes attrs = schemaRoot.getAttributes( "cn=" + TEST_SCHEMA );
688         Attribute dependencies = attrs.get( "m-dependencies" );
689         assertTrue( dependencies.contains( "mozilla" ) );
690     }
691 
692 
693     /**
694      * Checks to make sure the addition of an defined yet enabled schema to the 
695      * dependencies of an existing disabled schema succeeds.
696      *
697      * @throws Exception on error
698      */
699     @Test
700     public void testAddOfEnabledDependencyToDisabledSchema() throws Exception
701     {
702         LdapContext schemaRoot = getSchemaContext( service );
703         ModificationItem[] mods = new ModificationItem[1];
704         Attribute attr = new BasicAttribute( "m-dependencies", "java" );
705         mods[0] = new ModificationItem( DirContext.ADD_ATTRIBUTE, attr );
706         schemaRoot.modifyAttributes( "cn=" + TEST_SCHEMA, mods );
707         Attributes attrs = schemaRoot.getAttributes( "cn=" + TEST_SCHEMA );
708         Attribute dependencies = attrs.get( "m-dependencies" );
709         assertTrue( dependencies.contains( "java" ) );
710     }
711 }