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.Registries;
32  import org.apache.directory.server.schema.registries.SyntaxCheckerRegistry;
33  import org.apache.directory.server.schema.registries.SyntaxRegistry;
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.syntax.SyntaxChecker;
44  import org.apache.directory.shared.ldap.schema.syntax.SyntaxCheckerDescription;
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 MetaSyntaxCheckerHandler extends AbstractSchemaChangeHandler
56  {
57      private final SchemaEntityFactory factory;
58      private final SyntaxCheckerRegistry syntaxCheckerRegistry;
59      private final SyntaxRegistry syntaxRegistry;
60      private final AttributeType byteCodeAT;
61      private final AttributeType descAT;
62      private final AttributeType fqcnAT;
63      
64  
65      public MetaSyntaxCheckerHandler( Registries targetRegistries, PartitionSchemaLoader loader ) throws Exception
66      {
67          super( targetRegistries, loader );
68          this.syntaxCheckerRegistry = targetRegistries.getSyntaxCheckerRegistry();
69          this.syntaxRegistry = targetRegistries.getSyntaxRegistry();
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      private SyntaxCheckerDescription getSyntaxCheckerDescription( String schemaName, ServerEntry entry ) 
78          throws Exception
79      {
80          SyntaxCheckerDescription description = new SyntaxCheckerDescription();
81          description.setNumericOid( getOid( entry ) );
82          List<String> values = new ArrayList<String>();
83          values.add( schemaName );
84          description.addExtension( MetaSchemaConstants.X_SCHEMA, values );
85          description.setFqcn( entry.get( fqcnAT ).getString() );
86          
87          EntryAttribute desc = entry.get( descAT );
88          
89          if ( desc != null && desc.size() > 0 )
90          {
91              description.setDescription( desc.getString() );
92          }
93          
94          EntryAttribute bytecode = entry.get( byteCodeAT );
95          
96          if ( bytecode != null && bytecode.size() > 0 )
97          {
98              byte[] bytes = bytecode.getBytes();
99              description.setBytecode( new String( Base64.encode( bytes ) ) );
100         }
101 
102         return description;
103     }
104 
105     
106     protected void modify( LdapDN name, ServerEntry entry, ServerEntry targetEntry, boolean cascade ) throws Exception
107     {
108         String oid = getOid( entry );
109         SyntaxChecker syntaxChecker = factory.getSyntaxChecker( targetEntry, targetRegistries );
110         
111         Schema schema = getSchema( name );
112         
113         if ( ! schema.isDisabled() )
114         {
115             syntaxCheckerRegistry.unregister( oid );
116             SyntaxCheckerDescription syntaxCheckerDescription = 
117                 getSyntaxCheckerDescription( schema.getSchemaName(), targetEntry );
118             syntaxCheckerRegistry.register( syntaxCheckerDescription, syntaxChecker );
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         String oid = getOid( entry );
129         if ( super.targetRegistries.getSyntaxCheckerRegistry().hasSyntaxChecker( oid ) )
130         {
131             throw new LdapNamingException( "Oid " + oid + " for new schema syntaxChecker is not unique.", 
132                 ResultCodeEnum.OTHER );
133         }
134         
135         SyntaxChecker syntaxChecker = factory.getSyntaxChecker( entry, targetRegistries );
136         Schema schema = getSchema( name );
137         
138         if ( ! schema.isDisabled() )
139         {
140             SyntaxCheckerDescription syntaxCheckerDescription = 
141                 getSyntaxCheckerDescription( schema.getSchemaName(), entry );
142             syntaxCheckerRegistry.register( syntaxCheckerDescription, syntaxChecker );
143         }
144     }
145 
146 
147     public void add( SyntaxCheckerDescription syntaxCheckerDescription ) throws Exception
148     {
149         SyntaxChecker syntaxChecker = factory.getSyntaxChecker( syntaxCheckerDescription, targetRegistries );
150         String schemaName = MetaSchemaConstants.SCHEMA_OTHER;
151         
152         if ( syntaxCheckerDescription.getExtensions().get( MetaSchemaConstants.X_SCHEMA ) != null )
153         {
154             schemaName = syntaxCheckerDescription.getExtensions()
155                 .get( MetaSchemaConstants.X_SCHEMA ).get( 0 );
156         }
157         
158         Schema schema = loader.getSchema( schemaName );
159         
160         if ( ! schema.isDisabled() )
161         {
162             syntaxCheckerRegistry.register( syntaxCheckerDescription, syntaxChecker );
163         }
164     }
165 
166 
167     public void delete( LdapDN name, ServerEntry entry, boolean cascade ) throws Exception
168     {
169         delete( getOid( entry ), cascade );
170     }
171 
172 
173     public void delete( String oid, boolean cascade ) throws NamingException
174     {
175         if ( syntaxRegistry.hasSyntax( oid ) )
176         {
177             throw new LdapOperationNotSupportedException( "The syntaxChecker with OID " + oid 
178                 + " cannot be deleted until all " 
179                 + "syntaxes using this syntaxChecker have also been deleted.", 
180                 ResultCodeEnum.UNWILLING_TO_PERFORM );
181         }
182         
183         if ( syntaxCheckerRegistry.hasSyntaxChecker( oid ) )
184         {
185             syntaxCheckerRegistry.unregister( oid );
186         }
187     }
188 
189 
190     public void rename( LdapDN name, ServerEntry entry, Rdn newRdn, boolean cascade ) throws Exception
191     {
192         String oldOid = getOid( entry );
193 
194         if ( syntaxRegistry.hasSyntax( oldOid ) )
195         {
196             throw new LdapOperationNotSupportedException( "The syntaxChecker with OID " + oldOid 
197                 + " cannot have it's OID changed until all " 
198                 + "syntaxes using that syntaxChecker have been deleted.", 
199                 ResultCodeEnum.UNWILLING_TO_PERFORM );
200         }
201 
202         Schema schema = getSchema( name );
203         ServerEntry targetEntry = ( ServerEntry ) entry.clone();
204         String newOid = ( String ) newRdn.getValue();
205         if ( super.targetRegistries.getSyntaxCheckerRegistry().hasSyntaxChecker( newOid ) )
206         {
207             throw new LdapNamingException( "Oid " + newOid + " for new schema syntaxChecker is not unique.", 
208                 ResultCodeEnum.OTHER );
209         }
210 
211         targetEntry.put( MetaSchemaConstants.M_OID_AT, newOid );
212         if ( ! schema.isDisabled() )
213         {
214             SyntaxChecker syntaxChecker = factory.getSyntaxChecker( targetEntry, targetRegistries );
215             syntaxCheckerRegistry.unregister( oldOid );
216             SyntaxCheckerDescription syntaxCheckerDescription = 
217                 getSyntaxCheckerDescription( schema.getSchemaName(), entry );
218             syntaxCheckerDescription.setNumericOid( newOid );
219             syntaxCheckerRegistry.register( syntaxCheckerDescription, syntaxChecker );
220         }
221     }
222 
223 
224     public void move( LdapDN oriChildName, LdapDN newParentName, Rdn newRdn, boolean deleteOldRn, 
225         ServerEntry entry, boolean cascade ) throws Exception
226     {
227         checkNewParent( newParentName );
228         String oldOid = getOid( entry );
229 
230         if ( syntaxRegistry.hasSyntax( oldOid ) )
231         {
232             throw new LdapOperationNotSupportedException( "The syntaxChecker with OID " + oldOid 
233                 + " cannot have it's OID changed until all " 
234                 + "syntaxes using that syntaxChecker have been deleted.", 
235                 ResultCodeEnum.UNWILLING_TO_PERFORM );
236         }
237 
238         Schema oldSchema = getSchema( oriChildName );
239         Schema newSchema = getSchema( newParentName );
240         ServerEntry targetEntry = ( ServerEntry ) entry.clone();
241         
242         String newOid = ( String ) newRdn.getValue();
243         if ( super.targetRegistries.getSyntaxCheckerRegistry().hasSyntaxChecker( newOid ) )
244         {
245             throw new LdapNamingException( "Oid " + newOid + " for new schema syntaxChecker is not unique.", 
246                 ResultCodeEnum.OTHER );
247         }
248 
249         targetEntry.put( MetaSchemaConstants.M_OID_AT, newOid );
250         SyntaxChecker syntaxChecker = factory.getSyntaxChecker( targetEntry, targetRegistries );
251 
252         if ( ! oldSchema.isDisabled() )
253         {
254             syntaxCheckerRegistry.unregister( oldOid );
255         }
256 
257         if ( ! newSchema.isDisabled() )
258         {
259             SyntaxCheckerDescription syntaxCheckerDescription = 
260                 getSyntaxCheckerDescription( newSchema.getSchemaName(), entry );
261             syntaxCheckerDescription.setNumericOid( newOid );
262             syntaxCheckerRegistry.register( syntaxCheckerDescription, syntaxChecker );
263         }
264     }
265 
266 
267     public void replace( LdapDN oriChildName, LdapDN newParentName, ServerEntry entry, boolean cascade ) 
268         throws Exception
269     {
270         checkNewParent( newParentName );
271         String oid = getOid( entry );
272 
273         if ( syntaxRegistry.hasSyntax( oid ) )
274         {
275             throw new LdapOperationNotSupportedException( "The syntaxChecker with OID " + oid 
276                 + " cannot be moved to another schema until all " 
277                 + "syntax using that syntaxChecker have been deleted.", 
278                 ResultCodeEnum.UNWILLING_TO_PERFORM );
279         }
280 
281         Schema oldSchema = getSchema( oriChildName );
282         Schema newSchema = getSchema( newParentName );
283         
284         SyntaxChecker syntaxChecker = factory.getSyntaxChecker( entry, targetRegistries );
285         
286         if ( ! oldSchema.isDisabled() )
287         {
288             syntaxCheckerRegistry.unregister( oid );
289         }
290         
291         if ( ! newSchema.isDisabled() )
292         {
293             SyntaxCheckerDescription syntaxCheckerDescription = 
294                 getSyntaxCheckerDescription( newSchema.getSchemaName(), entry );
295             syntaxCheckerRegistry.register( syntaxCheckerDescription, syntaxChecker );
296         }
297     }
298     
299     
300     private void checkNewParent( LdapDN newParent ) throws NamingException
301     {
302         if ( newParent.size() != 3 )
303         {
304             throw new LdapInvalidNameException( 
305                 "The parent dn of a syntaxChecker should be at most 3 name components in length.", 
306                 ResultCodeEnum.NAMING_VIOLATION );
307         }
308         
309         Rdn rdn = newParent.getRdn();
310         if ( ! targetRegistries.getOidRegistry().getOid( rdn.getNormType() ).equals( SchemaConstants.OU_AT_OID ) )
311         {
312             throw new LdapInvalidNameException( "The parent entry of a syntaxChecker should be an organizationalUnit.", 
313                 ResultCodeEnum.NAMING_VIOLATION );
314         }
315         
316         if ( ! ( ( String ) rdn.getValue() ).equalsIgnoreCase( SchemaConstants.SYNTAX_CHECKERS_AT ) )
317         {
318             throw new LdapInvalidNameException( 
319                 "The parent entry of a normalizer should have a relative name of ou=syntaxCheckers.", 
320                 ResultCodeEnum.NAMING_VIOLATION );
321         }
322     }
323 }