View Javadoc

1   /*
2    *   Licensed to the Apache Software Foundation (ASF) under one
3    *   or more contributor license agreements.  See the NOTICE file
4    *   distributed with this work for additional information
5    *   regarding copyright ownership.  The ASF licenses this file
6    *   to you under the Apache License, Version 2.0 (the
7    *   "License"); you may not use this file except in compliance
8    *   with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *   Unless required by applicable law or agreed to in writing,
13   *   software distributed under the License is distributed on an
14   *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *   KIND, either express or implied.  See the License for the
16   *   specific language governing permissions and limitations
17   *   under the License.
18   *
19   */
20  package org.apache.directory.server.core.schema;
21  
22  
23  import java.util.Set;
24  
25  import javax.naming.NamingException;
26  
27  import org.apache.directory.server.constants.MetaSchemaConstants;
28  import org.apache.directory.server.core.entry.ServerEntry;
29  import org.apache.directory.server.schema.bootstrap.Schema;
30  import org.apache.directory.server.schema.registries.ObjectClassRegistry;
31  import org.apache.directory.server.schema.registries.Registries;
32  import org.apache.directory.shared.ldap.constants.SchemaConstants;
33  import org.apache.directory.shared.ldap.exception.LdapInvalidNameException;
34  import org.apache.directory.shared.ldap.exception.LdapOperationNotSupportedException;
35  import org.apache.directory.shared.ldap.message.ResultCodeEnum;
36  import org.apache.directory.shared.ldap.name.LdapDN;
37  import org.apache.directory.shared.ldap.name.Rdn;
38  import org.apache.directory.shared.ldap.schema.ObjectClass;
39  
40  
41  /**
42   * A handler for operations peformed to add, delete, modify, rename and 
43   * move schema normalizers.
44   *
45   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
46   * @version $Rev$, $Date$
47   */
48  public class MetaObjectClassHandler extends AbstractSchemaChangeHandler
49  {
50      private final SchemaPartitionDao dao;
51      private final ObjectClassRegistry objectClassRegistry;
52  
53  
54      public MetaObjectClassHandler( Registries targetRegistries, PartitionSchemaLoader loader, SchemaPartitionDao dao ) 
55          throws Exception
56      {
57          super( targetRegistries, loader );
58          
59          this.dao = dao;
60          this.objectClassRegistry = targetRegistries.getObjectClassRegistry();
61      }
62  
63  
64      protected void modify( LdapDN name, ServerEntry entry, ServerEntry targetEntry, 
65          boolean cascade ) throws Exception
66      {
67          String oid = getOid( entry );
68          Schema schema = getSchema( name );
69          ObjectClass oc = factory.getObjectClass( targetEntry, targetRegistries, schema.getSchemaName() );
70  
71          if ( ! schema.isDisabled() )
72          {
73              objectClassRegistry.unregister( oid );
74              objectClassRegistry.register( oc );
75          }
76      }
77  
78  
79      public void add( LdapDN name, ServerEntry entry ) throws Exception
80      {
81          LdapDN parentDn = ( LdapDN ) name.clone();
82          parentDn.remove( parentDn.size() - 1 );
83          checkNewParent( parentDn );
84          checkOidIsUnique( entry );
85          
86          String schemaName = getSchemaName( name );
87          ObjectClass oc = factory.getObjectClass( entry, targetRegistries, schemaName );
88          add( oc );
89      }
90  
91  
92      public void delete( LdapDN name, ServerEntry entry, boolean cascade ) throws Exception
93      {
94          String schemaName = getSchemaName( name );
95          ObjectClass oc = factory.getObjectClass( entry, targetRegistries, schemaName );
96          Set<ServerEntry> dependees = dao.listObjectClassDependents( oc );
97          
98          if ( dependees != null && dependees.size() > 0 )
99          {
100             throw new LdapOperationNotSupportedException( "The objectClass with OID " + oc.getOid() 
101                 + " cannot be deleted until all entities" 
102                 + " using this objectClass have also been deleted.  The following dependees exist: " 
103                 + getOids( dependees ), 
104                 ResultCodeEnum.UNWILLING_TO_PERFORM );
105         }
106 
107         delete( oc, cascade );
108     }
109 
110 
111     public void delete( ObjectClass oc, boolean cascade ) throws Exception
112     {
113         Schema schema = loader.getSchema( oc.getSchema() );
114         
115         if ( ! schema.isDisabled() )
116         {
117             objectClassRegistry.unregister( oc.getOid() );
118         }
119         
120         unregisterOids( oc.getOid() );
121     }
122 
123 
124     public void rename( LdapDN name, ServerEntry entry, Rdn newRdn, boolean cascade ) throws Exception
125     {
126         Schema schema = getSchema( name );
127         ObjectClass oldOc = factory.getObjectClass( entry, targetRegistries, schema.getSchemaName() );
128         Set<ServerEntry> dependees = dao.listObjectClassDependents( oldOc );
129         
130         if ( dependees != null && dependees.size() > 0 )
131         {
132             throw new LdapOperationNotSupportedException( "The objectClass with OID " + oldOc.getOid()
133                 + " cannot be deleted until all entities" 
134                 + " using this objectClass have also been deleted.  The following dependees exist: " 
135                 + getOids( dependees ), 
136                 ResultCodeEnum.UNWILLING_TO_PERFORM );
137         }
138 
139         ServerEntry targetEntry = ( ServerEntry ) entry.clone();
140         String newOid = ( String ) newRdn.getValue();
141         targetEntry.put( MetaSchemaConstants.M_OID_AT, newOid );
142         checkOidIsUnique( newOid );
143         ObjectClass oc = factory.getObjectClass( targetEntry, targetRegistries, schema.getSchemaName() );
144 
145         if ( ! schema.isDisabled() )
146         {
147             objectClassRegistry.unregister( oldOc.getOid() );
148             objectClassRegistry.register( oc );
149         }
150         else
151         {
152             registerOids( oc );
153         }
154         
155         unregisterOids( oldOc.getOid() );
156     }
157 
158 
159     public void move( LdapDN oriChildName, LdapDN newParentName, Rdn newRdn, boolean deleteOldRn,
160         ServerEntry entry, boolean cascade ) throws Exception
161     {
162         checkNewParent( newParentName );
163         Schema oldSchema = getSchema( oriChildName );
164         ObjectClass oldOc = factory.getObjectClass( entry, targetRegistries, oldSchema.getSchemaName() );
165         Set<ServerEntry> dependees = dao.listObjectClassDependents( oldOc );
166         
167         if ( dependees != null && dependees.size() > 0 )
168         {
169             throw new LdapOperationNotSupportedException( "The objectClass with OID " + oldOc.getOid()
170                 + " cannot be deleted until all entities" 
171                 + " using this objectClass have also been deleted.  The following dependees exist: " 
172                 + getOids( dependees ), 
173                 ResultCodeEnum.UNWILLING_TO_PERFORM );
174         }
175 
176         Schema newSchema = getSchema( newParentName );
177         ServerEntry targetEntry = ( ServerEntry ) entry.clone();
178         String newOid = ( String ) newRdn.getValue();
179         checkOidIsUnique( newOid );
180         targetEntry.put( MetaSchemaConstants.M_OID_AT, newOid );
181         ObjectClass oc = factory.getObjectClass( targetEntry, targetRegistries, newSchema.getSchemaName() );
182 
183         if ( ! oldSchema.isDisabled() )
184         {
185             objectClassRegistry.unregister( oldOc.getOid() );
186         }
187         unregisterOids( oldOc.getOid() );
188         
189         if ( ! newSchema.isDisabled() )
190         {
191             objectClassRegistry.register( oc );
192         }
193         else
194         {
195             registerOids( oc );
196         }
197     }
198 
199 
200     public void replace( LdapDN oriChildName, LdapDN newParentName, ServerEntry entry, boolean cascade ) 
201         throws Exception
202     {
203         checkNewParent( newParentName );
204         Schema oldSchema = getSchema( oriChildName );
205         ObjectClass oldAt = factory.getObjectClass( entry, targetRegistries, oldSchema.getSchemaName() );
206         Set<ServerEntry> dependees = dao.listObjectClassDependents( oldAt );
207         
208         if ( dependees != null && dependees.size() > 0 )
209         {
210             throw new LdapOperationNotSupportedException( "The objectClass with OID " + oldAt.getOid() 
211                 + " cannot be deleted until all entities" 
212                 + " using this objectClass have also been deleted.  The following dependees exist: " 
213                 + getOids( dependees ), 
214                 ResultCodeEnum.UNWILLING_TO_PERFORM );
215         }
216 
217         Schema newSchema = getSchema( newParentName );
218         ObjectClass oc = factory.getObjectClass( entry, targetRegistries, newSchema.getSchemaName() );
219         
220         if ( ! oldSchema.isDisabled() )
221         {
222             objectClassRegistry.unregister( oldAt.getOid() );
223         }
224         
225         if ( ! newSchema.isDisabled() )
226         {
227             objectClassRegistry.register( oc );
228         }
229     }
230 
231 
232     private void checkNewParent( LdapDN newParent ) throws NamingException
233     {
234         if ( newParent.size() != 3 )
235         {
236             throw new LdapInvalidNameException( 
237                 "The parent dn of a objectClass should be at most 3 name components in length.", 
238                 ResultCodeEnum.NAMING_VIOLATION );
239         }
240         
241         Rdn rdn = newParent.getRdn();
242         if ( ! targetRegistries.getOidRegistry().getOid( rdn.getNormType() ).equals( SchemaConstants.OU_AT_OID ) )
243         {
244             throw new LdapInvalidNameException( "The parent entry of a objectClass should be an organizationalUnit.", 
245                 ResultCodeEnum.NAMING_VIOLATION );
246         }
247         
248         if ( ! ( ( String ) rdn.getValue() ).equalsIgnoreCase( SchemaConstants.OBJECT_CLASSES_AT ) )
249         {
250             throw new LdapInvalidNameException( 
251                 "The parent entry of a attributeType should have a relative name of ou=objectClasses.", 
252                 ResultCodeEnum.NAMING_VIOLATION );
253         }
254     }
255 
256 
257     public void add( ObjectClass oc ) throws Exception
258     {
259         Schema schema = loader.getSchema( oc.getSchema() );
260         if ( ! schema.isDisabled() )
261         {
262             objectClassRegistry.register( oc );
263         }
264         else
265         {
266             registerOids( oc );
267         }
268     }
269 }