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.Iterator;
025 import java.util.List;
026 import java.util.Map;
027 import java.util.Set;
028
029 import org.apache.directory.server.core.CoreSession;
030 import org.apache.directory.server.core.OperationManager;
031 import org.apache.directory.server.core.entry.ServerEntryUtils;
032 import org.apache.directory.server.core.interceptor.context.ModifyOperationContext;
033 import org.apache.directory.server.core.partition.ByPassConstants;
034 import org.apache.directory.server.i18n.I18n;
035 import org.apache.directory.shared.ldap.constants.MetaSchemaConstants;
036 import org.apache.directory.shared.ldap.constants.SchemaConstants;
037 import org.apache.directory.shared.ldap.entry.DefaultServerAttribute;
038 import org.apache.directory.shared.ldap.entry.EntryAttribute;
039 import org.apache.directory.shared.ldap.entry.Modification;
040 import org.apache.directory.shared.ldap.entry.ModificationOperation;
041 import org.apache.directory.shared.ldap.entry.ServerEntry;
042 import org.apache.directory.shared.ldap.entry.ServerModification;
043 import org.apache.directory.shared.ldap.entry.Value;
044 import org.apache.directory.shared.ldap.exception.LdapException;
045 import org.apache.directory.shared.ldap.exception.LdapInvalidDnException;
046 import org.apache.directory.shared.ldap.exception.LdapUnwillingToPerformException;
047 import org.apache.directory.shared.ldap.message.ResultCodeEnum;
048 import org.apache.directory.shared.ldap.name.DN;
049 import org.apache.directory.shared.ldap.name.RDN;
050 import org.apache.directory.shared.ldap.schema.AttributeType;
051 import org.apache.directory.shared.ldap.schema.SchemaManager;
052 import org.apache.directory.shared.ldap.schema.SchemaObject;
053 import org.apache.directory.shared.ldap.schema.SchemaObjectType;
054 import org.apache.directory.shared.ldap.schema.SchemaObjectWrapper;
055 import org.apache.directory.shared.ldap.schema.loader.ldif.SchemaEntityFactory;
056 import org.apache.directory.shared.ldap.schema.registries.AttributeTypeRegistry;
057 import org.apache.directory.shared.ldap.schema.registries.DefaultSchemaObjectRegistry;
058 import org.apache.directory.shared.ldap.schema.registries.Registries;
059 import org.apache.directory.shared.ldap.schema.registries.Schema;
060 import org.apache.directory.shared.ldap.util.DateUtils;
061 import org.apache.directory.shared.ldap.util.StringTools;
062 import org.slf4j.Logger;
063 import org.slf4j.LoggerFactory;
064
065
066 /**
067 * This class handle modifications made on a global schema. Modifications made
068 * on SchemaObjects are handled by the specific shcemaObject synchronizers.
069 *
070 * @TODO poorly implemented - revisit the SchemaChangeHandler for this puppy
071 * and do it right.
072 *
073 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
074 * @version $Rev$, $Date$
075 */
076 public class SchemaSynchronizer implements RegistrySynchronizer
077 {
078 /** A logger for this class */
079 private static final Logger LOG = LoggerFactory.getLogger( SchemaSynchronizer.class );
080
081 private final SchemaEntityFactory factory;
082 //private final PartitionSchemaLoader loader;
083
084 private final SchemaManager schemaManager;
085
086 /** The global registries */
087 private final Registries registries;
088
089 /** The m-disable AttributeType */
090 private final AttributeType disabledAT;
091
092 /** The CN attributeType */
093 private final AttributeType cnAT;
094
095 /** The m-dependencies AttributeType */
096 private final AttributeType dependenciesAT;
097
098 /** The modifiersName AttributeType */
099 private final AttributeType modifiersNameAT;
100
101 /** The modifyTimestamp AttributeType */
102 private final AttributeType modifyTimestampAT;
103
104 /** A static DN referencing ou=schema */
105 private final DN ouSchemaDN;
106
107 /**
108 * Creates and initializes a new instance of Schema synchronizer
109 *
110 * @param registries The Registries
111 * @param loader The schema loader
112 * @throws Exception If something went wrong
113 */
114 public SchemaSynchronizer( SchemaManager schemaManager ) throws Exception
115 {
116 this.registries = schemaManager.getRegistries();
117 this.schemaManager = schemaManager;
118 disabledAT = registries.getAttributeTypeRegistry().lookup( MetaSchemaConstants.M_DISABLED_AT );
119 factory = new SchemaEntityFactory();
120 cnAT = registries.getAttributeTypeRegistry().lookup( SchemaConstants.CN_AT );
121 dependenciesAT = registries.getAttributeTypeRegistry()
122 .lookup( MetaSchemaConstants.M_DEPENDENCIES_AT );
123 modifiersNameAT = registries.getAttributeTypeRegistry().lookup( SchemaConstants.MODIFIERS_NAME_AT );
124 modifyTimestampAT = registries.getAttributeTypeRegistry().lookup( SchemaConstants.MODIFY_TIMESTAMP_AT );
125
126 ouSchemaDN = new DN( SchemaConstants.OU_SCHEMA );
127 ouSchemaDN.normalize( registries.getAttributeTypeRegistry().getNormalizerMapping() );
128 }
129
130
131 /**
132 * The only modification done on a schema element is on the m-disabled
133 * attributeType
134 *
135 * Depending in the existence of this attribute in the previous entry, we will
136 * have to update the entry or not.
137 */
138 public boolean modify( ModifyOperationContext opContext, ServerEntry targetEntry, boolean cascade ) throws Exception
139 {
140 ServerEntry entry = opContext.getEntry();
141 List<Modification> mods = opContext.getModItems();
142 boolean hasModification = SCHEMA_UNCHANGED;
143
144 // Check if the entry has a m-disabled attribute
145 EntryAttribute disabledInEntry = entry.get( disabledAT );
146 Modification disabledModification = ServerEntryUtils.getModificationItem( mods, disabledAT );
147
148 // The attribute might be present, but that does not mean we will change it.
149 // If it's absent, and if we have it in the previous entry, that mean we want
150 // to enable the schema
151 if ( disabledModification != null )
152 {
153 // We are trying to modify the m-disabled attribute.
154 ModificationOperation modification = disabledModification.getOperation();
155 EntryAttribute attribute = disabledModification.getAttribute();
156
157 hasModification = modifyDisable( opContext, modification, attribute, disabledInEntry );
158 }
159 else if ( disabledInEntry != null )
160 {
161 hasModification = modifyDisable( opContext, ModificationOperation.REMOVE_ATTRIBUTE, null, disabledInEntry );
162 }
163
164
165 return hasModification;
166 }
167
168
169 public void moveAndRename( DN oriChildName, DN newParentName, RDN newRn, boolean deleteOldRn, ServerEntry entry, boolean cascaded ) throws LdapException
170 {
171
172 }
173
174
175 /**
176 * Handles the addition of a metaSchema object to the schema partition.
177 *
178 * @param name the dn of the new metaSchema object
179 * @param entry the attributes of the new metaSchema object
180 */
181 public void add( ServerEntry entry ) throws Exception
182 {
183 DN dn = entry.getDn();
184 DN parentDn = ( DN ) dn.clone();
185 parentDn.remove( parentDn.size() - 1 );
186 parentDn.normalize( registries.getAttributeTypeRegistry().getNormalizerMapping() );
187
188 if ( !parentDn.equals( ouSchemaDN ) )
189 {
190 throw new LdapInvalidDnException( ResultCodeEnum.NAMING_VIOLATION, I18n.err( I18n.ERR_380, ouSchemaDN.getName(),
191 parentDn.getNormName() ) );
192 }
193
194 // check if the new schema is enabled or disabled
195 boolean isEnabled = false;
196 EntryAttribute disabled = entry.get( disabledAT );
197
198 if ( disabled == null )
199 {
200 // If the attribute is absent, then the schema is enabled by default
201 isEnabled = true;
202 }
203 else if ( ! disabled.contains( "TRUE" ) )
204 {
205 isEnabled = true;
206 }
207
208 // check to see that all dependencies are resolved and loaded if this
209 // schema is enabled, otherwise check that the dependency schemas exist
210 checkForDependencies( isEnabled, entry );
211
212 /*
213 * There's a slight problem that may result when adding a metaSchema
214 * object if the addition of the physical entry fails. If the schema
215 * is enabled when added in the condition tested below, that schema
216 * is added to the global registries. We need to add this so subsequent
217 * schema entity additions are loaded into the registries as they are
218 * added to the schema partition. However if the metaSchema object
219 * addition fails then we're left with this schema object looking like
220 * it is enabled in the registries object's schema hash. The effects
221 * of this are unpredictable.
222 *
223 * This whole problem is due to the inability of these handlers to
224 * react to a failed operation. To fix this we would need some way
225 * for these handlers to respond to failed operations and revert their
226 * effects on the registries.
227 *
228 * TODO: might want to add a set of failedOnXXX methods to the adapter
229 * where on failure the schema service calls the schema manager and it
230 * calls the appropriate methods on the respective handler. This way
231 * the schema manager can rollback registry changes when LDAP operations
232 * fail.
233 */
234
235 if ( isEnabled )
236 {
237 Schema schema = factory.getSchema( entry );
238 schemaManager.load( schema );
239 }
240 }
241
242
243 /**
244 * Called to react to the deletion of a metaSchema object. This method
245 * simply removes the schema from the loaded schema map of the global
246 * registries.
247 *
248 * @param name the dn of the metaSchema object being deleted
249 * @param entry the attributes of the metaSchema object
250 */
251 public void delete( ServerEntry entry, boolean cascade ) throws Exception
252 {
253 EntryAttribute cn = entry.get( cnAT );
254 String schemaName = cn.getString();
255
256 // Before allowing a schema object to be deleted we must check
257 // to make sure it's not depended upon by another schema
258 Set<String> dependents = schemaManager.listDependentSchemaNames( schemaName );
259
260 if ( ( dependents != null ) && ! dependents.isEmpty() )
261 {
262 String msg = I18n.err( I18n.ERR_381, dependents );
263 LOG.warn( msg );
264 throw new LdapUnwillingToPerformException(
265 ResultCodeEnum.UNWILLING_TO_PERFORM,
266 msg );
267 }
268
269 // no need to check if schema is enabled or disabled here
270 // if not in the loaded set there will be no negative effect
271 schemaManager.unload( schemaName );
272 }
273
274
275
276 /**
277 * Responds to the rdn (commonName) of the metaSchema object being
278 * changed. Changes all the schema entities associated with the
279 * renamed schema so they now map to a new schema name.
280 *
281 * @param name the dn of the metaSchema object renamed
282 * @param entry the entry of the metaSchema object before the rename
283 * @param newRdn the new commonName of the metaSchema object
284 */
285 public void rename( ServerEntry entry, RDN newRdn, boolean cascade ) throws Exception
286 {
287 String rdnAttribute = newRdn.getUpType();
288 String rdnAttributeOid = registries.getAttributeTypeRegistry().getOidByName( rdnAttribute );
289
290 if ( ! rdnAttributeOid.equals( cnAT.getOid() ) )
291 {
292 throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM,
293 I18n.err( I18n.ERR_382, rdnAttribute ) );
294 }
295
296 /*
297 * This operation has to do the following:
298 *
299 * [1] check and make sure there are no dependent schemas on the
300 * one being renamed - if so an exception should result
301 *
302 * [2] make non-schema object registries modify the mapping
303 * for their entities: non-schema object registries contain
304 * objects that are not SchemaObjects and hence do not carry
305 * their schema within the object as a property
306 *
307 * [3] make schema object registries do the same but the way
308 * they do them will be different since these objects will
309 * need to be replaced or will require a setter for the
310 * schema name
311 */
312
313 // step [1]
314 /*
315 String schemaName = getSchemaName( entry.getDn() );
316 Set<String> dependents = schemaManager.listDependentSchemaNames( schemaName );
317 if ( ! dependents.isEmpty() )
318 {
319 throw new LdapUnwillingToPerformException(
320 "Cannot allow a rename on " + schemaName + " schema while it has depentents.",
321 ResultCodeEnum.UNWILLING_TO_PERFORM );
322 }
323
324 // check if the new schema is enabled or disabled
325 boolean isEnabled = false;
326 EntryAttribute disabled = entry.get( disabledAT );
327
328 if ( disabled == null )
329 {
330 isEnabled = true;
331 }
332 else if ( ! disabled.get().equals( "TRUE" ) )
333 {
334 isEnabled = true;
335 }
336
337 if ( ! isEnabled )
338 {
339 return;
340 }
341
342 // do steps 2 and 3 if the schema has been enabled and is loaded
343
344 // step [2]
345 String newSchemaName = ( String ) newRdn.getUpValue();
346 registries.getComparatorRegistry().renameSchema( schemaName, newSchemaName );
347 registries.getNormalizerRegistry().renameSchema( schemaName, newSchemaName );
348 registries.getSyntaxCheckerRegistry().renameSchema( schemaName, newSchemaName );
349
350 // step [3]
351 renameSchema( registries.getAttributeTypeRegistry(), schemaName, newSchemaName );
352 renameSchema( registries.getDitContentRuleRegistry(), schemaName, newSchemaName );
353 renameSchema( registries.getDitStructureRuleRegistry(), schemaName, newSchemaName );
354 renameSchema( registries.getMatchingRuleRegistry(), schemaName, newSchemaName );
355 renameSchema( registries.getMatchingRuleUseRegistry(), schemaName, newSchemaName );
356 renameSchema( registries.getNameFormRegistry(), schemaName, newSchemaName );
357 renameSchema( registries.getObjectClassRegistry(), schemaName, newSchemaName );
358 renameSchema( registries.getLdapSyntaxRegistry(), schemaName, newSchemaName );
359 */
360 }
361
362
363 /**
364 * Moves are not allowed for metaSchema objects so this always throws an
365 * UNWILLING_TO_PERFORM LdapException.
366 */
367 public void moveAndRename( DN oriChildName, DN newParentName, String newRn, boolean deleteOldRn,
368 ServerEntry entry, boolean cascade ) throws LdapUnwillingToPerformException
369 {
370 throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM,
371 I18n.err( I18n.ERR_383 ) );
372 }
373
374
375 /**
376 * Moves are not allowed for metaSchema objects so this always throws an
377 * UNWILLING_TO_PERFORM LdapException.
378 */
379 public void move( DN oriChildName, DN newParentName,
380 ServerEntry entry, boolean cascade ) throws LdapUnwillingToPerformException
381 {
382 throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM,
383 I18n.err( I18n.ERR_383 ) );
384 }
385
386
387 // -----------------------------------------------------------------------
388 // private utility methods
389 // -----------------------------------------------------------------------
390
391
392 /**
393 * Modify the Disable flag (the flag can be set to true or false).
394 *
395 * We can ADD, REMOVE or MODIFY this flag. The following matrix expose what will be the consequences
396 * of this operation, depending on the current state
397 *
398 * <pre>
399 * +-------------------+--------------------+--------------------+
400 * op/state | TRUE | FALSE | ABSENT |
401 * +-------+-------+----------------------------------------+--------------------+
402 * | ADD | TRUE | do nothing | do nothing | disable the schema |
403 * | +-------+-------------------+--------------------+--------------------+
404 * | | FALSE | do nothing | do nothing | do nothing |
405 * +-------+-------+-------------------+--------------------+--------------------+
406 * |REMOVE | N/A | enable the schema | do nothing | do nothing |
407 * +-------+-------+-------------------+--------------------+--------------------+
408 * |MODIFY | TRUE | do nothing | disable the schema | disable the schema |
409 * | +-------+-------------------+--------------------+--------------------+
410 * | | FALSE | enable the schema | do nothing | do nothing |
411 * +-------+-------+-------------------+--------------------+--------------------+
412 * </pre>
413 */
414 private boolean modifyDisable( ModifyOperationContext opContext, ModificationOperation modOp,
415 EntryAttribute disabledInMods, EntryAttribute disabledInEntry ) throws Exception
416 {
417 DN name = opContext.getDn();
418
419 switch ( modOp )
420 {
421 /*
422 * If the user is adding a new m-disabled attribute to an enabled schema,
423 * we check that the value is "TRUE" and disable that schema if so.
424 */
425 case ADD_ATTRIBUTE :
426 if ( disabledInEntry == null )
427 {
428 if ( "TRUE".equalsIgnoreCase( disabledInMods.getString() ) )
429 {
430 return disableSchema( opContext.getSession(), getSchemaName( name ) );
431 }
432 }
433
434 break;
435
436 /*
437 * If the user is removing the m-disabled attribute we check if the schema is currently
438 * disabled. If so we enable the schema.
439 */
440 case REMOVE_ATTRIBUTE :
441 if ( ( disabledInEntry != null ) && ( "TRUE".equalsIgnoreCase( disabledInEntry.getString() ) ) )
442 {
443 return enableSchema( getSchemaName( name ) );
444 }
445
446 break;
447
448 /*
449 * If the user is replacing the m-disabled attribute we check if the schema is
450 * currently disabled and enable it if the new state has it as enabled. If the
451 * schema is not disabled we disable it if the mods set m-disabled to true.
452 */
453 case REPLACE_ATTRIBUTE :
454
455 boolean isCurrentlyDisabled = false;
456
457 if ( disabledInEntry != null )
458 {
459 isCurrentlyDisabled = "TRUE".equalsIgnoreCase( disabledInEntry.getString() );
460 }
461
462 boolean isNewStateDisabled = false;
463
464 if ( disabledInMods != null )
465 {
466 Value<?> val = disabledInMods.get();
467
468 if ( val == null )
469 {
470 isNewStateDisabled = false;
471 }
472 else
473 {
474 isNewStateDisabled = "TRUE".equalsIgnoreCase( val.getString() );
475 }
476 }
477
478 if ( isCurrentlyDisabled && !isNewStateDisabled )
479 {
480 return enableSchema( getSchemaName( name ) );
481 }
482
483 if ( !isCurrentlyDisabled && isNewStateDisabled )
484 {
485 return disableSchema( opContext.getSession(), getSchemaName( name ) );
486 }
487
488 break;
489
490 default:
491 throw new IllegalArgumentException( I18n.err( I18n.ERR_384, modOp ) );
492 }
493
494 return SCHEMA_UNCHANGED;
495 }
496
497
498 private String getSchemaName( DN schema )
499 {
500 return ( String ) schema.getRdn().getNormValue();
501 }
502
503
504 /**
505 * Build the DN to access a schemaObject path for a specific schema
506 */
507 private DN buildDn( SchemaObjectType schemaObjectType, String schemaName ) throws LdapInvalidDnException
508 {
509
510 DN path = new DN(
511 SchemaConstants.OU_SCHEMA,
512 "cn=" + schemaName,
513 schemaObjectType.getRdn()
514 );
515
516 return path;
517 }
518
519
520 /**
521 * Disable a schema and update all of its schemaObject
522 */
523 private void disable( SchemaObject schemaObject, CoreSession session, Registries registries )
524 throws Exception
525 {
526 Schema schema = registries.getLoadedSchema( schemaObject.getSchemaName() );
527 List<Modification> modifications = new ArrayList<Modification>();
528
529 // The m-disabled AT
530 EntryAttribute disabledAttr = new DefaultServerAttribute( disabledAT, "FALSE" );
531 Modification disabledMod = new ServerModification( ModificationOperation.REPLACE_ATTRIBUTE, disabledAttr );
532
533 modifications.add( disabledMod );
534
535 // The modifiersName AT
536 EntryAttribute modifiersNameAttr =
537 new DefaultServerAttribute( modifiersNameAT, session.getEffectivePrincipal().getName() );
538 Modification modifiersNameMod = new ServerModification( ModificationOperation.REPLACE_ATTRIBUTE, modifiersNameAttr );
539
540 modifications.add( modifiersNameMod );
541
542 // The modifyTimestamp AT
543 EntryAttribute modifyTimestampAttr =
544 new DefaultServerAttribute( modifyTimestampAT, DateUtils.getGeneralizedTime() );
545 Modification modifyTimestampMod = new ServerModification( ModificationOperation.REPLACE_ATTRIBUTE, modifyTimestampAttr );
546
547 modifications.add( modifyTimestampMod );
548
549 // Call the modify operation
550 DN dn = buildDn( schemaObject.getObjectType(), schemaObject.getName() );
551
552 ModifyOperationContext modifyContext = new ModifyOperationContext( session, dn, modifications );
553 modifyContext.setByPassed( ByPassConstants.BYPASS_ALL_COLLECTION );
554
555 OperationManager operationManager =
556 session.getDirectoryService().getOperationManager();
557
558 operationManager.modify( modifyContext );
559
560 // Now iterate on all the schemaObject under this schema
561 for ( SchemaObjectWrapper schemaObjectWrapper : schema.getContent() )
562 {
563
564 }
565 }
566
567 private boolean disableSchema( CoreSession session, String schemaName ) throws Exception
568 {
569 Schema schema = registries.getLoadedSchema( schemaName );
570
571 if ( schema == null )
572 {
573 // This is not possible. We can't enable a schema which is not loaded.
574 String msg = I18n.err( I18n.ERR_85, schemaName );
575 LOG.error( msg );
576 throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM, msg );
577 }
578
579 return schemaManager.disable( schemaName );
580
581 /*
582 // First check that the schema is not already disabled
583 Map<String, Schema> schemas = registries.getLoadedSchemas();
584
585 Schema schema = schemas.get( schemaName );
586
587 if ( ( schema == null ) || schema.isDisabled() )
588 {
589 // The schema is disabled, do nothing
590 return SCHEMA_UNCHANGED;
591 }
592
593 Set<String> dependents = schemaManager.listEnabledDependentSchemaNames( schemaName );
594
595 if ( ! dependents.isEmpty() )
596 {
597 throw new LdapUnwillingToPerformException(
598 "Cannot disable schema with enabled dependents: " + dependents,
599 ResultCodeEnum.UNWILLING_TO_PERFORM );
600 }
601
602 schema.disable();
603
604 // Use brute force right now : iterate through all the schemaObjects
605 // searching for those associated with the disabled schema
606 disableAT( session, schemaName );
607
608 Set<SchemaObjectWrapper> content = registries.getLoadedSchema( schemaName ).getContent();
609
610 for ( SchemaObjectWrapper schemaWrapper : content )
611 {
612 SchemaObject schemaObject = schemaWrapper.get();
613
614 System.out.println( "Disabling " + schemaObject.getName() );
615 }
616
617 return SCHEMA_MODIFIED;
618 */
619 }
620
621
622 private void disableAT( CoreSession session, String schemaName )
623 {
624 AttributeTypeRegistry atRegistry = registries.getAttributeTypeRegistry();
625
626 for ( AttributeType attributeType : atRegistry )
627 {
628 if ( schemaName.equalsIgnoreCase( attributeType.getSchemaName() ) )
629 {
630 if ( attributeType.isDisabled() )
631 {
632 continue;
633 }
634
635 EntryAttribute disable = new DefaultServerAttribute( disabledAT, "TRUE" );
636 Modification modification =
637 new ServerModification( ModificationOperation.REPLACE_ATTRIBUTE, disable );
638
639 //session.modify( dn, mods, ignoreReferral, log )
640 }
641 }
642 }
643
644
645 /**
646 * Enabling a schema consist on switching all of its schema element to enable.
647 * We have to do it on a temporary registries.
648 */
649 private boolean enableSchema( String schemaName ) throws Exception
650 {
651 Schema schema = registries.getLoadedSchema( schemaName );
652
653 if ( schema == null )
654 {
655 // We have to load the schema before enabling it.
656 schemaManager.loadDisabled( schemaName );
657 }
658
659 return schemaManager.enable( schemaName );
660 }
661
662
663 /**
664 * Checks to make sure the dependencies either exist for disabled metaSchemas,
665 * or exist and are loaded (enabled) for enabled metaSchemas.
666 *
667 * @param isEnabled whether or not the new metaSchema is enabled
668 * @param entry the Attributes for the new metaSchema object
669 * @throws NamingException if the dependencies do not resolve or are not
670 * loaded (enabled)
671 */
672 private void checkForDependencies( boolean isEnabled, ServerEntry entry ) throws Exception
673 {
674 EntryAttribute dependencies = entry.get( this.dependenciesAT );
675
676 if ( dependencies == null )
677 {
678 return;
679 }
680
681 if ( isEnabled )
682 {
683 // check to make sure all the dependencies are also enabled
684 Map<String,Schema> loaded = registries.getLoadedSchemas();
685
686 for ( Value<?> value:dependencies )
687 {
688 String dependency = value.getString();
689
690 if ( ! loaded.containsKey( dependency ) )
691 {
692 throw new LdapUnwillingToPerformException(
693 ResultCodeEnum.UNWILLING_TO_PERFORM, "Unwilling to perform operation on enabled schema with disabled or missing dependencies: "
694 + dependency );
695 }
696 }
697 }
698 else
699 {
700 for ( Value<?> value:dependencies )
701 {
702 String dependency = value.getString();
703
704 if ( schemaManager.getLoadedSchema( StringTools.toLowerCase( dependency ) ) == null )
705 {
706 throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM,
707 I18n.err( I18n.ERR_385, dependency ) );
708 }
709 }
710 }
711 }
712
713
714 /**
715 * Used to iterate through SchemaObjects in a DefaultSchemaObjectRegistry and rename
716 * their schema property to a new schema name.
717 *
718 * @param registry the registry whose objects are changed
719 * @param originalSchemaName the original schema name
720 * @param newSchemaName the new schema name
721 */
722 private void renameSchema( DefaultSchemaObjectRegistry<? extends SchemaObject> registry, String originalSchemaName, String newSchemaName )
723 {
724 Iterator<? extends SchemaObject> list = registry.iterator();
725 while ( list.hasNext() )
726 {
727 SchemaObject obj = list.next();
728 if ( obj.getSchemaName().equalsIgnoreCase( originalSchemaName ) )
729 {
730 obj.setSchemaName( newSchemaName );
731 }
732 }
733 }
734 }