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 org.apache.directory.server.core.interceptor.context.ModifyOperationContext;
024 import org.apache.directory.server.i18n.I18n;
025 import org.apache.directory.shared.ldap.constants.MetaSchemaConstants;
026 import org.apache.directory.shared.ldap.constants.SchemaConstants;
027 import org.apache.directory.shared.ldap.entry.ServerEntry;
028 import org.apache.directory.shared.ldap.exception.LdapException;
029 import org.apache.directory.shared.ldap.exception.LdapInvalidDnException;
030 import org.apache.directory.shared.ldap.exception.LdapSchemaViolationException;
031 import org.apache.directory.shared.ldap.exception.LdapUnwillingToPerformException;
032 import org.apache.directory.shared.ldap.message.ResultCodeEnum;
033 import org.apache.directory.shared.ldap.name.DN;
034 import org.apache.directory.shared.ldap.name.RDN;
035 import org.apache.directory.shared.ldap.schema.SchemaManager;
036 import org.apache.directory.shared.ldap.schema.SyntaxChecker;
037 import org.apache.directory.shared.ldap.schema.registries.Registries;
038 import org.apache.directory.shared.ldap.schema.registries.Schema;
039 import org.apache.directory.shared.ldap.util.StringTools;
040 import org.slf4j.Logger;
041 import org.slf4j.LoggerFactory;
042
043
044 /**
045 * A synchronizer which detects changes to syntaxCheckers and updates the
046 * respective {@link Registries}.
047 *
048 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
049 * @version $Rev$, $Date$
050 */
051 public class SyntaxCheckerSynchronizer extends AbstractRegistrySynchronizer
052 {
053 /** A logger for this class */
054 private static final Logger LOG = LoggerFactory.getLogger( SyntaxCheckerSynchronizer.class );
055
056
057 /**
058 * Creates a new instance of SyntaxCheckerSynchronizer.
059 *
060 * @param schemaManager The global schemaManager
061 * @throws Exception If the initialization failed
062 */
063 public SyntaxCheckerSynchronizer( SchemaManager schemaManager ) throws Exception
064 {
065 super( schemaManager );
066 }
067
068
069 /**
070 * {@inheritDoc}
071 */
072 public boolean modify( ModifyOperationContext opContext, ServerEntry targetEntry, boolean cascade )
073 throws Exception
074 {
075 DN name = opContext.getDn();
076 ServerEntry entry = opContext.getEntry();
077 String schemaName = getSchemaName( name );
078 String oid = getOid( entry );
079 SyntaxChecker syntaxChecker = factory.getSyntaxChecker( schemaManager, targetEntry, schemaManager
080 .getRegistries(), schemaName );
081
082 if ( isSchemaEnabled( schemaName ) )
083 {
084 syntaxChecker.setSchemaName( schemaName );
085
086 schemaManager.unregisterSyntaxChecker( oid );
087 schemaManager.add( syntaxChecker );
088
089 return SCHEMA_MODIFIED;
090 }
091
092 return SCHEMA_UNCHANGED;
093 }
094
095
096 /**
097 * {@inheritDoc}
098 */
099 public void add( ServerEntry entry ) throws Exception
100 {
101 DN dn = entry.getDn();
102 DN parentDn = ( DN ) dn.clone();
103 parentDn.remove( parentDn.size() - 1 );
104
105 // The parent DN must be ou=syntaxcheckers,cn=<schemaName>,ou=schema
106 checkParent( parentDn, schemaManager, SchemaConstants.SYNTAX_CHECKER );
107
108 // The new schemaObject's OID must not already exist
109 checkOidIsUniqueForSyntaxChecker( entry );
110
111 // Build the new SyntaxChecker from the given entry
112 String schemaName = getSchemaName( dn );
113
114 SyntaxChecker syntaxChecker = factory.getSyntaxChecker( schemaManager, entry, schemaManager.getRegistries(),
115 schemaName );
116
117 // At this point, the constructed SyntaxChecker has not been checked against the
118 // existing Registries. It will be checked there, if the schema and the
119 // SyntaxChecker are both enabled.
120 Schema schema = schemaManager.getLoadedSchema( schemaName );
121
122 if ( schema.isEnabled() && syntaxChecker.isEnabled() )
123 {
124 if ( schemaManager.add( syntaxChecker ) )
125 {
126 LOG.debug( "Added {} into the enabled schema {}", dn.getName(), schemaName );
127 }
128 else
129 {
130 String msg = I18n.err( I18n.ERR_386, entry.getDn().getName(),
131 StringTools.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 SyntaxChecker {} cannot be added in the disabled schema {}", dn.getName(), schemaName );
139 }
140 }
141
142
143 /**
144 * {@inheritDoc}
145 */
146 public void delete( ServerEntry entry, boolean cascade ) throws Exception
147 {
148 DN dn = entry.getDn();
149 DN parentDn = ( DN ) dn.clone();
150 parentDn.remove( parentDn.size() - 1 );
151
152 // The parent DN must be ou=syntaxcheckers,cn=<schemaName>,ou=schema
153 checkParent( parentDn, schemaManager, SchemaConstants.SYNTAX_CHECKER );
154
155 // Get the SyntaxChecker's instance
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 SyntaxChecker {} cannot be deleted from the disabled schema {}", dn.getName(), schemaName );
165
166 return;
167 }
168
169 // Test that the Oid exists
170 SyntaxChecker syntaxChecker = null;
171
172 try
173 {
174 syntaxChecker = ( SyntaxChecker ) checkSyntaxCheckerOidExists( entry );
175 }
176 catch ( LdapSchemaViolationException lsve )
177 {
178 // The syntaxChecker does not exist
179 syntaxChecker = factory.getSyntaxChecker( schemaManager, entry, schemaManager.getRegistries(), schemaName );
180
181 if ( schemaManager.getRegistries().contains( syntaxChecker ) )
182 {
183 // Remove the syntaxChecker from the schema/SchemaObject Map
184 schemaManager.getRegistries().dissociateFromSchema( syntaxChecker );
185
186 // Ok, we can exit.
187 return;
188 }
189 else
190 {
191 // Ok, definitively an error
192 String msg = I18n.err( I18n.ERR_387, entry.getDn().getName() );
193 LOG.info( msg );
194 throw new LdapSchemaViolationException( ResultCodeEnum.UNWILLING_TO_PERFORM, msg );
195 }
196 }
197
198 if ( schema.isEnabled() && syntaxChecker.isEnabled() )
199 {
200 if ( schemaManager.delete( syntaxChecker ) )
201 {
202 LOG.debug( "Deleted {} from the enabled schema {}", dn.getName(), schemaName );
203 }
204 else
205 {
206 String msg = I18n.err( I18n.ERR_386, entry.getDn().getName(),
207 StringTools.listToString( schemaManager.getErrors() ) );
208 LOG.info( msg );
209 throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM, msg );
210 }
211 }
212 else
213 {
214 LOG.debug( "The syntaxChecker {} cannot be deleted from the disabled schema {}", dn.getName(), schemaName );
215 }
216 }
217
218
219 /**
220 * {@inheritDoc}
221 */
222 public void rename( ServerEntry entry, RDN newRdn, boolean cascade ) throws Exception
223 {
224 String oldOid = getOid( entry );
225 String schemaName = getSchemaName( entry.getDn() );
226
227 if ( schemaManager.getLdapSyntaxRegistry().contains( oldOid ) )
228 {
229 throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM,
230 I18n.err( I18n.ERR_389, oldOid ) );
231 }
232
233 ServerEntry targetEntry = ( ServerEntry ) entry.clone();
234 String newOid = ( String ) newRdn.getNormValue();
235
236 if ( schemaManager.getSyntaxCheckerRegistry().contains( newOid ) )
237 {
238 throw new LdapSchemaViolationException( ResultCodeEnum.OTHER,
239 I18n.err( I18n.ERR_390, newOid ) );
240 }
241
242 targetEntry.put( MetaSchemaConstants.M_OID_AT, newOid );
243
244 if ( isSchemaEnabled( schemaName ) )
245 {
246 SyntaxChecker syntaxChecker = factory.getSyntaxChecker( schemaManager, targetEntry, schemaManager
247 .getRegistries(), schemaName );
248 schemaManager.unregisterSyntaxChecker( oldOid );
249 schemaManager.add( syntaxChecker );
250 }
251 }
252
253
254 public void moveAndRename( DN oriChildName, DN newParentName, RDN newRdn, boolean deleteOldRn,
255 ServerEntry entry, boolean cascade ) throws Exception
256 {
257 checkNewParent( newParentName );
258 String oldOid = getOid( entry );
259 String oldSchemaName = getSchemaName( oriChildName );
260 String newSchemaName = getSchemaName( newParentName );
261
262 if ( schemaManager.getLdapSyntaxRegistry().contains( oldOid ) )
263 {
264 throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM,
265 I18n.err( I18n.ERR_391, oldOid ) );
266 }
267
268 ServerEntry targetEntry = ( ServerEntry ) entry.clone();
269
270 String newOid = ( String ) newRdn.getNormValue();
271
272 if ( schemaManager.getSyntaxCheckerRegistry().contains( newOid ) )
273 {
274 throw new LdapSchemaViolationException( ResultCodeEnum.OTHER,
275 I18n.err( I18n.ERR_390, newOid ) );
276 }
277
278 targetEntry.put( MetaSchemaConstants.M_OID_AT, newOid );
279 SyntaxChecker syntaxChecker = factory.getSyntaxChecker( schemaManager, targetEntry, schemaManager
280 .getRegistries(), newSchemaName );
281
282 if ( isSchemaEnabled( oldSchemaName ) )
283 {
284 schemaManager.unregisterSyntaxChecker( oldOid );
285 }
286
287 if ( isSchemaEnabled( newSchemaName ) )
288 {
289 schemaManager.add( syntaxChecker );
290 }
291 }
292
293
294 public void move( DN oriChildName, DN newParentName, ServerEntry entry, boolean cascade ) throws Exception
295 {
296 checkNewParent( newParentName );
297 String oid = getOid( entry );
298 String oldSchemaName = getSchemaName( oriChildName );
299 String newSchemaName = getSchemaName( newParentName );
300
301 if ( schemaManager.getLdapSyntaxRegistry().contains( oid ) )
302 {
303 throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM,
304 I18n.err( I18n.ERR_393, oid ) );
305 }
306
307 SyntaxChecker syntaxChecker = factory.getSyntaxChecker( schemaManager, entry, schemaManager.getRegistries(),
308 newSchemaName );
309
310 if ( isSchemaEnabled( oldSchemaName ) )
311 {
312 schemaManager.unregisterSyntaxChecker( oid );
313 }
314
315 if ( isSchemaEnabled( newSchemaName ) )
316 {
317 schemaManager.add( syntaxChecker );
318 }
319 }
320
321
322 private void checkOidIsUniqueForSyntaxChecker( ServerEntry entry ) throws Exception
323 {
324 String oid = getOid( entry );
325
326 if ( schemaManager.getNormalizerRegistry().contains( oid ) )
327 {
328 throw new LdapSchemaViolationException( ResultCodeEnum.OTHER,
329 I18n.err( I18n.ERR_390, oid ) );
330 }
331 }
332
333
334 /**
335 * Check that a SyntaxChecker exists in the SyntaxCheckerRegistry, and if so,
336 * return it.
337 */
338 protected SyntaxChecker checkSyntaxCheckerOidExists( ServerEntry entry ) throws Exception
339 {
340 String oid = getOid( entry );
341
342 if ( schemaManager.getSyntaxCheckerRegistry().contains( oid ) )
343 {
344 return (SyntaxChecker)schemaManager.getSyntaxCheckerRegistry().get( oid );
345 }
346 else
347 {
348 throw new LdapSchemaViolationException( ResultCodeEnum.OTHER,
349 I18n.err( I18n.ERR_336, oid ) );
350 }
351 }
352
353
354 private void checkNewParent( DN newParent ) throws LdapException
355 {
356 if ( newParent.size() != 3 )
357 {
358 throw new LdapInvalidDnException( ResultCodeEnum.NAMING_VIOLATION,
359 I18n.err( I18n.ERR_396 ) );
360 }
361
362 RDN rdn = newParent.getRdn();
363 if ( !schemaManager.getAttributeTypeRegistry().getOidByName( rdn.getNormType() ).equals(
364 SchemaConstants.OU_AT_OID ) )
365 {
366 throw new LdapInvalidDnException( ResultCodeEnum.NAMING_VIOLATION,
367 I18n.err( I18n.ERR_397 ) );
368 }
369
370 if ( !( ( String ) rdn.getNormValue() ).equalsIgnoreCase( SchemaConstants.SYNTAX_CHECKERS_AT ) )
371 {
372 throw new LdapInvalidDnException( ResultCodeEnum.NAMING_VIOLATION,
373 I18n.err( I18n.ERR_372 ) );
374 }
375 }
376 }