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.api.schema.registries.synchronizers;
21  
22  
23  import org.apache.directory.api.ldap.model.constants.MetaSchemaConstants;
24  import org.apache.directory.api.ldap.model.constants.SchemaConstants;
25  import org.apache.directory.api.ldap.model.entry.Entry;
26  import org.apache.directory.api.ldap.model.exception.LdapException;
27  import org.apache.directory.api.ldap.model.exception.LdapUnwillingToPerformException;
28  import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
29  import org.apache.directory.api.ldap.model.name.Dn;
30  import org.apache.directory.api.ldap.model.name.Rdn;
31  import org.apache.directory.api.ldap.model.schema.AttributeType;
32  import org.apache.directory.api.ldap.model.schema.SchemaManager;
33  import org.apache.directory.api.ldap.model.schema.registries.Schema;
34  import org.apache.directory.api.util.Strings;
35  import org.apache.directory.server.core.api.interceptor.context.ModifyOperationContext;
36  import org.apache.directory.server.i18n.I18n;
37  import org.slf4j.Logger;
38  import org.slf4j.LoggerFactory;
39  
40  
41  /**
42   * A handler for operations performed to add, delete, modify, rename and 
43   * move schema AttributeTypes.
44   *
45   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
46   */
47  public class AttributeTypeSynchronizer extends AbstractRegistrySynchronizer
48  {
49      /** A logger for this class */
50      private static final Logger LOG = LoggerFactory.getLogger( AttributeTypeSynchronizer.class );
51  
52  
53      /**
54       * Creates a new instance of AttributeTypeSynchronizer.
55       *
56       * @param schemaManager The global schemaManager
57       * @throws Exception If the initialization failed
58       */
59      public AttributeTypeSynchronizer( SchemaManager schemaManager ) throws Exception
60      {
61          super( schemaManager );
62      }
63  
64  
65      /**
66       * {@inheritDoc}
67       */
68      @Override
69      public void add( Entry entry ) throws LdapException
70      {
71          Dn dn = entry.getDn();
72          Dn parentDn = dn.getParent();
73  
74          // The parent Dn must be ou=attributetypes,cn=<schemaName>,ou=schema
75          checkParent( parentDn, schemaManager, SchemaConstants.ATTRIBUTE_TYPE );
76  
77          // The new schemaObject's OID must not already exist
78          checkOidIsUnique( entry );
79  
80          // Build the new AttributeType from the given entry
81          String schemaName = getSchemaName( dn );
82  
83          AttributeType attributeType = factory.getAttributeType( schemaManager, entry, schemaManager.getRegistries(),
84              schemaName );
85  
86          // At this point, the constructed AttributeType has not been checked against the 
87          // existing Registries. It may be broken (missing SUP, or such), it will be checked
88          // there, if the schema and the AttributeType are both enabled.
89          Schema schema = schemaManager.getLoadedSchema( schemaName );
90  
91          if ( schema.isEnabled() && attributeType.isEnabled() )
92          {
93              if ( schemaManager.add( attributeType ) )
94              {
95                  LOG.debug( "Added {} into the enabled schema {}", dn.getName(), schemaName );
96              }
97              else
98              {
99                  // We have some error : reject the addition and get out
100                 String msg = I18n.err( I18n.ERR_345, entry.getDn().getName(),
101                     Strings.listToString( schemaManager.getErrors() ) );
102                 LOG.info( msg );
103                 throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM, msg );
104             }
105         }
106         else
107         {
108             LOG.debug( "The AttributeType {} cannot be added in the disabled schema {}.", attributeType, schemaName );
109         }
110     }
111 
112 
113     /**
114      * {@inheritDoc}
115      */
116     @Override
117     public boolean modify( ModifyOperationContext modifyContext, Entry targetEntry, boolean cascade )
118         throws LdapException
119     {
120         Dn name = modifyContext.getDn();
121         Entry entry = modifyContext.getEntry();
122         String schemaName = getSchemaName( name );
123         String oid = getOid( entry );
124         AttributeType at = factory.getAttributeType( schemaManager, targetEntry, schemaManager.getRegistries(),
125             schemaName );
126 
127         if ( isSchemaEnabled( schemaName ) )
128         {
129             if ( schemaManager.getAttributeTypeRegistry().contains( oid ) )
130             {
131                 schemaManager.unregisterAttributeType( oid );
132             }
133 
134             schemaManager.add( at );
135 
136             return SCHEMA_MODIFIED;
137         }
138 
139         return SCHEMA_UNCHANGED;
140     }
141 
142 
143     /**
144      * {@inheritDoc}
145      */
146     @Override
147     public void delete( Entry entry, boolean cascade ) throws LdapException
148     {
149         Dn dn = entry.getDn();
150         Dn parentDn = dn.getParent();
151 
152         // The parent Dn must be ou=attributetypes,cn=<schemaName>,ou=schema
153         checkParent( parentDn, schemaManager, SchemaConstants.ATTRIBUTE_TYPE );
154 
155         // Get the SchemaName
156         String schemaName = getSchemaName( entry.getDn() );
157 
158         // Get the schema 
159         Schema schema = schemaManager.getLoadedSchema( schemaName );
160 
161         if ( schema.isDisabled() )
162         {
163             // The schema is disabled, nothing to do.
164             LOG.debug( "The AttributeType {} cannot be removed from the disabled schema {}.",
165                 dn.getName(), schemaName );
166 
167             return;
168         }
169 
170         // Test that the Oid exists
171         AttributeType attributeType = ( AttributeType ) checkOidExists( entry );
172 
173         if ( schema.isEnabled() && attributeType.isEnabled() )
174         {
175             if ( schemaManager.delete( attributeType ) )
176             {
177                 LOG.debug( "Removed {} from the schema {}", attributeType, schemaName );
178             }
179             else
180             {
181                 // We have some error : reject the deletion and get out
182                 String msg = I18n.err( I18n.ERR_346, entry.getDn().getName(),
183                     Strings.listToString( schemaManager.getErrors() ) );
184                 LOG.info( msg );
185                 throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM, msg );
186             }
187         }
188         else
189         {
190             LOG.debug( "Removed {} from the disabled schema {}", attributeType, schemaName );
191         }
192     }
193 
194 
195     /**
196      * {@inheritDoc}
197      */
198     @Override
199     public void rename( Entry entry, Rdn newRdn, boolean cascade ) throws LdapException
200     {
201         String schemaName = getSchemaName( entry.getDn() );
202         AttributeType oldAt = factory
203             .getAttributeType( schemaManager, entry, schemaManager.getRegistries(), schemaName );
204 
205         // Inject the new OID
206         Entry targetEntry =  entry.clone();
207         String newOid = newRdn.getValue();
208         checkOidIsUnique( newOid );
209         targetEntry.put( MetaSchemaConstants.M_OID_AT, newOid );
210 
211         // Inject the new Dn
212         Dn newDn = targetEntry.getDn().getParent();
213         newDn = newDn.add( newRdn );
214         targetEntry.setDn( newDn );
215 
216         AttributeType at = factory.getAttributeType( schemaManager, targetEntry, schemaManager.getRegistries(),
217             schemaName );
218 
219         if ( isSchemaEnabled( schemaName ) )
220         {
221             // Check that the entry has no descendant
222             if ( schemaManager.getAttributeTypeRegistry().hasDescendants( oldAt.getOid() ) )
223             {
224                 String msg = I18n.err( I18n.ERR_347, entry.getDn().getName(), newDn );
225 
226                 throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM, msg );
227             }
228 
229             schemaManager.unregisterAttributeType( oldAt.getOid() );
230             schemaManager.add( at );
231         }
232         else
233         {
234             unregisterOids( oldAt );
235             registerOids( at );
236         }
237     }
238 
239 
240     /**
241      * {@inheritDoc}
242      */
243     @Override
244     public void moveAndRename( Dn oriChildName, Dn newParentName, Rdn newRn, boolean deleteOldRn,
245         Entry entry, boolean cascade ) throws LdapException
246     {
247         checkParent( newParentName, schemaManager, SchemaConstants.ATTRIBUTE_TYPE );
248         String oldSchemaName = getSchemaName( oriChildName );
249         String newSchemaName = getSchemaName( newParentName );
250         AttributeType oldAt = factory.getAttributeType( schemaManager, entry, schemaManager.getRegistries(),
251             oldSchemaName );
252         Entry targetEntry = entry.clone();
253         String newOid = newRn.getValue();
254         targetEntry.put( MetaSchemaConstants.M_OID_AT, newOid );
255         checkOidIsUnique( newOid );
256         AttributeType newAt = factory.getAttributeType( schemaManager, targetEntry, schemaManager.getRegistries(),
257             newSchemaName );
258 
259         if ( !isSchemaLoaded( oldSchemaName ) )
260         {
261             String msg = I18n.err( I18n.ERR_348, oldSchemaName );
262             LOG.warn( msg );
263             throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM, msg );
264         }
265 
266         if ( !isSchemaLoaded( newSchemaName ) )
267         {
268             String msg = I18n.err( I18n.ERR_349, newSchemaName );
269             LOG.warn( msg );
270             throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM, msg );
271         }
272 
273         deleteFromSchema( oldAt, oldSchemaName );
274         addToSchema( newAt, newSchemaName );
275 
276         if ( isSchemaEnabled( oldSchemaName ) )
277         {
278             schemaManager.unregisterAttributeType( oldAt.getOid() );
279         }
280         else
281         {
282             unregisterOids( oldAt );
283         }
284 
285         if ( isSchemaEnabled( newSchemaName ) )
286         {
287             schemaManager.add( newAt );
288         }
289         else
290         {
291             registerOids( newAt );
292         }
293     }
294 
295 
296     /**
297      * {@inheritDoc}
298      */
299     @Override
300     public void move( Dn oriChildName, Dn newParentName, Entry entry, boolean cascade ) throws LdapException
301     {
302         checkParent( newParentName, schemaManager, SchemaConstants.ATTRIBUTE_TYPE );
303         String oldSchemaName = getSchemaName( oriChildName );
304         String newSchemaName = getSchemaName( newParentName );
305         AttributeType oldAt = factory.getAttributeType( schemaManager, entry, schemaManager.getRegistries(),
306             oldSchemaName );
307         AttributeType newAt = factory.getAttributeType( schemaManager, entry, schemaManager.getRegistries(),
308             newSchemaName );
309 
310         if ( !isSchemaLoaded( oldSchemaName ) )
311         {
312             String msg = "Cannot move a schemaObject from a not loaded schema " + oldSchemaName;
313             LOG.warn( msg );
314             throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM, msg );
315         }
316 
317         if ( !isSchemaLoaded( newSchemaName ) )
318         {
319             String msg = I18n.err( I18n.ERR_349, newSchemaName );
320             LOG.warn( msg );
321             throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM, msg );
322         }
323 
324         deleteFromSchema( oldAt, oldSchemaName );
325         addToSchema( newAt, newSchemaName );
326 
327         if ( isSchemaEnabled( oldSchemaName ) )
328         {
329             schemaManager.unregisterAttributeType( oldAt.getOid() );
330         }
331         else
332         {
333             unregisterOids( oldAt );
334         }
335 
336         if ( isSchemaEnabled( newSchemaName ) )
337         {
338             schemaManager.add( newAt );
339         }
340         else
341         {
342             registerOids( newAt );
343         }
344     }
345 }