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