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 }