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.LdapInvalidDnException;
28  import org.apache.directory.api.ldap.model.exception.LdapUnwillingToPerformException;
29  import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
30  import org.apache.directory.api.ldap.model.name.Dn;
31  import org.apache.directory.api.ldap.model.name.Rdn;
32  import org.apache.directory.api.ldap.model.schema.MatchingRule;
33  import org.apache.directory.api.ldap.model.schema.SchemaManager;
34  import org.apache.directory.api.ldap.model.schema.registries.Schema;
35  import org.apache.directory.api.util.Strings;
36  import org.apache.directory.server.core.api.interceptor.context.ModifyOperationContext;
37  import org.apache.directory.server.i18n.I18n;
38  import org.slf4j.Logger;
39  import org.slf4j.LoggerFactory;
40  
41  
42  /**
43   * A handler for operations performed to add, delete, modify, rename and 
44   * move schema normalizers.
45   *
46   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
47   */
48  public class MatchingRuleSynchronizer extends AbstractRegistrySynchronizer
49  {
50      /** A logger for this class */
51      private static final Logger LOG = LoggerFactory.getLogger( MatchingRuleSynchronizer.class );
52  
53  
54      /**
55       * Creates a new instance of MatchingRuleSynchronizer.
56       *
57       * @param schemaManager The global schemaManager
58       * @throws Exception If the initialization failed
59       */
60      public MatchingRuleSynchronizer( SchemaManager schemaManager ) throws Exception
61      {
62          super( schemaManager );
63      }
64  
65  
66      /**
67       * {@inheritDoc}
68       */
69      @Override
70      public boolean modify( ModifyOperationContext modifyContext, Entry targetEntry, boolean cascade )
71          throws LdapException
72      {
73          Dn name = modifyContext.getDn();
74          Entry entry = modifyContext.getEntry();
75          String schemaName = getSchemaName( name );
76          MatchingRule mr = factory.getMatchingRule( schemaManager, targetEntry, schemaManager.getRegistries(),
77              schemaName );
78  
79          String oldOid = getOid( entry );
80  
81          if ( isSchemaEnabled( schemaName ) )
82          {
83              schemaManager.unregisterMatchingRule( oldOid );
84              schemaManager.add( mr );
85  
86              return SCHEMA_MODIFIED;
87          }
88          else
89          {
90              return SCHEMA_UNCHANGED;
91          }
92      }
93  
94  
95      /**
96       * {@inheritDoc}
97       */
98      @Override
99      public void add( Entry entry ) throws LdapException
100     {
101         Dn dn = entry.getDn();
102         Dn parentDn = dn.getParent();
103 
104         // The parent Dn must be ou=matchingrules,cn=<schemaName>,ou=schema
105         checkParent( parentDn, schemaManager, SchemaConstants.MATCHING_RULE );
106 
107         // The new schemaObject's OID must not already exist
108         checkOidIsUnique( entry );
109 
110         // Build the new MatchingRule from the given entry
111         String schemaName = getSchemaName( dn );
112 
113         MatchingRule matchingRule = factory.getMatchingRule( schemaManager, entry, schemaManager.getRegistries(),
114             schemaName );
115 
116         // At this point, the constructed MatchingRule has not been checked against the 
117         // existing Registries. It may be broken (missing SUP, or such), it will be checked
118         // there, if the schema and the MatchingRule are both enabled.
119         Schema schema = schemaManager.getLoadedSchema( schemaName );
120 
121         if ( schema.isEnabled() && matchingRule.isEnabled() )
122         {
123             if ( schemaManager.add( matchingRule ) )
124             {
125                 LOG.debug( "Added {} into the enabled schema {}", dn.getName(), schemaName );
126             }
127             else
128             {
129                 // We have some error : reject the addition and get out
130                 String msg = I18n.err( I18n.ERR_360, entry.getDn().getName(),
131                     Strings.listToString( schemaManager.getErrors() ) );
132                 LOG.info( msg );
133                 throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM, msg );
134             }
135         }
136         else
137         {
138             LOG.debug( "The MztchingRule {} cannot be added in the disabled schema {}.", matchingRule, schemaName );
139         }
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=matchingrules,cn=<schemaName>,ou=schema
153         checkParent( parentDn, schemaManager, SchemaConstants.MATCHING_RULE );
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 MatchingRule {} cannot be removed from the disabled schema {}.",
165                 dn.getName(), schemaName );
166 
167             return;
168         }
169 
170         // Test that the Oid exists
171         MatchingRule matchingRule = ( MatchingRule ) checkOidExists( entry );
172 
173         if ( schema.isEnabled() && matchingRule.isEnabled() )
174         {
175             if ( schemaManager.delete( matchingRule ) )
176             {
177                 LOG.debug( "Removed {} from the schema {}", matchingRule, schemaName );
178             }
179             else
180             {
181                 // We have some error : reject the deletion and get out
182                 // The schema is disabled. We still have to update the backend
183                 String msg = I18n.err( I18n.ERR_360, entry.getDn().getName(),
184                     Strings.listToString( schemaManager.getErrors() ) );
185                 LOG.info( msg );
186                 throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM, msg );
187             }
188         }
189         else
190         {
191             LOG.debug( "Removed {} from the disabled schema {}", matchingRule, schemaName );
192         }
193     }
194 
195 
196     /**
197      * {@inheritDoc}
198      */
199     @Override
200     public void rename( Entry entry, Rdn newRdn, boolean cascade ) throws LdapException
201     {
202         String schemaName = getSchemaName( entry.getDn() );
203         MatchingRule oldMr = factory.getMatchingRule( schemaManager, entry, schemaManager.getRegistries(), schemaName );
204         Entry targetEntry = entry.clone();
205         String newOid = newRdn.getValue();
206         checkOidIsUnique( newOid );
207 
208         targetEntry.put( MetaSchemaConstants.M_OID_AT, newOid );
209         MatchingRule mr = factory.getMatchingRule( schemaManager, targetEntry, schemaManager.getRegistries(),
210             schemaName );
211 
212         if ( isSchemaEnabled( schemaName ) )
213         {
214             schemaManager.unregisterMatchingRule( oldMr.getOid() );
215             schemaManager.add( mr );
216         }
217         else
218         {
219             unregisterOids( oldMr );
220             registerOids( mr );
221         }
222     }
223 
224 
225     /**
226      * {@inheritDoc}
227      */
228     @Override
229     public void moveAndRename( Dn oriChildName, Dn newParentName, Rdn newRdn, boolean deleteOldRn,
230         Entry entry, boolean cascade ) throws LdapException
231     {
232         checkNewParent( newParentName );
233         String oldSchemaName = getSchemaName( oriChildName );
234         String newSchemaName = getSchemaName( newParentName );
235         MatchingRule oldMr = factory.getMatchingRule( schemaManager, entry, schemaManager.getRegistries(),
236             oldSchemaName );
237         Entry targetEntry = entry.clone();
238         String newOid = newRdn.getValue();
239         checkOidIsUnique( newOid );
240 
241         targetEntry.put( MetaSchemaConstants.M_OID_AT, newOid );
242         MatchingRule mr = factory.getMatchingRule( schemaManager, targetEntry, schemaManager.getRegistries(),
243             newSchemaName );
244 
245         if ( isSchemaEnabled( oldSchemaName ) )
246         {
247             schemaManager.unregisterMatchingRule( oldMr.getOid() );
248         }
249         else
250         {
251             unregisterOids( oldMr );
252         }
253 
254         if ( isSchemaEnabled( newSchemaName ) )
255         {
256             schemaManager.add( mr );
257         }
258         else
259         {
260             registerOids( mr );
261         }
262     }
263 
264 
265     /**
266      * {@inheritDoc}
267      */
268     @Override
269     public void move( Dn oriChildName, Dn newParentName, Entry entry, boolean cascade ) throws LdapException
270     {
271         checkNewParent( newParentName );
272         String oldSchemaName = getSchemaName( oriChildName );
273         String newSchemaName = getSchemaName( newParentName );
274         MatchingRule oldMr = factory.getMatchingRule( schemaManager, entry, schemaManager.getRegistries(),
275             oldSchemaName );
276         MatchingRule newMr = factory.getMatchingRule( schemaManager, entry, schemaManager.getRegistries(),
277             newSchemaName );
278 
279         if ( isSchemaEnabled( oldSchemaName ) )
280         {
281             schemaManager.unregisterMatchingRule( oldMr.getOid() );
282         }
283         else
284         {
285             unregisterOids( oldMr );
286         }
287 
288         if ( isSchemaEnabled( newSchemaName ) )
289         {
290             schemaManager.add( newMr );
291         }
292         else
293         {
294             registerOids( newMr );
295         }
296     }
297 
298 
299     private void checkNewParent( Dn newParent ) throws LdapException
300     {
301         if ( newParent.size() != 3 )
302         {
303             throw new LdapInvalidDnException( ResultCodeEnum.NAMING_VIOLATION,
304                 I18n.err( I18n.ERR_361 ) );
305         }
306 
307         Rdn rdn = newParent.getRdn();
308 
309         if ( !schemaManager.getAttributeTypeRegistry().getOidByName( rdn.getNormType() ).equals(
310             SchemaConstants.OU_AT_OID ) )
311         {
312             throw new LdapInvalidDnException( ResultCodeEnum.NAMING_VIOLATION,
313                 I18n.err( I18n.ERR_362 ) );
314         }
315 
316         if ( !rdn.getValue().equalsIgnoreCase( SchemaConstants.MATCHING_RULES_AT ) )
317         {
318             throw new LdapInvalidDnException( ResultCodeEnum.NAMING_VIOLATION,
319                 I18n.err( I18n.ERR_363 ) );
320         }
321     }
322 }