001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied. See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 *
019 */
020 package org.apache.directory.server.core.schema.registries.synchronizers;
021
022
023 import java.util.ArrayList;
024 import java.util.List;
025
026 import org.apache.directory.server.core.interceptor.context.ModifyOperationContext;
027 import org.apache.directory.server.i18n.I18n;
028 import org.apache.directory.shared.ldap.constants.MetaSchemaConstants;
029 import org.apache.directory.shared.ldap.constants.SchemaConstants;
030 import org.apache.directory.shared.ldap.entry.ServerEntry;
031 import org.apache.directory.shared.ldap.exception.LdapException;
032 import org.apache.directory.shared.ldap.exception.LdapInvalidDnException;
033 import org.apache.directory.shared.ldap.exception.LdapSchemaViolationException;
034 import org.apache.directory.shared.ldap.exception.LdapUnwillingToPerformException;
035 import org.apache.directory.shared.ldap.message.ResultCodeEnum;
036 import org.apache.directory.shared.ldap.name.DN;
037 import org.apache.directory.shared.ldap.name.RDN;
038 import org.apache.directory.shared.ldap.schema.Normalizer;
039 import org.apache.directory.shared.ldap.schema.SchemaManager;
040 import org.apache.directory.shared.ldap.schema.registries.Schema;
041 import org.apache.directory.shared.ldap.util.StringTools;
042 import org.slf4j.Logger;
043 import org.slf4j.LoggerFactory;
044
045
046 /**
047 *
048 *
049 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
050 * @version $Rev$, $Date$
051 */
052 public class NormalizerSynchronizer extends AbstractRegistrySynchronizer
053 {
054 /** A logger for this class */
055 private static final Logger LOG = LoggerFactory.getLogger( NormalizerSynchronizer.class );
056
057
058 /**
059 * Creates a new instance of NormalizerSynchronizer.
060 *
061 * @param registries The global registries
062 * @throws Exception If the initialization failed
063 */
064 public NormalizerSynchronizer( SchemaManager schemaManager ) throws Exception
065 {
066 super( schemaManager );
067 }
068
069
070 /**
071 * {@inheritDoc}
072 */
073 public boolean modify( ModifyOperationContext opContext, ServerEntry targetEntry, boolean cascade )
074 throws Exception
075 {
076 DN name = opContext.getDn();
077 ServerEntry entry = opContext.getEntry();
078 String schemaName = getSchemaName( name );
079 String oldOid = getOid( entry );
080 Normalizer normalizer = factory.getNormalizer( schemaManager, targetEntry, schemaManager.getRegistries(),
081 schemaName );
082
083 if ( isSchemaEnabled( schemaName ) )
084 {
085 normalizer.setSchemaName( schemaName );
086
087 schemaManager.unregisterNormalizer( oldOid );
088 schemaManager.add( normalizer );
089
090 return SCHEMA_MODIFIED;
091 }
092
093 return SCHEMA_UNCHANGED;
094 }
095
096
097 /**
098 * {@inheritDoc}
099 */
100 public void add( ServerEntry entry ) throws Exception
101 {
102 DN dn = entry.getDn();
103 DN parentDn = ( DN ) dn.clone();
104 parentDn.remove( parentDn.size() - 1 );
105
106 // The parent DN must be ou=normalizers,cn=<schemaName>,ou=schema
107 checkParent( parentDn, schemaManager, SchemaConstants.NORMALIZER );
108
109 // The new schemaObject's OID must not already exist
110 checkOidIsUniqueForNormalizer( entry );
111
112 // Build the new Normalizer from the given entry
113 String schemaName = getSchemaName( dn );
114
115 Normalizer normalizer = factory.getNormalizer( schemaManager, entry, schemaManager.getRegistries(), schemaName );
116
117 // At this point, the constructed Normalizer has not been checked against the
118 // existing Registries. It will be checked there, if the schema and the
119 // Normalizer are both enabled.
120 Schema schema = schemaManager.getLoadedSchema( schemaName );
121 List<Throwable> errors = new ArrayList<Throwable>();
122
123 if ( schema.isEnabled() && normalizer.isEnabled() )
124 {
125 if ( schemaManager.add( normalizer ) )
126 {
127 LOG.debug( "Added {} into the enabled schema {}", dn.getName(), schemaName );
128 }
129 else
130 {
131 String msg = I18n.err( I18n.ERR_364, entry.getDn().getName(),
132 StringTools.listToString( errors ) );
133 LOG.info( msg );
134 throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM, msg );
135 }
136 }
137 else
138 {
139 // At least, we associates the Normalizer with the schema
140 schemaManager.getRegistries().associateWithSchema( errors, normalizer );
141
142 if ( !errors.isEmpty() )
143 {
144 String msg = I18n.err( I18n.ERR_365, entry.getDn().getName(),
145 StringTools.listToString( errors ) );
146
147 throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM, msg );
148 }
149
150 LOG.debug( "The normalizer {} cannot be added in schema {}", dn.getName(), schemaName );
151 }
152 }
153
154
155 /**
156 * {@inheritDoc}
157 */
158 public void delete( ServerEntry entry, boolean cascade ) throws Exception
159 {
160 DN dn = entry.getDn();
161 DN parentDn = ( DN ) dn.clone();
162 parentDn.remove( parentDn.size() - 1 );
163
164 // The parent DN must be ou=normalizers,cn=<schemaName>,ou=schema
165 checkParent( parentDn, schemaManager, SchemaConstants.NORMALIZER );
166
167 // Get the Normalizer from the given entry ( it has been grabbed from the server earlier)
168 String schemaName = getSchemaName( entry.getDn() );
169 Normalizer normalizer = factory.getNormalizer( schemaManager, entry, schemaManager.getRegistries(), schemaName );
170
171 String oid = normalizer.getOid();
172
173 if ( isSchemaEnabled( schemaName ) )
174 {
175 if ( schemaManager.getRegistries().isReferenced( normalizer ) )
176 {
177 String msg = I18n.err( I18n.ERR_366, entry.getDn().getName(), getReferenced( normalizer ) );
178 LOG.warn( msg );
179 throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM, msg );
180 }
181
182 // As the normalizer has the same OID than its attached MR, it won't
183 // be loaded into the schemaManager if it's disabled
184 deleteFromSchema( normalizer, schemaName );
185 }
186
187 if ( schemaManager.getNormalizerRegistry().contains( oid ) )
188 {
189 schemaManager.unregisterNormalizer( oid );
190 LOG.debug( "Removed {} from the enabled schema {}", normalizer, schemaName );
191 }
192 else
193 {
194 LOG.debug( "Removed {} from the enabled schema {}", normalizer, schemaName );
195 }
196 }
197
198
199 /**
200 * {@inheritDoc}
201 */
202 public void rename( ServerEntry entry, RDN newRdn, boolean cascade ) throws Exception
203 {
204 String oldOid = getOid( entry );
205 String schemaName = getSchemaName( entry.getDn() );
206
207 if ( schemaManager.getMatchingRuleRegistry().contains( oldOid ) )
208 {
209 throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM,
210 I18n.err( I18n.ERR_367, oldOid ) );
211 }
212
213 String newOid = ( String ) newRdn.getNormValue();
214 checkOidIsUniqueForNormalizer( newOid );
215
216 if ( isSchemaEnabled( schemaName ) )
217 {
218 // Inject the new OID
219 ServerEntry targetEntry = ( ServerEntry ) entry.clone();
220 targetEntry.put( MetaSchemaConstants.M_OID_AT, newOid );
221
222 // Inject the new DN
223 DN newDn = new DN( targetEntry.getDn() );
224 newDn.remove( newDn.size() - 1 );
225 newDn.add( newRdn );
226 targetEntry.setDn( newDn );
227
228 Normalizer normalizer = factory.getNormalizer( schemaManager, targetEntry, schemaManager.getRegistries(),
229 schemaName );
230 schemaManager.unregisterNormalizer( oldOid );
231 schemaManager.add( normalizer );
232 }
233 }
234
235
236 public void moveAndRename( DN oriChildName, DN newParentName, RDN newRdn, boolean deleteOldRn,
237 ServerEntry entry, boolean cascade ) throws Exception
238 {
239 checkNewParent( newParentName );
240 String oldOid = getOid( entry );
241 String oldSchemaName = getSchemaName( oriChildName );
242 String newSchemaName = getSchemaName( newParentName );
243
244 if ( schemaManager.getMatchingRuleRegistry().contains( oldOid ) )
245 {
246 throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM,
247 I18n.err( I18n.ERR_367, oldOid ) );
248 }
249
250 String oid = ( String ) newRdn.getNormValue();
251 checkOidIsUniqueForNormalizer( oid );
252 Normalizer normalizer = factory.getNormalizer( schemaManager, entry, schemaManager.getRegistries(),
253 newSchemaName );
254
255 if ( isSchemaEnabled( oldSchemaName ) )
256 {
257 schemaManager.unregisterNormalizer( oldOid );
258 }
259
260 if ( isSchemaEnabled( newSchemaName ) )
261 {
262 schemaManager.add( normalizer );
263 }
264 }
265
266
267 public void move( DN oriChildName, DN newParentName, ServerEntry entry, boolean cascade ) throws Exception
268 {
269 checkNewParent( newParentName );
270 String oid = getOid( entry );
271 String oldSchemaName = getSchemaName( oriChildName );
272 String newSchemaName = getSchemaName( newParentName );
273
274 if ( schemaManager.getMatchingRuleRegistry().contains( oid ) )
275 {
276 throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM,
277 I18n.err( I18n.ERR_368, oid ) );
278 }
279
280 Normalizer normalizer = factory.getNormalizer( schemaManager, entry, schemaManager.getRegistries(),
281 newSchemaName );
282
283 if ( isSchemaEnabled( oldSchemaName ) )
284 {
285 schemaManager.unregisterNormalizer( oid );
286 }
287
288 if ( isSchemaEnabled( newSchemaName ) )
289 {
290 schemaManager.add( normalizer );
291 }
292 }
293
294
295 private void checkOidIsUniqueForNormalizer( String oid ) throws Exception
296 {
297 if ( schemaManager.getNormalizerRegistry().contains( oid ) )
298 {
299 throw new LdapSchemaViolationException( ResultCodeEnum.OTHER,
300 I18n.err( I18n.ERR_369, oid ) );
301 }
302 }
303
304
305 private void checkOidIsUniqueForNormalizer( ServerEntry entry ) throws Exception
306 {
307 String oid = getOid( entry );
308
309 if ( schemaManager.getNormalizerRegistry().contains( oid ) )
310 {
311 throw new LdapSchemaViolationException( ResultCodeEnum.OTHER,
312 I18n.err( I18n.ERR_369, oid ) );
313 }
314 }
315
316
317 private void checkNewParent( DN newParent ) throws LdapException
318 {
319 if ( newParent.size() != 3 )
320 {
321 throw new LdapInvalidDnException( ResultCodeEnum.NAMING_VIOLATION, I18n.err( I18n.ERR_370 ) );
322 }
323
324 RDN rdn = newParent.getRdn();
325
326 if ( !schemaManager.getAttributeTypeRegistry().getOidByName( rdn.getNormType() ).equals(
327 SchemaConstants.OU_AT_OID ) )
328 {
329 throw new LdapInvalidDnException( ResultCodeEnum.NAMING_VIOLATION, I18n.err( I18n.ERR_371 ) );
330 }
331
332 if ( !( ( String ) rdn.getNormValue() ).equalsIgnoreCase( SchemaConstants.NORMALIZERS_AT ) )
333 {
334 throw new LdapInvalidDnException( ResultCodeEnum.NAMING_VIOLATION, I18n.err( I18n.ERR_372 ) );
335 }
336 }
337 }