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.Registries;
31  import org.apache.directory.server.schema.registries.SyntaxRegistry;
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.Syntax;
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 MetaSyntaxHandler extends AbstractSchemaChangeHandler
49  {
50      private final SchemaPartitionDao dao;
51      private final SyntaxRegistry syntaxRegistry;
52  
53      
54      public MetaSyntaxHandler( Registries targetRegistries, PartitionSchemaLoader loader, SchemaPartitionDao dao ) 
55          throws Exception
56      {
57          super( targetRegistries, loader );
58  
59          this.dao = dao;
60          this.syntaxRegistry = targetRegistries.getSyntaxRegistry();
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          Syntax syntax = factory.getSyntax( targetEntry, targetRegistries, schema.getSchemaName() );
70          
71          if ( ! schema.isDisabled() )
72          {
73              syntaxRegistry.unregister( oid );
74              syntaxRegistry.register( syntax );
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          Syntax syntax = factory.getSyntax( entry, targetRegistries, schemaName );
88          add( syntax );
89      }
90  
91  
92      public void delete( LdapDN name, ServerEntry entry, boolean cascade ) throws Exception
93      {
94          String oid = getOid( entry );
95          
96          Set<ServerEntry> dependees = dao.listSyntaxDependents( oid );
97          
98          if ( dependees != null && dependees.size() > 0 )
99          {
100             throw new LdapOperationNotSupportedException( "The syntax with OID " + oid 
101                 + " cannot be deleted until all entities" 
102                 + " using this syntax have also been deleted.  The following dependees exist: " 
103                 + getOids( dependees ), 
104                 ResultCodeEnum.UNWILLING_TO_PERFORM );
105         }
106         
107         
108         String schemaName = getSchemaName( name );
109         Syntax syntax = factory.getSyntax( entry, targetRegistries, schemaName );
110         delete( syntax, cascade );
111     }
112 
113 
114     public void delete( Syntax syntax, boolean cascade ) throws Exception
115     {
116         Schema schema = loader.getSchema( syntax.getSchema() );
117         if ( ! schema.isDisabled() )
118         {
119             syntaxRegistry.unregister( syntax.getOid() );
120         }
121 
122         // no matter what we remove OID for deleted syntaxes
123         unregisterOids( syntax.getOid() );
124     }
125 
126     
127     public void rename( LdapDN name, ServerEntry entry, Rdn newRdn, boolean cascade ) throws Exception
128     {
129         String oldOid = getOid( entry );
130 
131         Set<ServerEntry> dependees = dao.listSyntaxDependents( oldOid );
132         
133         if ( dependees != null && dependees.size() > 0 )
134         {
135             throw new LdapOperationNotSupportedException( "The syntax with OID " + oldOid
136                 + " cannot be deleted until all entities" 
137                 + " using this syntax have also been deleted.  The following dependees exist: " 
138                 + getOids( dependees ), 
139                 ResultCodeEnum.UNWILLING_TO_PERFORM );
140         }
141 
142         Schema schema = getSchema( name );
143         ServerEntry targetEntry = ( ServerEntry ) entry.clone();
144         String newOid = ( String ) newRdn.getValue();
145         checkOidIsUnique( newOid );
146         
147         targetEntry.put( MetaSchemaConstants.M_OID_AT, newOid );
148         Syntax syntax = factory.getSyntax( targetEntry, targetRegistries, schema.getSchemaName() );
149         
150         if ( ! schema.isDisabled() )
151         {
152             syntaxRegistry.unregister( oldOid );
153             syntaxRegistry.register( syntax );
154         }
155         else
156         {
157             // even for disabled schemas add OIDs
158             registerOids( syntax );
159         }
160         
161         // always remove old OIDs that are not in schema anymore
162         unregisterOids( oldOid );
163     }
164 
165 
166     public void move( LdapDN oriChildName, LdapDN newParentName, Rdn newRn, boolean deleteOldRn,
167         ServerEntry entry, boolean cascade ) throws Exception
168     {
169         checkNewParent( newParentName );
170         String oldOid = getOid( entry );
171 
172         Set<ServerEntry> dependees = dao.listSyntaxDependents( oldOid );
173         
174         if ( dependees != null && dependees.size() > 0 )
175         {
176             throw new LdapOperationNotSupportedException( "The syntax with OID " + oldOid 
177                 + " cannot be deleted until all entities" 
178                 + " using this syntax have also been deleted.  The following dependees exist: " 
179                 + getOids( dependees ), 
180                 ResultCodeEnum.UNWILLING_TO_PERFORM );
181         }
182 
183         Schema oldSchema = getSchema( oriChildName );
184         Schema newSchema = getSchema( newParentName );
185         ServerEntry targetEntry = ( ServerEntry ) entry.clone();
186         String newOid = ( String ) newRn.getValue();
187         checkOidIsUnique( newOid );
188         
189         targetEntry.put( MetaSchemaConstants.M_OID_AT, newOid );
190         Syntax syntax = factory.getSyntax( targetEntry, targetRegistries, newSchema.getSchemaName() );
191 
192         if ( ! oldSchema.isDisabled() )
193         {
194             syntaxRegistry.unregister( oldOid );
195         }
196         // always remove old OIDs that are not in schema anymore
197         unregisterOids( oldOid );
198 
199         if ( ! newSchema.isDisabled() )
200         {
201             syntaxRegistry.register( syntax );
202         }
203         else
204         {
205             // register new syntax OIDs even if schema is disabled 
206             registerOids( syntax );
207         }
208     }
209 
210 
211     public void replace( LdapDN oriChildName, LdapDN newParentName, ServerEntry entry, boolean cascade ) 
212         throws Exception
213     {
214         checkNewParent( newParentName );
215         String oid = getOid( entry );
216         
217         Set<ServerEntry> dependees = dao.listSyntaxDependents( oid );
218         
219         if ( dependees != null && dependees.size() > 0 )
220         {
221             throw new LdapOperationNotSupportedException( "The syntax with OID " + oid 
222                 + " cannot be deleted until all entities" 
223                 + " using this syntax have also been deleted.  The following dependees exist: " 
224                 + getOids( dependees ), 
225                 ResultCodeEnum.UNWILLING_TO_PERFORM );
226         }
227 
228         Schema oldSchema = getSchema( oriChildName );
229         Schema newSchema = getSchema( newParentName );
230         
231         Syntax syntax = factory.getSyntax( entry, targetRegistries, newSchema.getSchemaName() );
232         
233         if ( ! oldSchema.isDisabled() )
234         {
235             syntaxRegistry.unregister( oid );
236         }
237         
238         if ( ! newSchema.isDisabled() )
239         {
240             syntaxRegistry.register( syntax );
241         }
242     }
243     
244     
245     private void checkNewParent( LdapDN newParent ) throws NamingException
246     {
247         if ( newParent.size() != 3 )
248         {
249             throw new LdapInvalidNameException( 
250                 "The parent dn of a syntax should be at most 3 name components in length.", 
251                 ResultCodeEnum.NAMING_VIOLATION );
252         }
253         
254         Rdn rdn = newParent.getRdn();
255         if ( ! targetRegistries.getOidRegistry().getOid( rdn.getNormType() ).equals( SchemaConstants.OU_AT_OID ) )
256         {
257             throw new LdapInvalidNameException( "The parent entry of a syntax should be an organizationalUnit.", 
258                 ResultCodeEnum.NAMING_VIOLATION );
259         }
260         
261         if ( ! ( ( String ) rdn.getValue() ).equalsIgnoreCase( "syntaxes" ) )
262         {
263             throw new LdapInvalidNameException( 
264                 "The parent entry of a syntax should have a relative name of ou=syntaxes.", 
265                 ResultCodeEnum.NAMING_VIOLATION );
266         }
267     }
268 
269 
270     /**
271      * Adds a syntax to this handler's registries if it's schema is enabled.  The
272      * OID is always registered with the OidRegistry regardless of the enabled state
273      * of the schema.   
274      * 
275      * @param syntax the syntax that is to be added to this handler's registries
276      * @throws NamingException if there are problems access schema data
277      */
278     public void add( Syntax syntax ) throws Exception
279     {
280         Schema schema = loader.getSchema( syntax.getSchema() );
281         
282         if ( ! schema.isDisabled() )
283         {
284             syntaxRegistry.register( syntax );
285         }
286         else
287         {
288             // even for disabled schemas add OIDs
289             registerOids( syntax );
290         }
291     }
292 }