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.core.DirectoryService;
24  import org.apache.directory.server.core.integ.CiRunner;
25  import static org.apache.directory.server.core.integ.IntegrationUtils.getSchemaContext;
26  import org.apache.directory.server.schema.registries.ObjectClassRegistry;
27  import org.apache.directory.shared.ldap.exception.LdapInvalidNameException;
28  import org.apache.directory.shared.ldap.exception.LdapOperationNotSupportedException;
29  import org.apache.directory.shared.ldap.message.ResultCodeEnum;
30  import org.apache.directory.shared.ldap.name.LdapDN;
31  import org.apache.directory.shared.ldap.schema.ObjectClass;
32  import org.junit.Test;
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.fail;
37  import org.junit.runner.RunWith;
38  
39  import javax.naming.NamingException;
40  import javax.naming.directory.Attribute;
41  import javax.naming.directory.Attributes;
42  import javax.naming.directory.BasicAttribute;
43  import javax.naming.directory.BasicAttributes;
44  import javax.naming.directory.DirContext;
45  import javax.naming.directory.ModificationItem;
46  
47  
48  /**
49   * A test case which tests the addition of various schema elements
50   * to the ldap server.
51   *
52   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
53   * @version $Rev$
54   */
55  @RunWith ( CiRunner.class )
56  public class MetaObjectClassHandlerIT
57  {
58      private static final String NAME = "testObjectClass";
59      private static final String NEW_NAME = "alternateName";
60      private static final String DEPENDEE_NAME = "dependeeName";
61  
62      private static final String DESCRIPTION0 = "A test objectClass";
63      private static final String DESCRIPTION1 = "An alternate description";
64      
65      private static final String OID = "1.3.6.1.4.1.18060.0.4.0.3.100000";
66      private static final String NEW_OID = "1.3.6.1.4.1.18060.0.4.0.3.100001";
67      private static final String DEPENDEE_OID = "1.3.6.1.4.1.18060.0.4.0.3.100002";
68  
69  
70      public static DirectoryService service;
71  
72      
73      /**
74       * Gets relative DN to ou=schema.
75       *
76       * @param schemaName the name of the schema
77       * @return the dn of the container which contains objectClasses
78       * @throws Exception on error
79       */
80      private LdapDN getObjectClassContainer( String schemaName ) throws Exception
81      {
82          return new LdapDN( "ou=objectClasses,cn=" + schemaName );
83      }
84  
85  
86      private static ObjectClassRegistry getObjectClassRegistry()
87      {
88          return service.getRegistries().getObjectClassRegistry();
89      }
90      
91      
92      private void addObjectClass() throws Exception
93      {
94          Attributes attrs = new BasicAttributes( true );
95          Attribute oc = new BasicAttribute( "objectClass", "top" );
96          oc.add( "metaTop" );
97          oc.add( "metaObjectClass" );
98          attrs.put( oc );
99          attrs.put( "m-oid", OID );
100         attrs.put( "m-name", NAME);
101         attrs.put( "m-description", DESCRIPTION0 );
102         attrs.put( "m-typeObjectClass", "AUXILIARY" );
103         attrs.put( "m-must", "cn" );
104         attrs.put( "m-may", "ou" );
105         
106         LdapDN dn = getObjectClassContainer( "apachemeta" );
107         dn.add( "m-oid" + "=" + OID );
108         getSchemaContext( service ).createSubcontext( dn, attrs );
109     }
110 
111     
112     // ----------------------------------------------------------------------
113     // Test all core methods with normal operational pathways
114     // ----------------------------------------------------------------------
115 
116 
117     @Test
118     public void testAddObjectClass() throws Exception
119     {
120         addObjectClass();
121         
122         assertTrue( getObjectClassRegistry().hasObjectClass( OID ) );
123         assertEquals( getObjectClassRegistry().getSchemaName( OID ), "apachemeta" );
124     }
125     
126     
127     @Test
128     public void testDeleteAttributeType() throws Exception
129     {
130         LdapDN dn = getObjectClassContainer( "apachemeta" );
131         dn.add( "m-oid" + "=" + OID );
132         addObjectClass();
133         
134         getSchemaContext( service ).destroySubcontext( dn );
135 
136         assertFalse( "objectClass should be removed from the registry after being deleted", 
137             getObjectClassRegistry().hasObjectClass( OID ) );
138 
139         //noinspection EmptyCatchBlock
140         try
141         {
142             getObjectClassRegistry().lookup( OID );
143             fail( "objectClass lookup should fail after deleting it" );
144         }
145         catch( NamingException e )
146         {
147         }
148     }
149 
150 
151     @Test
152     public void testRenameAttributeType() throws Exception
153     {
154         LdapDN dn = getObjectClassContainer( "apachemeta" );
155         dn.add( "m-oid" + "=" + OID );
156         addObjectClass();
157         
158         LdapDN newdn = getObjectClassContainer( "apachemeta" );
159         newdn.add( "m-oid" + "=" + NEW_OID );
160         getSchemaContext( service ).rename( dn, newdn );
161 
162         assertFalse( "old objectClass OID should be removed from the registry after being renamed", 
163             getObjectClassRegistry().hasObjectClass( OID ) );
164 
165         //noinspection EmptyCatchBlock
166         try
167         {
168             getObjectClassRegistry().lookup( OID );
169             fail( "objectClass lookup should fail after renaming the objectClass" );
170         }
171         catch( NamingException e )
172         {
173         }
174 
175         assertTrue( getObjectClassRegistry().hasObjectClass( NEW_OID ) );
176     }
177 
178 
179     @Test
180     public void testMoveAttributeType() throws Exception
181     {
182         addObjectClass();
183         
184         LdapDN dn = getObjectClassContainer( "apachemeta" );
185         dn.add( "m-oid" + "=" + OID );
186 
187         LdapDN newdn = getObjectClassContainer( "apache" );
188         newdn.add( "m-oid" + "=" + OID );
189         
190         getSchemaContext( service ).rename( dn, newdn );
191 
192         assertTrue( "objectClass OID should still be present", 
193             getObjectClassRegistry().hasObjectClass( OID ) );
194         
195         assertEquals( "objectClass schema should be set to apache not apachemeta", 
196             getObjectClassRegistry().getSchemaName( OID ), "apache" );
197     }
198 
199 
200     @Test
201     public void testMoveObjectClassAndChangeRdn() throws Exception
202     {
203         addObjectClass();
204         
205         LdapDN dn = getObjectClassContainer( "apachemeta" );
206         dn.add( "m-oid" + "=" + OID );
207 
208         LdapDN newdn = getObjectClassContainer( "apache" );
209         newdn.add( "m-oid" + "=" + NEW_OID );
210         
211         getSchemaContext( service ).rename( dn, newdn );
212 
213         assertFalse( "old objectClass OID should NOT be present", 
214             getObjectClassRegistry().hasObjectClass( OID ) );
215         
216         assertTrue( "new objectClass OID should be present", 
217             getObjectClassRegistry().hasObjectClass( NEW_OID ) );
218         
219         assertEquals( "objectClass with new oid should have schema set to apache NOT apachemeta", 
220             getObjectClassRegistry().getSchemaName( NEW_OID ), "apache" );
221     }
222 
223     
224     @Test
225     public void testModifyAttributeTypeWithModificationItems() throws Exception
226     {
227         addObjectClass();
228         
229         ObjectClass oc = getObjectClassRegistry().lookup( OID );
230         assertEquals( oc.getDescription(), DESCRIPTION0 );
231         assertEquals( oc.getName(), NAME );
232 
233         LdapDN dn = getObjectClassContainer( "apachemeta" );
234         dn.add( "m-oid" + "=" + OID );
235         
236         ModificationItem[] mods = new ModificationItem[2];
237         Attribute attr = new BasicAttribute( "m-description", DESCRIPTION1 );
238         mods[0] = new ModificationItem( DirContext.REPLACE_ATTRIBUTE, attr );
239         attr = new BasicAttribute( "m-name", NEW_NAME );
240         mods[1] = new ModificationItem( DirContext.REPLACE_ATTRIBUTE, attr );
241         getSchemaContext( service ).modifyAttributes( dn, mods );
242 
243         assertTrue( "objectClass OID should still be present", 
244             getObjectClassRegistry().hasObjectClass( OID ) );
245         
246         assertEquals( "objectClass schema should be set to apachemeta", 
247             getObjectClassRegistry().getSchemaName( OID ), "apachemeta" );
248         
249         oc = getObjectClassRegistry().lookup( OID );
250         assertEquals( oc.getDescription(), DESCRIPTION1 );
251         assertEquals( oc.getName(), NEW_NAME );
252     }
253 
254     
255     @Test
256     public void testModifyAttributeTypeWithAttributes() throws Exception
257     {
258         addObjectClass();
259         
260         ObjectClass oc = getObjectClassRegistry().lookup( OID );
261         assertEquals( oc.getDescription(), DESCRIPTION0 );
262         assertEquals( oc.getName(), NAME );
263 
264         LdapDN dn = getObjectClassContainer( "apachemeta" );
265         dn.add( "m-oid" + "=" + OID );
266         
267         Attributes mods = new BasicAttributes( true );
268         mods.put( "m-description", DESCRIPTION1 );
269         mods.put( "m-name", NEW_NAME );
270         getSchemaContext( service ).modifyAttributes( dn, DirContext.REPLACE_ATTRIBUTE, mods );
271 
272         assertTrue( "objectClass OID should still be present", 
273             getObjectClassRegistry().hasObjectClass( OID ) );
274         
275         assertEquals( "objectClass schema should be set to apachemeta", 
276             getObjectClassRegistry().getSchemaName( OID ), "apachemeta" );
277 
278         oc = getObjectClassRegistry().lookup( OID );
279         assertEquals( oc.getDescription(), DESCRIPTION1 );
280         assertEquals( oc.getName(), NEW_NAME );
281     }
282     
283 
284     // ----------------------------------------------------------------------
285     // Test move, rename, and delete when a OC exists and uses the OC as sup
286     // ----------------------------------------------------------------------
287     private void addDependeeObjectClass() throws Exception
288     {
289         Attributes attrs = new BasicAttributes( true );
290         Attribute oc = new BasicAttribute( "objectClass", "top" );
291         oc.add( "metaTop" );
292         oc.add( "metaObjectClass" );
293         attrs.put( oc );
294         attrs.put( "m-oid", DEPENDEE_OID );
295         attrs.put( "m-name", DEPENDEE_NAME );
296         attrs.put( "m-description", DESCRIPTION0 );
297         attrs.put( "m-typeObjectClass", "AUXILIARY" );
298         attrs.put( "m-must", "cn" );
299         attrs.put( "m-may", "ou" );
300         attrs.put( "m-supObjectClass", OID );
301         
302         LdapDN dn = getObjectClassContainer( "apachemeta" );
303         dn.add( "m-oid" + "=" + DEPENDEE_OID );
304         getSchemaContext( service ).createSubcontext( dn, attrs );
305         
306         assertTrue( getObjectClassRegistry().hasObjectClass( DEPENDEE_OID ) );
307         assertEquals( getObjectClassRegistry().getSchemaName( DEPENDEE_OID ), "apachemeta" );
308     }
309 
310     
311     @Test
312     public void testDeleteObjectClassWhenInUse() throws Exception
313     {
314         LdapDN dn = getObjectClassContainer( "apachemeta" );
315         dn.add( "m-oid" + "=" + OID );
316         addObjectClass();
317         addDependeeObjectClass();
318         
319         try
320         {
321             getSchemaContext( service ).destroySubcontext( dn );
322             fail( "should not be able to delete a objectClass in use" );
323         }
324         catch( LdapOperationNotSupportedException e ) 
325         {
326             assertEquals( e.getResultCode(), ResultCodeEnum.UNWILLING_TO_PERFORM );
327         }
328 
329         assertTrue( "objectClass should still be in the registry after delete failure", 
330             getObjectClassRegistry().hasObjectClass( OID ) );
331     }
332     
333     
334     @Test
335     public void testMoveObjectClassWhenInUse() throws Exception
336     {
337         addObjectClass();
338         addDependeeObjectClass();
339         
340         LdapDN dn = getObjectClassContainer( "apachemeta" );
341         dn.add( "m-oid" + "=" + OID );
342 
343         LdapDN newdn = getObjectClassContainer( "apache" );
344         newdn.add( "m-oid" + "=" + OID );
345         
346         try
347         {
348             getSchemaContext( service ).rename( dn, newdn );
349             fail( "should not be able to move a objectClass in use" );
350         }
351         catch( LdapOperationNotSupportedException e ) 
352         {
353             assertEquals( e.getResultCode(), ResultCodeEnum.UNWILLING_TO_PERFORM );
354         }
355 
356         assertTrue( "objectClass should still be in the registry after move failure", 
357             getObjectClassRegistry().hasObjectClass( OID ) );
358     }
359 
360 
361     @Test
362     public void testMoveObjectClassAndChangeRdnWhenInUse() throws Exception
363     {
364         addObjectClass();
365         addDependeeObjectClass();
366         
367         LdapDN dn = getObjectClassContainer( "apachemeta" );
368         dn.add( "m-oid" + "=" + OID );
369 
370         LdapDN newdn = getObjectClassContainer( "apache" );
371         newdn.add( "m-oid" + "=" + NEW_OID );
372         
373         try
374         {
375             getSchemaContext( service ).rename( dn, newdn );
376             fail( "should not be able to move an objectClass in use" );
377         }
378         catch( LdapOperationNotSupportedException e ) 
379         {
380             assertEquals( e.getResultCode(), ResultCodeEnum.UNWILLING_TO_PERFORM );
381         }
382 
383         assertTrue( "ObjectClass should still be in the registry after move failure", 
384             getObjectClassRegistry().hasObjectClass( OID ) );
385     }
386 
387     
388     @Test
389     public void testRenameObjectClassWhenInUse() throws Exception
390     {
391         LdapDN dn = getObjectClassContainer( "apachemeta" );
392         dn.add( "m-oid" + "=" + OID );
393         addObjectClass();
394         addDependeeObjectClass();
395         
396         LdapDN newdn = getObjectClassContainer( "apachemeta" );
397         newdn.add( "m-oid" + "=" + NEW_OID );
398         
399         try
400         {
401             getSchemaContext( service ).rename( dn, newdn );
402             fail( "should not be able to rename an objectClass in use" );
403         }
404         catch( LdapOperationNotSupportedException e ) 
405         {
406             assertEquals( e.getResultCode(), ResultCodeEnum.UNWILLING_TO_PERFORM );
407         }
408 
409         assertTrue( "objectClass should still be in the registry after rename failure", 
410             getObjectClassRegistry().hasObjectClass( OID ) );
411     }
412 
413 
414     // ----------------------------------------------------------------------
415     // Let's try some freaky stuff
416     // ----------------------------------------------------------------------
417     @Test
418     public void testMoveObjectClassToTop() throws Exception
419     {
420         addObjectClass();
421         
422         LdapDN dn = getObjectClassContainer( "apachemeta" );
423         dn.add( "m-oid" + "=" + OID );
424 
425         LdapDN top = new LdapDN();
426         top.add( "m-oid" + "=" + OID );
427         
428         try
429         {
430             getSchemaContext( service ).rename( dn, top );
431             fail( "should not be able to move a objectClass up to ou=schema" );
432         }
433         catch( LdapInvalidNameException e ) 
434         {
435             assertEquals( e.getResultCode(), ResultCodeEnum.NAMING_VIOLATION );
436         }
437 
438         assertTrue( "objectClass should still be in the registry after move failure", 
439             getObjectClassRegistry().hasObjectClass( OID ) );
440     }
441 
442 
443     @Test
444     public void testMoveObjectClassToComparatorContainer() throws Exception
445     {
446         addObjectClass();
447         
448         LdapDN dn = getObjectClassContainer( "apachemeta" );
449         dn.add( "m-oid" + "=" + OID );
450 
451         LdapDN newdn = new LdapDN( "ou=comparators,cn=apachemeta" );
452         newdn.add( "m-oid" + "=" + OID );
453         
454         try
455         {
456             getSchemaContext( service ).rename( dn, newdn );
457             fail( "should not be able to move a objectClass into comparators container" );
458         }
459         catch( LdapInvalidNameException e ) 
460         {
461             assertEquals( e.getResultCode(), ResultCodeEnum.NAMING_VIOLATION );
462         }
463 
464         assertTrue( "objectClass should still be in the registry after move failure", 
465             getObjectClassRegistry().hasObjectClass( OID ) );
466     }
467 
468     
469     private void addObjectClassToDisabledSchema() throws Exception
470     {
471         Attributes attrs = new BasicAttributes( true );
472         Attribute oc = new BasicAttribute( "objectClass", "top" );
473         oc.add( "metaTop" );
474         oc.add( "metaObjectClass" );
475         attrs.put( oc );
476         attrs.put( "m-oid", OID );
477         attrs.put( "m-name", NAME);
478         attrs.put( "m-description", DESCRIPTION0 );
479         attrs.put( "m-typeObjectClass", "AUXILIARY" );
480         attrs.put( "m-must", "cn" );
481         attrs.put( "m-may", "ou" );
482         
483         LdapDN dn = getObjectClassContainer( "nis" );
484         dn.add( "m-oid" + "=" + OID );
485         getSchemaContext( service ).createSubcontext( dn, attrs );
486     }
487     
488     @Test
489     public void testAddObjectClassToDisabledSchema1() throws Exception
490     {
491         addObjectClassToDisabledSchema();
492         
493         assertFalse( "adding new objectClass to disabled schema should not register it into the registries", 
494             getObjectClassRegistry().hasObjectClass( OID ) );
495     }
496 
497 
498     @Test
499     public void testMoveObjectClassToDisabledSchema() throws Exception
500     {
501         addObjectClass();
502         
503         LdapDN dn = getObjectClassContainer( "apachemeta" );
504         dn.add( "m-oid" + "=" + OID );
505 
506         // nis is inactive by default
507         LdapDN newdn = getObjectClassContainer( "nis" );
508         newdn.add( "m-oid" + "=" + OID );
509         
510         getSchemaContext( service ).rename( dn, newdn );
511 
512         assertFalse( "objectClass OID should no longer be present", 
513             getObjectClassRegistry().hasObjectClass( OID ) );
514     }
515 
516 
517     @Test
518     public void testMoveObjectClassToEnabledSchema() throws Exception
519     {
520         addObjectClassToDisabledSchema();
521         
522         // nis is inactive by default
523         LdapDN dn = getObjectClassContainer( "nis" );
524         dn.add( "m-oid" + "=" + OID );
525 
526         assertFalse( "objectClass OID should NOT be present when added to disabled nis schema", 
527             getObjectClassRegistry().hasObjectClass( OID ) );
528 
529         LdapDN newdn = getObjectClassContainer( "apachemeta" );
530         newdn.add( "m-oid" + "=" + OID );
531         
532         getSchemaContext( service ).rename( dn, newdn );
533 
534         assertTrue( "objectClass OID should be present when moved to enabled schema", 
535             getObjectClassRegistry().hasObjectClass( OID ) );
536         
537         assertEquals( "objectClass should be in apachemeta schema after move", 
538             getObjectClassRegistry().getSchemaName( OID ), "apachemeta" );
539     }
540     
541     // ----------------------------------------------------------------------
542     // Let's test the Abstract, Auiliary and Structural inheritence enforcement
543     // ----------------------------------------------------------------------
544     /**
545      * Check that we can create an ABSTRACT OC which inherit from an ABSTRACT OC
546      */
547     @Test
548     public void testAddAbstractOCinheritingFromAbstractOC() throws Exception
549     {
550         Attributes attrs = new BasicAttributes( true );
551         Attribute oc = new BasicAttribute( "objectClass", "top" );
552         oc.add( "metaTop" );
553         oc.add( "metaObjectClass" );
554         attrs.put( oc );
555         
556         attrs.put( "m-oid", OID );
557         attrs.put( "m-name", "abstractOCtest");
558         attrs.put( "m-description", "An abstract oC inheriting from top" );
559         attrs.put( "m-typeObjectClass", "ABSTRACT" );
560         attrs.put( "m-supObjectClass", "top" );
561         attrs.put( "m-must", "cn" );
562         attrs.put( "m-may", "ou" );
563         
564         LdapDN dn = getObjectClassContainer( "apachemeta" );
565         dn.add( "m-oid" + "=" + OID );
566         getSchemaContext( service ).createSubcontext( dn, attrs );
567         
568         assertTrue( getObjectClassRegistry().hasObjectClass( OID ) );
569         assertEquals( getObjectClassRegistry().getSchemaName( OID ), "apachemeta" );
570     }
571 
572     
573     /**
574      * Check that we can't create an ABSTRACT OC which inherit from an AUXILIARY OC
575      */
576     @Test
577     public void testAddAbstractOCinheritingFromAuxiliaryOC() throws Exception
578     {
579         Attributes attrs = new BasicAttributes( true );
580         Attribute oc = new BasicAttribute( "objectClass", "top" );
581         oc.add( "metaTop" );
582         oc.add( "metaObjectClass" );
583         attrs.put( oc );
584         
585         attrs.put( "m-oid", OID );
586         attrs.put( "m-name", "abstractOCtest");
587         attrs.put( "m-description", "An abstract oC inheriting from top" );
588         attrs.put( "m-typeObjectClass", "ABSTRACT" );
589         attrs.put( "m-must", "cn" );
590         attrs.put( "m-may", "ou" );
591         
592         Attribute sup = new BasicAttribute( "m-supObjectClass" );
593         sup.add( "top" );
594         sup.add( "javaSerializedObject");
595         attrs.put( sup );
596         
597         LdapDN dn = getObjectClassContainer( "apachemeta" );
598         dn.add( "m-oid" + "=" + OID );
599         
600         try
601         {
602         	getSchemaContext( service ).createSubcontext( dn, attrs );
603         	fail();
604         }
605         catch ( NamingException ne )
606         {
607         	assertTrue( true );
608         }
609     }
610     
611     
612     /**
613      * Check that we can't create an ABSTRACT OC which inherit from an STRUCTURAL OC
614      */
615     @Test
616     public void testAddAbstractOCinheritingFromStructuralOC() throws Exception
617     {
618         Attributes attrs = new BasicAttributes( true );
619         Attribute oc = new BasicAttribute( "objectClass", "top" );
620         oc.add( "metaTop" );
621         oc.add( "metaObjectClass" );
622         attrs.put( oc );
623         
624         attrs.put( "m-oid", OID );
625         attrs.put( "m-name", "abstractOCtest");
626         attrs.put( "m-description", "An abstract oC inheriting from top" );
627         attrs.put( "m-typeObjectClass", "ABSTRACT" );
628         attrs.put( "m-must", "cn" );
629         attrs.put( "m-may", "ou" );
630         
631         Attribute sup = new BasicAttribute( "m-supObjectClass" );
632         sup.add( "top" );
633         sup.add( "person");
634         attrs.put( sup );
635         
636         LdapDN dn = getObjectClassContainer( "apachemeta" );
637         dn.add( "m-oid" + "=" + OID );
638         
639         try
640         {
641         	getSchemaContext( service ).createSubcontext( dn, attrs );
642         	fail();
643         }
644         catch ( NamingException ne )
645         {
646         	assertTrue( true );
647         }
648     }
649     
650     
651     /**
652      * Check that we can create an AUXILIARY OC which inherit from an ABSTRACT OC
653      */
654     @Test
655     public void testAddAuxiliaryOCinheritingFromAbstractOC() throws Exception
656     {
657         Attributes attrs = new BasicAttributes( true );
658         Attribute oc = new BasicAttribute( "objectClass", "top" );
659         oc.add( "metaTop" );
660         oc.add( "metaObjectClass" );
661         attrs.put( oc );
662         
663         attrs.put( "m-oid", NEW_OID );
664         attrs.put( "m-name", "abstractOCtest");
665         attrs.put( "m-description", "An abstract oC inheriting from top" );
666         attrs.put( "m-typeObjectClass", "AUXILIARY" );
667         attrs.put( "m-supObjectClass", "top" );
668         attrs.put( "m-must", "cn" );
669         attrs.put( "m-may", "ou" );
670         
671         LdapDN dn = getObjectClassContainer( "apachemeta" );
672         dn.add( "m-oid" + "=" + NEW_OID );
673         getSchemaContext( service ).createSubcontext( dn, attrs );
674         
675         assertTrue( getObjectClassRegistry().hasObjectClass( NEW_OID ) );
676         assertEquals( getObjectClassRegistry().getSchemaName( NEW_OID ), "apachemeta" );
677     }
678 
679     
680     /**
681      * Check that we can create an AUXILIARY OC which inherit from an AUXILIARY OC
682      */
683     @Test
684     public void testAddAuxiliaryOCinheritingFromAuxiliaryOC() throws Exception
685     {
686         Attributes attrs = new BasicAttributes( true );
687         Attribute oc = new BasicAttribute( "objectClass", "top" );
688         oc.add( "metaTop" );
689         oc.add( "metaObjectClass" );
690         attrs.put( oc );
691         
692         attrs.put( "m-oid", NEW_OID );
693         attrs.put( "m-name", "abstractOCtest");
694         attrs.put( "m-description", "An abstract oC inheriting from top" );
695         attrs.put( "m-typeObjectClass", "AUXILIARY" );
696         attrs.put( "m-supObjectClass", "javaNamingReference" );
697         attrs.put( "m-must", "cn" );
698         attrs.put( "m-may", "ou" );
699         
700         Attribute sup = new BasicAttribute( "m-supObjectClass" );
701         sup.add( "top" );
702         sup.add( "javaNamingReference");
703         attrs.put( sup );
704 
705         LdapDN dn = getObjectClassContainer( "apachemeta" );
706         dn.add( "m-oid" + "=" + NEW_OID );
707         getSchemaContext( service ).createSubcontext( dn, attrs );
708         
709         assertTrue( getObjectClassRegistry().hasObjectClass( NEW_OID ) );
710         assertEquals( getObjectClassRegistry().getSchemaName( NEW_OID ), "apachemeta" );
711     }
712 
713     
714     /**
715      * Check that we can't create an Auxiliary OC which inherit from an STRUCTURAL OC
716      */
717     @Test
718     public void testAddAuxiliaryOCinheritingFromStructuralOC() throws Exception
719     {
720         Attributes attrs = new BasicAttributes( true );
721         Attribute oc = new BasicAttribute( "objectClass", "top" );
722         oc.add( "metaTop" );
723         oc.add( "metaObjectClass" );
724         attrs.put( oc );
725         
726         attrs.put( "m-oid", OID );
727         attrs.put( "m-name", "abstractOCtest");
728         attrs.put( "m-description", "An abstract oC inheriting from top" );
729         attrs.put( "m-typeObjectClass", "ABSTRACT" );
730         attrs.put( "m-must", "cn" );
731         attrs.put( "m-may", "ou" );
732         
733         Attribute sup = new BasicAttribute( "m-supObjectClass" );
734         sup.add( "top" );
735         sup.add( "person");
736         attrs.put( sup );
737         
738         LdapDN dn = getObjectClassContainer( "apachemeta" );
739         dn.add( "m-oid" + "=" + OID );
740         
741         try
742         {
743         	getSchemaContext( service ).createSubcontext( dn, attrs );
744         	fail();
745         }
746         catch ( NamingException ne )
747         {
748         	assertTrue( true );
749         }
750     }
751 
752     
753     /**
754      * Check that we can create a STRUCTURAL OC which inherit from an ABSTRACT OC
755      */
756     @Test
757     public void testAddStructuralOCinheritingFromAbstractOC() throws Exception
758     {
759         Attributes attrs = new BasicAttributes( true );
760         Attribute oc = new BasicAttribute( "objectClass", "top" );
761         oc.add( "metaTop" );
762         oc.add( "metaObjectClass" );
763         attrs.put( oc );
764         
765         attrs.put( "m-oid", NEW_OID );
766         attrs.put( "m-name", "abstractOCtest");
767         attrs.put( "m-description", "An abstract oC inheriting from top" );
768         attrs.put( "m-typeObjectClass", "STRUCTURAL" );
769         attrs.put( "m-supObjectClass", "top" );
770         attrs.put( "m-must", "cn" );
771         attrs.put( "m-may", "ou" );
772         
773         LdapDN dn = getObjectClassContainer( "apachemeta" );
774         dn.add( "m-oid" + "=" + NEW_OID );
775         getSchemaContext( service ).createSubcontext( dn, attrs );
776         
777         assertTrue( getObjectClassRegistry().hasObjectClass( NEW_OID ) );
778         assertEquals( getObjectClassRegistry().getSchemaName( NEW_OID ), "apachemeta" );
779     }
780 
781     
782     /**
783      * Check that we can create a STRUCTURAL OC which inherit from an AUXILIARY OC
784      */
785     @Test
786     public void testAddStructuralOCinheritingFromAuxiliaryOC() throws Exception
787     {
788         Attributes attrs = new BasicAttributes( true );
789         Attribute oc = new BasicAttribute( "objectClass", "top" );
790         oc.add( "metaTop" );
791         oc.add( "metaObjectClass" );
792         attrs.put( oc );
793         
794         attrs.put( "m-oid", NEW_OID );
795         attrs.put( "m-name", "abstractOCtest");
796         attrs.put( "m-description", "An abstract oC inheriting from top" );
797         attrs.put( "m-typeObjectClass", "STRUCTURAL" );
798         attrs.put( "m-must", "cn" );
799         attrs.put( "m-may", "ou" );
800         
801         Attribute sup = new BasicAttribute( "m-supObjectClass" );
802         sup.add( "top" );
803         sup.add( "javaNamingReference");
804         attrs.put( sup );
805 
806         LdapDN dn = getObjectClassContainer( "apachemeta" );
807         dn.add( "m-oid" + "=" + NEW_OID );
808         getSchemaContext( service ).createSubcontext( dn, attrs );
809         
810         assertTrue( getObjectClassRegistry().hasObjectClass( NEW_OID ) );
811         assertEquals( getObjectClassRegistry().getSchemaName( NEW_OID ), "apachemeta" );
812     }
813 
814     
815     /**
816      * Check that we can create a STRUCTURAL OC which inherit from an STRUCTURAL OC
817      */
818     @Test
819     public void testAddStructuralOCinheritingFromStructuralOC() throws Exception
820     {
821         Attributes attrs = new BasicAttributes( true );
822         Attribute oc = new BasicAttribute( "objectClass", "top" );
823         oc.add( "metaTop" );
824         oc.add( "metaObjectClass" );
825         attrs.put( oc );
826         
827         attrs.put( "m-oid", NEW_OID );
828         attrs.put( "m-name", "abstractOCtest");
829         attrs.put( "m-description", "An abstract oC inheriting from top" );
830         attrs.put( "m-typeObjectClass", "STRUCTURAL" );
831         attrs.put( "m-must", "cn" );
832         attrs.put( "m-may", "ou" );
833         
834         Attribute sup = new BasicAttribute( "m-supObjectClass" );
835         sup.add( "top" );
836         sup.add( "person");
837         attrs.put( sup );
838 
839         LdapDN dn = getObjectClassContainer( "apachemeta" );
840         dn.add( "m-oid" + "=" + NEW_OID );
841         getSchemaContext( service ).createSubcontext( dn, attrs );
842         
843         assertTrue( getObjectClassRegistry().hasObjectClass( NEW_OID ) );
844         assertEquals( getObjectClassRegistry().getSchemaName( NEW_OID ), "apachemeta" );
845     }
846 }