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.ArrayList;
24  import java.util.List;
25  
26  import javax.naming.NamingException;
27  
28  import org.apache.directory.server.constants.MetaSchemaConstants;
29  import org.apache.directory.server.core.entry.ServerEntry;
30  import org.apache.directory.server.schema.bootstrap.Schema;
31  import org.apache.directory.server.schema.registries.MatchingRuleRegistry;
32  import org.apache.directory.server.schema.registries.NormalizerRegistry;
33  import org.apache.directory.server.schema.registries.Registries;
34  import org.apache.directory.shared.ldap.constants.SchemaConstants;
35  import org.apache.directory.shared.ldap.entry.EntryAttribute;
36  import org.apache.directory.shared.ldap.exception.LdapInvalidNameException;
37  import org.apache.directory.shared.ldap.exception.LdapNamingException;
38  import org.apache.directory.shared.ldap.exception.LdapOperationNotSupportedException;
39  import org.apache.directory.shared.ldap.message.ResultCodeEnum;
40  import org.apache.directory.shared.ldap.name.LdapDN;
41  import org.apache.directory.shared.ldap.name.Rdn;
42  import org.apache.directory.shared.ldap.schema.AttributeType;
43  import org.apache.directory.shared.ldap.schema.Normalizer;
44  import org.apache.directory.shared.ldap.schema.syntax.NormalizerDescription;
45  import org.apache.directory.shared.ldap.util.Base64;
46  
47  
48  /**
49   * A handler for operations peformed to add, delete, modify, rename and 
50   * move schema normalizers.
51   *
52   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
53   * @version $Rev$, $Date$
54   */
55  public class MetaNormalizerHandler extends AbstractSchemaChangeHandler
56  {
57      private final SchemaEntityFactory factory;
58      private final NormalizerRegistry normalizerRegistry;
59      private final MatchingRuleRegistry matchingRuleRegistry;
60      private final AttributeType byteCodeAT;
61      private final AttributeType descAT;
62      private final AttributeType fqcnAT;
63      
64  
65      public MetaNormalizerHandler( Registries targetRegistries, PartitionSchemaLoader loader ) throws Exception
66      {
67          super( targetRegistries, loader );
68          this.normalizerRegistry = targetRegistries.getNormalizerRegistry();
69          this.matchingRuleRegistry = targetRegistries.getMatchingRuleRegistry();
70          this.factory = new SchemaEntityFactory( targetRegistries );
71          this.byteCodeAT = targetRegistries.getAttributeTypeRegistry().lookup( MetaSchemaConstants.M_BYTECODE_AT );
72          this.descAT = targetRegistries.getAttributeTypeRegistry().lookup( MetaSchemaConstants.M_DESCRIPTION_AT );
73          this.fqcnAT = targetRegistries.getAttributeTypeRegistry().lookup( MetaSchemaConstants.M_FQCN_AT );
74      }
75  
76  
77      
78      
79      private NormalizerDescription getNormalizerDescription( String schemaName, ServerEntry entry ) throws Exception
80      {
81          NormalizerDescription description = new NormalizerDescription();
82          description.setNumericOid( getOid( entry ) );
83          List<String> values = new ArrayList<String>();
84          values.add( schemaName );
85          description.addExtension( MetaSchemaConstants.X_SCHEMA, values );
86          description.setFqcn( entry.get( fqcnAT ).getString() );
87          
88          EntryAttribute desc = entry.get( descAT );
89          
90          if ( ( desc != null ) && ( desc.size() > 0 ) )
91          {
92              description.setDescription( desc.getString() );
93          }
94          
95          EntryAttribute bytecode =  entry.get( byteCodeAT );
96          
97          if ( ( bytecode != null ) && ( bytecode.size() > 0 ) )
98          {
99              byte[] bytes = bytecode.getBytes();
100             description.setBytecode( new String( Base64.encode( bytes ) ) );
101         }
102 
103         return description;
104     }
105     
106     
107     protected void modify( LdapDN name, ServerEntry entry, ServerEntry targetEntry, boolean cascade ) throws Exception
108     {
109         String oid = getOid( entry );
110         Normalizer normalizer = factory.getNormalizer( targetEntry, targetRegistries );
111         Schema schema = getSchema( name );
112         
113         if ( ! schema.isDisabled() )
114         {
115             normalizerRegistry.unregister( oid );
116             NormalizerDescription normalizerDescription = getNormalizerDescription( schema.getSchemaName(), 
117                 targetEntry );
118             normalizerRegistry.register( normalizerDescription, normalizer );
119         }
120     }
121 
122 
123     public void add( LdapDN name, ServerEntry entry ) throws Exception
124     {
125         LdapDN parentDn = ( LdapDN ) name.clone();
126         parentDn.remove( parentDn.size() - 1 );
127         checkNewParent( parentDn );
128         checkOidIsUniqueForNormalizer( entry );
129         
130         Normalizer normalizer = factory.getNormalizer( entry, targetRegistries );
131         Schema schema = getSchema( name );
132         
133         if ( ! schema.isDisabled() )
134         {
135             NormalizerDescription normalizerDescription = getNormalizerDescription( schema.getSchemaName(), entry );
136             normalizerRegistry.register( normalizerDescription, normalizer );
137         }
138     }
139 
140     
141     public void add( NormalizerDescription normalizerDescription ) throws Exception
142     {
143         Normalizer normalizer = factory.getNormalizer( normalizerDescription, targetRegistries );
144         String schemaName = MetaSchemaConstants.SCHEMA_OTHER;
145         
146         if ( normalizerDescription.getExtensions().get( MetaSchemaConstants.X_SCHEMA ) != null )
147         {
148             schemaName = normalizerDescription.getExtensions().get( MetaSchemaConstants.X_SCHEMA ).get( 0 );
149         }
150         
151         Schema schema = loader.getSchema( schemaName );
152         
153         if ( ! schema.isDisabled() )
154         {
155             normalizerRegistry.register( normalizerDescription, normalizer );
156         }
157     }
158 
159 
160     public void delete( LdapDN name, ServerEntry entry, boolean cascade ) throws Exception
161     {
162         delete( getOid( entry ), cascade );
163     }
164 
165 
166     public void delete( String oid, boolean cascade ) throws NamingException
167     {
168         if ( matchingRuleRegistry.hasMatchingRule( oid ) )
169         {
170             throw new LdapOperationNotSupportedException( "The normalizer with OID " + oid 
171                 + " cannot be deleted until all " 
172                 + "matchingRules using that normalizer have also been deleted.", 
173                 ResultCodeEnum.UNWILLING_TO_PERFORM );
174         }
175         
176         if ( normalizerRegistry.hasNormalizer( oid ) )
177         {
178             normalizerRegistry.unregister( oid );
179         }
180     }
181     
182 
183     public void rename( LdapDN name, ServerEntry entry, Rdn newRdn, boolean cascade ) throws Exception
184     {
185         String oldOid = getOid( entry );
186 
187         if ( matchingRuleRegistry.hasMatchingRule( oldOid ) )
188         {
189             throw new LdapOperationNotSupportedException( "The normalizer with OID " + oldOid 
190                 + " cannot have it's OID changed until all " 
191                 + "matchingRules using that normalizer have been deleted.", 
192                 ResultCodeEnum.UNWILLING_TO_PERFORM );
193         }
194 
195         String oid = ( String ) newRdn.getValue();
196         checkOidIsUniqueForNormalizer( oid );
197         
198         Schema schema = getSchema( name );
199         
200         if ( ! schema.isDisabled() )
201         {
202             Normalizer normalizer = factory.getNormalizer( entry, targetRegistries );
203             normalizerRegistry.unregister( oldOid );
204             
205             NormalizerDescription normalizerDescription = getNormalizerDescription( schema.getSchemaName(), entry );
206             normalizerDescription.setNumericOid( oid );
207             normalizerRegistry.register( normalizerDescription, normalizer );
208         }
209     }
210 
211 
212     public void move( LdapDN oriChildName, LdapDN newParentName, Rdn newRdn, boolean deleteOldRn,
213         ServerEntry entry, boolean cascade ) throws Exception
214     {
215         checkNewParent( newParentName );
216         String oldOid = getOid( entry );
217 
218         if ( matchingRuleRegistry.hasMatchingRule( oldOid ) )
219         {
220             throw new LdapOperationNotSupportedException( "The normalizer with OID " + oldOid 
221                 + " cannot have it's OID changed until all " 
222                 + "matchingRules using that normalizer have been deleted.", 
223                 ResultCodeEnum.UNWILLING_TO_PERFORM );
224         }
225 
226         String oid = ( String ) newRdn.getValue();
227         checkOidIsUniqueForNormalizer( oid );
228         
229         Schema oldSchema = getSchema( oriChildName );
230         Schema newSchema = getSchema( newParentName );
231         
232         Normalizer normalizer = factory.getNormalizer( entry, targetRegistries );
233 
234         if ( ! oldSchema.isDisabled() )
235         {
236             normalizerRegistry.unregister( oldOid );
237         }
238 
239         if ( ! newSchema.isDisabled() )
240         {
241             NormalizerDescription normalizerDescription = getNormalizerDescription( newSchema.getSchemaName(), entry );
242             normalizerDescription.setNumericOid( oid );
243             normalizerRegistry.register( normalizerDescription, normalizer );
244         }
245     }
246 
247 
248     public void replace( LdapDN oriChildName, LdapDN newParentName, ServerEntry entry, boolean cascade ) 
249         throws Exception
250     {
251         checkNewParent( newParentName );
252         String oid = getOid( entry );
253 
254         if ( matchingRuleRegistry.hasMatchingRule( oid ) )
255         {
256             throw new LdapOperationNotSupportedException( "The normalizer with OID " + oid 
257                 + " cannot be moved to another schema until all " 
258                 + "matchingRules using that normalizer have been deleted.", 
259                 ResultCodeEnum.UNWILLING_TO_PERFORM );
260         }
261 
262         Schema oldSchema = getSchema( oriChildName );
263         Schema newSchema = getSchema( newParentName );
264         
265         Normalizer normalizer = factory.getNormalizer( entry, targetRegistries );
266         
267         if ( ! oldSchema.isDisabled() )
268         {
269             normalizerRegistry.unregister( oid );
270         }
271         
272         if ( ! newSchema.isDisabled() )
273         {
274             NormalizerDescription normalizerDescription = getNormalizerDescription( newSchema.getSchemaName(), entry );
275             normalizerRegistry.register( normalizerDescription, normalizer );
276         }
277     }
278 
279     
280     private void checkOidIsUniqueForNormalizer( String oid ) throws NamingException
281     {
282         if ( super.targetRegistries.getNormalizerRegistry().hasNormalizer( oid ) )
283         {
284             throw new LdapNamingException( "Oid " + oid + " for new schema normalizer is not unique.", 
285                 ResultCodeEnum.OTHER );
286         }
287     }
288 
289 
290     private void checkOidIsUniqueForNormalizer( ServerEntry entry ) throws Exception
291     {
292         String oid = getOid( entry );
293         
294         if ( super.targetRegistries.getNormalizerRegistry().hasNormalizer( oid ) )
295         {
296             throw new LdapNamingException( "Oid " + oid + " for new schema normalizer is not unique.", 
297                 ResultCodeEnum.OTHER );
298         }
299     }
300 
301 
302     private void checkNewParent( LdapDN newParent ) throws NamingException
303     {
304         if ( newParent.size() != 3 )
305         {
306             throw new LdapInvalidNameException( 
307                 "The parent dn of a normalizer should be at most 3 name components in length.", 
308                 ResultCodeEnum.NAMING_VIOLATION );
309         }
310         
311         Rdn rdn = newParent.getRdn();
312         if ( ! targetRegistries.getOidRegistry().getOid( rdn.getNormType() ).equals( SchemaConstants.OU_AT_OID ) )
313         {
314             throw new LdapInvalidNameException( "The parent entry of a normalizer should be an organizationalUnit.", 
315                 ResultCodeEnum.NAMING_VIOLATION );
316         }
317         
318         if ( ! ( ( String ) rdn.getValue() ).equalsIgnoreCase( SchemaConstants.NORMALIZERS_AT ) )
319         {
320             throw new LdapInvalidNameException( 
321                 "The parent entry of a normalizer should have a relative name of ou=normalizers.", 
322                 ResultCodeEnum.NAMING_VIOLATION );
323         }
324     }
325 }