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 */ 020package org.apache.directory.api.ldap.schema.manager.impl; 021 022 023import java.io.IOException; 024import java.util.ArrayList; 025import java.util.Collection; 026import java.util.HashMap; 027import java.util.HashSet; 028import java.util.List; 029import java.util.Map; 030import java.util.Set; 031 032import org.apache.directory.api.i18n.I18n; 033import org.apache.directory.api.ldap.model.constants.MetaSchemaConstants; 034import org.apache.directory.api.ldap.model.entry.Entry; 035import org.apache.directory.api.ldap.model.exception.LdapException; 036import org.apache.directory.api.ldap.model.exception.LdapOtherException; 037import org.apache.directory.api.ldap.model.exception.LdapProtocolErrorException; 038import org.apache.directory.api.ldap.model.exception.LdapSchemaException; 039import org.apache.directory.api.ldap.model.exception.LdapSchemaExceptionCodes; 040import org.apache.directory.api.ldap.model.exception.LdapUnwillingToPerformException; 041import org.apache.directory.api.ldap.model.message.ResultCodeEnum; 042import org.apache.directory.api.ldap.model.name.Dn; 043import org.apache.directory.api.ldap.model.schema.AttributeType; 044import org.apache.directory.api.ldap.model.schema.LdapComparator; 045import org.apache.directory.api.ldap.model.schema.LdapSyntax; 046import org.apache.directory.api.ldap.model.schema.LoadableSchemaObject; 047import org.apache.directory.api.ldap.model.schema.LoggingSchemaErrorHandler; 048import org.apache.directory.api.ldap.model.schema.MatchingRule; 049import org.apache.directory.api.ldap.model.schema.Normalizer; 050import org.apache.directory.api.ldap.model.schema.ObjectClass; 051import org.apache.directory.api.ldap.model.schema.SchemaErrorHandler; 052import org.apache.directory.api.ldap.model.schema.SchemaManager; 053import org.apache.directory.api.ldap.model.schema.SchemaObject; 054import org.apache.directory.api.ldap.model.schema.SchemaObjectWrapper; 055import org.apache.directory.api.ldap.model.schema.SchemaUtils; 056import org.apache.directory.api.ldap.model.schema.SyntaxChecker; 057import org.apache.directory.api.ldap.model.schema.normalizers.OidNormalizer; 058import org.apache.directory.api.ldap.model.schema.registries.AttributeTypeRegistry; 059import org.apache.directory.api.ldap.model.schema.registries.ComparatorRegistry; 060import org.apache.directory.api.ldap.model.schema.registries.DitContentRuleRegistry; 061import org.apache.directory.api.ldap.model.schema.registries.DitStructureRuleRegistry; 062import org.apache.directory.api.ldap.model.schema.registries.ImmutableAttributeTypeRegistry; 063import org.apache.directory.api.ldap.model.schema.registries.ImmutableComparatorRegistry; 064import org.apache.directory.api.ldap.model.schema.registries.ImmutableDitContentRuleRegistry; 065import org.apache.directory.api.ldap.model.schema.registries.ImmutableDitStructureRuleRegistry; 066import org.apache.directory.api.ldap.model.schema.registries.ImmutableLdapSyntaxRegistry; 067import org.apache.directory.api.ldap.model.schema.registries.ImmutableMatchingRuleRegistry; 068import org.apache.directory.api.ldap.model.schema.registries.ImmutableMatchingRuleUseRegistry; 069import org.apache.directory.api.ldap.model.schema.registries.ImmutableNameFormRegistry; 070import org.apache.directory.api.ldap.model.schema.registries.ImmutableNormalizerRegistry; 071import org.apache.directory.api.ldap.model.schema.registries.ImmutableObjectClassRegistry; 072import org.apache.directory.api.ldap.model.schema.registries.ImmutableSyntaxCheckerRegistry; 073import org.apache.directory.api.ldap.model.schema.registries.LdapSyntaxRegistry; 074import org.apache.directory.api.ldap.model.schema.registries.LowerCaseKeyMap; 075import org.apache.directory.api.ldap.model.schema.registries.MatchingRuleRegistry; 076import org.apache.directory.api.ldap.model.schema.registries.MatchingRuleUseRegistry; 077import org.apache.directory.api.ldap.model.schema.registries.NameFormRegistry; 078import org.apache.directory.api.ldap.model.schema.registries.NormalizerRegistry; 079import org.apache.directory.api.ldap.model.schema.registries.ObjectClassRegistry; 080import org.apache.directory.api.ldap.model.schema.registries.OidRegistry; 081import org.apache.directory.api.ldap.model.schema.registries.Registries; 082import org.apache.directory.api.ldap.model.schema.registries.Schema; 083import org.apache.directory.api.ldap.model.schema.registries.SchemaLoader; 084import org.apache.directory.api.ldap.model.schema.registries.SyntaxCheckerRegistry; 085import org.apache.directory.api.ldap.schema.loader.EntityFactory; 086import org.apache.directory.api.ldap.schema.loader.JarLdifSchemaLoader; 087import org.apache.directory.api.ldap.schema.loader.SchemaEntityFactory; 088import org.apache.directory.api.util.Strings; 089import org.slf4j.Logger; 090import org.slf4j.LoggerFactory; 091 092 093/** 094 * The SchemaManager class : it handles all the schema operations (addition, removal, 095 * modification). 096 * 097 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 098 */ 099public class DefaultSchemaManager implements SchemaManager 100{ 101 /** static class logger */ 102 private static final Logger LOG = LoggerFactory.getLogger( DefaultSchemaManager.class ); 103 104 /** The NamingContext this SchemaManager is associated with */ 105 private Dn namingContext; 106 107 /** The global registries for this namingContext */ 108 private volatile Registries registries; 109 110 /** the factory that generates respective SchemaObjects from LDIF entries */ 111 private final EntityFactory factory; 112 113 /** A Map containing all the schema being dependent from a schema */ 114 private Map<String, Set<String>> schemaDependencies = new HashMap<>(); 115 116 /** 117 * A map of all available schema names to schema objects. This map is 118 * populated when this class is created with all the schemas present in 119 * the LDIF based schema repository. 120 */ 121 private Map<String, Schema> schemaMap = new LowerCaseKeyMap(); 122 123 /** A flag indicating that the SchemaManager is relaxed or not */ 124 private boolean isRelaxed = STRICT; 125 126 /** 127 * Class that handles all the error that may occur during schema processing. 128 */ 129 private SchemaErrorHandler errorHandler; 130 131 /** 132 * Creates a new instance of DefaultSchemaManager with LDIF based SchemaLoader, 133 * Strict schema validation 134 */ 135 public DefaultSchemaManager() 136 { 137 this( STRICT, jarLdifSchemaLoader().getAllSchemas() ); 138 139 try 140 { 141 loadAllEnabled(); 142 } 143 catch ( LdapException e ) 144 { 145 LOG.error( I18n.err( I18n.ERR_16077_SCHEMA_MANAGER_CANT_BE_LOADED, e.getMessage() ) ); 146 throw new RuntimeException( e.getMessage() ); 147 } 148 } 149 150 /* 151 Static helper factory Create LDIF based SchemaLoader 152 needed to handle checked exceptions 153 */ 154 private static SchemaLoader jarLdifSchemaLoader() 155 { 156 try 157 { 158 return new JarLdifSchemaLoader(); 159 } 160 catch ( LdapException | IOException e ) 161 { 162 LOG.error( I18n.err( I18n.ERR_16080_SCHEMA_LOADER_CANT_BE_CREATED, e.getMessage() ) ); 163 throw new RuntimeException( e.getMessage() ); 164 } 165 } 166 167 168 169 /** 170 * Creates a new instance of DefaultSchemaManager with the default schema schemaLoader 171 * Strict schema validation 172 * 173 * @param schemas The list of schema to load 174 */ 175 public DefaultSchemaManager( Collection<Schema> schemas ) 176 { 177 this( STRICT, schemas ); 178 } 179 180 181 /** 182 * Creates a new instance of DefaultSchemaManager with the given schemaLoader 183 * 184 * Schema validation strictness (i.e. relaxed/strict) controlled by the given schemaLoader 185 * 186 * @param schemaLoader The schemaLoader containing the schemas to load 187 */ 188 public DefaultSchemaManager( SchemaLoader schemaLoader ) 189 { 190 this( schemaLoader.isRelaxed(), schemaLoader.getAllSchemas() ); 191 } 192 193 194 /** 195 * Creates a new instance of DefaultSchemaManager with the default schema schemaLoader 196 * 197 * @param relaxed If the schema manager should be relaxed or not 198 * @param schemas The list of schema to load 199 */ 200 public DefaultSchemaManager( boolean relaxed, Collection<Schema> schemas ) 201 { 202 // Default to the the root (one schemaManager for all the entries 203 namingContext = Dn.ROOT_DSE; 204 205 for ( Schema schema : schemas ) 206 { 207 schemaMap.put( schema.getSchemaName(), schema ); 208 } 209 210 registries = new Registries(); 211 factory = new SchemaEntityFactory(); 212 isRelaxed = relaxed; 213 setErrorHandler( new LoggingSchemaErrorHandler() ); 214 } 215 216 217 //----------------------------------------------------------------------- 218 // Helper methods 219 //----------------------------------------------------------------------- 220 /** 221 * Clone the registries before doing any modification on it. Relax it 222 * too so that we can update it. 223 * 224 * @return The cloned Registries 225 * @throws LdapException If the Registries cannot be cloned 226 */ 227 private Registries cloneRegistries() throws LdapException 228 { 229 try 230 { 231 // Relax the controls at first 232 233 // Clone the Registries 234 Registries clonedRegistries = registries.clone(); 235 236 // And update references. We may have errors, that may be fixed 237 // by the new loaded schemas. 238 clonedRegistries.checkRefInteg(); 239 240 // Now, relax the cloned Registries if there is no error 241 clonedRegistries.setRelaxed(); 242 243 return clonedRegistries; 244 } 245 catch ( CloneNotSupportedException cnse ) 246 { 247 throw new LdapOtherException( cnse.getMessage(), cnse ); 248 } 249 } 250 251 252 /** 253 * Transform a String[] array of schema to a Schema[] 254 * 255 * @param schemas The Schema names to process 256 * @return an array of Schema instance 257 * @throws LdapException If one of the Schema cannot be found 258 */ 259 private Schema[] toArray( String... schemas ) throws LdapException 260 { 261 Schema[] schemaArray = new Schema[schemas.length]; 262 int n = 0; 263 264 for ( String schemaName : schemas ) 265 { 266 Schema schema = schemaMap.get( schemaName ); 267 268 if ( schema != null ) 269 { 270 schemaArray[n++] = schema; 271 } 272 else 273 { 274 throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM, I18n.err( 275 I18n.ERR_16078_CANNOT_LOAD_UNKNOWN_SCHEMA, schemaName ) ); 276 } 277 } 278 279 return schemaArray; 280 } 281 282 283 private void addSchemaObjects( Schema schema, Registries registries ) throws LdapException 284 { 285 // Create a content container for this schema 286 registries.addSchema( schema.getSchemaName() ); 287 schemaMap.put( schema.getSchemaName(), schema ); 288 289 // And inject any existing SchemaObject into the registries 290 try 291 { 292 addComparators( schema, registries ); 293 addNormalizers( schema, registries ); 294 addSyntaxCheckers( schema, registries ); 295 addSyntaxes( schema, registries ); 296 addMatchingRules( schema, registries ); 297 addAttributeTypes( schema, registries ); 298 addObjectClasses( schema, registries ); 299 //addMatchingRuleUses( schema, registries ); 300 //addDitContentRules( schema, registries ); 301 //addNameForms( schema, registries ); 302 //addDitStructureRules( schema, registries ); 303 } 304 catch ( IOException ioe ) 305 { 306 throw new LdapOtherException( ioe.getMessage(), ioe ); 307 } 308 } 309 310 311 /** 312 * Delete all the schemaObjects for a given schema from the registries 313 * 314 * @param schema The schema from which we want teh SchemaObjects to be deleted 315 * @param registries The Registries to process 316 * @throws LdapException If the SchemaObjects cannot be deleted 317 */ 318 private void deleteSchemaObjects( Schema schema, Registries registries ) throws LdapException 319 { 320 Map<String, Set<SchemaObjectWrapper>> schemaObjects = registries.getObjectBySchemaName(); 321 Set<SchemaObjectWrapper> content = schemaObjects.get( Strings.toLowerCaseAscii( schema.getSchemaName() ) ); 322 323 List<SchemaObject> toBeDeleted = new ArrayList<>(); 324 325 if ( content != null ) 326 { 327 // Build an intermediate list to avoid concurrent modifications 328 for ( SchemaObjectWrapper schemaObjectWrapper : content ) 329 { 330 toBeDeleted.add( schemaObjectWrapper.get() ); 331 } 332 333 for ( SchemaObject schemaObject : toBeDeleted ) 334 { 335 registries.delete( schemaObject ); 336 } 337 } 338 } 339 340 341 //----------------------------------------------------------------------- 342 // API methods 343 //----------------------------------------------------------------------- 344 /** 345 * {@inheritDoc} 346 */ 347 @Override 348 public boolean disable( Schema... schemas ) throws LdapException 349 { 350 boolean disabled = false; 351 352 // Reset the error handler 353 errorHandler.reset(); 354 355 // Work on a cloned and relaxed registries 356 Registries clonedRegistries = cloneRegistries(); 357 clonedRegistries.setRelaxed(); 358 359 for ( Schema schema : schemas ) 360 { 361 unload( clonedRegistries, schema ); 362 } 363 364 // Unload is producing some errors, not sure why. But they 365 // seem not relevant to disable functionality. 366 errorHandler.reset(); 367 368 // Build the cross references 369 clonedRegistries.buildReferences(); 370 371 // Destroy the clonedRegistry 372 clonedRegistries.clear(); 373 374 if ( !errorHandler.wasError() ) 375 { 376 // Ok no errors. Check the registries now 377 clonedRegistries.checkRefInteg(); 378 379 if ( !errorHandler.wasError() ) 380 { 381 // We are golden : let's apply the schemas in the real registries 382 for ( Schema schema : schemas ) 383 { 384 unload( registries, schema ); 385 schema.disable(); 386 } 387 388 // Unload is producing some errors, not sure why. But they 389 // seem not relevant to disable functionality. 390 errorHandler.reset(); 391 392 // Build the cross references 393 registries.buildReferences(); 394 registries.setStrict(); 395 396 disabled = true; 397 } 398 } 399 400 // clear the cloned registries 401 clonedRegistries.clear(); 402 403 return disabled; 404 } 405 406 407 /** 408 * {@inheritDoc} 409 */ 410 @Override 411 public boolean disable( String... schemaNames ) throws LdapException 412 { 413 Schema[] schemas = toArray( schemaNames ); 414 415 return disable( schemas ); 416 } 417 418 419 /** 420 * {@inheritDoc} 421 */ 422 @Override 423 public boolean disabledRelaxed( Schema... schemas ) 424 { 425 return false; 426 } 427 428 429 /** 430 * {@inheritDoc} 431 */ 432 @Override 433 public boolean disabledRelaxed( String... schemas ) 434 { 435 return false; 436 } 437 438 439 /** 440 * {@inheritDoc} 441 */ 442 @Override 443 public List<Schema> getDisabled() 444 { 445 List<Schema> disabled = new ArrayList<>(); 446 447 for ( Schema schema : registries.getLoadedSchemas().values() ) 448 { 449 if ( schema.isDisabled() ) 450 { 451 disabled.add( schema ); 452 } 453 } 454 455 return disabled; 456 } 457 458 459 /** 460 * {@inheritDoc} 461 */ 462 @Override 463 public boolean enable( Schema... schemas ) throws LdapException 464 { 465 boolean enabled = false; 466 467 // Reset the errors if not null 468 errorHandler.reset(); 469 470 // Work on a cloned and relaxed registries 471 Registries clonedRegistries = cloneRegistries(); 472 clonedRegistries.setRelaxed(); 473 474 Set<Schema> disabledSchemas = new HashSet<>(); 475 476 for ( Schema schema : schemas ) 477 { 478 if ( schema.getDependencies() != null ) 479 { 480 for ( String dependency : schema.getDependencies() ) 481 { 482 Schema dependencySchema = schemaMap.get( dependency ); 483 484 if ( dependencySchema.isDisabled() ) 485 { 486 disabledSchemas.add( dependencySchema ); 487 } 488 } 489 } 490 491 schema.enable(); 492 load( clonedRegistries, schema ); 493 } 494 495 // Revert back the disabled schema to disabled 496 for ( Schema disabledSchema : disabledSchemas ) 497 { 498 if ( disabledSchema.isEnabled() ) 499 { 500 disabledSchema.disable(); 501 } 502 } 503 504 // Build the cross references 505 clonedRegistries.buildReferences(); 506 507 // Destroy the clonedRegistry 508 clonedRegistries.clear(); 509 510 if ( !errorHandler.wasError() ) 511 { 512 // Ok no errors. Check the registries now 513 clonedRegistries.checkRefInteg(); 514 515 if ( !errorHandler.wasError() ) 516 { 517 // We are golden : let's apply the schemas in the real registries 518 for ( Schema schema : schemas ) 519 { 520 schema.enable(); 521 load( registries, schema ); 522 } 523 524 // Build the cross references 525 registries.buildReferences(); 526 registries.setStrict(); 527 528 enabled = true; 529 } 530 } 531 532 // clear the cloned registries 533 clonedRegistries.clear(); 534 535 return enabled; 536 } 537 538 539 /** 540 * {@inheritDoc} 541 */ 542 @Override 543 public boolean enable( String... schemaNames ) throws LdapException 544 { 545 Schema[] schemas = toArray( schemaNames ); 546 return enable( schemas ); 547 } 548 549 550 /** 551 * {@inheritDoc} 552 */ 553 @Override 554 public boolean enableRelaxed( Schema... schemas ) 555 { 556 return false; 557 } 558 559 560 /** 561 * {@inheritDoc} 562 */ 563 @Override 564 public boolean enableRelaxed( String... schemas ) 565 { 566 return false; 567 } 568 569 570 /** 571 * {@inheritDoc} 572 */ 573 @Override 574 public List<Schema> getEnabled() 575 { 576 List<Schema> enabled = new ArrayList<>(); 577 578 for ( Schema schema : registries.getLoadedSchemas().values() ) 579 { 580 if ( schema.isEnabled() ) 581 { 582 enabled.add( schema ); 583 } 584 } 585 586 return enabled; 587 } 588 589 590 /** 591 * {@inheritDoc} 592 */ 593 @Override 594 public List<Schema> getAllSchemas() 595 { 596 List<Schema> schemas = new ArrayList<>(); 597 598 for ( Schema schema : schemaMap.values() ) 599 { 600 if ( schema.isEnabled() ) 601 { 602 schemas.add( schema ); 603 } 604 } 605 606 return schemas; 607 } 608 609 610 /** 611 * {@inheritDoc} 612 */ 613 @Override 614 public List<Throwable> getErrors() 615 { 616 return errorHandler.getErrors(); 617 } 618 619 620 /** 621 * {@inheritDoc} 622 */ 623 @Override 624 public Registries getRegistries() 625 { 626 return registries; 627 } 628 629 630 /** 631 * Currently not implemented. 632 * 633 * @return Always FALSE 634 */ 635 public boolean isDisabledAccepted() 636 { 637 return false; 638 } 639 640 641 /** 642 * {@inheritDoc} 643 */ 644 @Override 645 public boolean load( Schema... schemas ) throws LdapException 646 { 647 if ( schemas.length == 0 ) 648 { 649 return true; 650 } 651 652 boolean loaded = false; 653 654 // Reset the errors if not null 655 errorHandler.reset(); 656 657 // Work on a cloned and relaxed registries 658 Registries clonedRegistries = cloneRegistries(); 659 clonedRegistries.setRelaxed(); 660 661 // Load the schemas 662 for ( Schema schema : schemas ) 663 { 664 boolean singleSchemaLoaded = load( clonedRegistries, schema ); 665 666 // return false if the schema was not loaded in the first place 667 if ( !singleSchemaLoaded ) 668 { 669 return false; 670 } 671 } 672 673 // Build the cross references 674 clonedRegistries.buildReferences(); 675 676 if ( !errorHandler.wasError() ) 677 { 678 // Ok no errors. Check the registries now 679 clonedRegistries.checkRefInteg(); 680 681 if ( !errorHandler.wasError() ) 682 { 683 // We are golden : let's apply the schema in the real registries 684 registries.setRelaxed(); 685 686 // Load the schemas 687 for ( Schema schema : schemas ) 688 { 689 load( registries, schema ); 690 691 // Update the schema dependences if needed 692 if ( schema.getDependencies() != null ) 693 { 694 for ( String dep : schema.getDependencies() ) 695 { 696 Set<String> deps = schemaDependencies.get( dep ); 697 698 if ( deps == null ) 699 { 700 deps = new HashSet<>(); 701 deps.add( schema.getSchemaName() ); 702 } 703 704 // Replace the dependences 705 schemaDependencies.put( dep, deps ); 706 } 707 } 708 709 // add the schema to the SchemaMap 710 schemaMap.put( schema.getSchemaName(), schema ); 711 } 712 713 // Build the cross references 714 registries.buildReferences(); 715 registries.setStrict(); 716 717 loaded = true; 718 } 719 } 720 721 // clear the cloned registries 722 clonedRegistries.clear(); 723 724 return loaded; 725 } 726 727 728 /** 729 * {@inheritDoc} 730 */ 731 @Override 732 public boolean load( String... schemaNames ) throws LdapException 733 { 734 if ( schemaNames.length == 0 ) 735 { 736 return true; 737 } 738 739 Schema[] schemas = toArray( schemaNames ); 740 741 return load( schemas ); 742 } 743 744 745 /** 746 * Load the schema in the registries. We will load everything accordingly to the two flags : 747 * - isRelaxed 748 * - disabledAccepted 749 * 750 * @param registries The Registries to process 751 * @param schema The schema to load in the Registries 752 * @return <tt>true</tt> if the schema has been loaded 753 * @throws LdapException If the schema cannot be loaded 754 */ 755 private boolean load( Registries registries, Schema schema ) throws LdapException 756 { 757 if ( schema == null ) 758 { 759 if ( LOG.isInfoEnabled() ) 760 { 761 LOG.info( I18n.msg( I18n.MSG_16013_SCHEMA_IS_NULL ) ); 762 } 763 764 return false; 765 } 766 767 // First avoid loading twice the same schema 768 if ( registries.isSchemaLoaded( schema.getSchemaName() ) ) 769 { 770 return true; 771 } 772 773 if ( schema.isDisabled() ) 774 { 775 if ( registries.isDisabledAccepted() ) 776 { 777 if ( LOG.isInfoEnabled() ) 778 { 779 LOG.info( I18n.msg( I18n.MSG_16014_LOADING_DISABLED_SCHEMA, schema.getSchemaName(), schema ) ); 780 } 781 782 registries.schemaLoaded( schema ); 783 addSchemaObjects( schema, registries ); 784 } 785 else 786 { 787 return false; 788 } 789 } 790 else 791 { 792 if ( LOG.isInfoEnabled() ) 793 { 794 LOG.info( I18n.msg( I18n.MSG_16015_LOADING_ENABLED_SCHEMA, schema.getSchemaName(), schema ) ); 795 } 796 797 // Check that the dependencies, if any, are correct 798 if ( schema.getDependencies() != null ) 799 { 800 for ( String dependency : schema.getDependencies() ) 801 { 802 Schema dependencySchema = schemaMap.get( dependency ); 803 804 if ( dependencySchema == null ) 805 { 806 // The dependency has not been loaded. 807 String msg = I18n.err( I18n.ERR_16035_CANNOT_LOAD_SCHEMA, schema.getSchemaName() ); 808 809 if ( LOG.isInfoEnabled() ) 810 { 811 LOG.info( msg ); 812 } 813 814 LdapProtocolErrorException error = new LdapProtocolErrorException( msg ); 815 errorHandler.handle( LOG, msg, error ); 816 817 return false; 818 } 819 820 // If the dependency is disabled, then enable it 821 if ( dependencySchema.isDisabled() ) 822 { 823 dependencySchema.enable(); 824 825 if ( !load( registries, dependencySchema ) ) 826 { 827 dependencySchema.disable(); 828 829 return false; 830 } 831 } 832 } 833 } 834 835 registries.schemaLoaded( schema ); 836 addSchemaObjects( schema, registries ); 837 } 838 839 return true; 840 } 841 842 843 /** 844 * Unload the schema from the registries. We will unload everything accordingly to the two flags : 845 * - isRelaxed 846 * - disabledAccepted 847 * 848 * @param registries The Registries to process 849 * @param schema The schema to unload from the Registries 850 * @return <tt>true</tt> if the schema has been unloaded 851 * @throws LdapException If the schema cannot be unloaded 852 */ 853 private boolean unload( Registries registries, Schema schema ) throws LdapException 854 { 855 if ( schema == null ) 856 { 857 if ( LOG.isInfoEnabled() ) 858 { 859 LOG.info( I18n.msg( I18n.MSG_16013_SCHEMA_IS_NULL ) ); 860 } 861 862 return false; 863 } 864 865 // First avoid unloading twice the same schema 866 if ( !registries.isSchemaLoaded( schema.getSchemaName() ) ) 867 { 868 return true; 869 } 870 871 if ( schema.isEnabled() ) 872 { 873 if ( LOG.isInfoEnabled() ) 874 { 875 LOG.info( I18n.msg( I18n.MSG_16016_UNLOADING_SCHEMA, schema.getSchemaName(), schema ) ); 876 } 877 878 deleteSchemaObjects( schema, registries ); 879 registries.schemaUnloaded( schema ); 880 } 881 882 return true; 883 } 884 885 886 /** 887 * Add all the Schema's AttributeTypes 888 * 889 * @param schema The schema in which the AttributeTypes will be added 890 * @param registries The Registries to process 891 * @throws LdapException If the AttributeTypes cannot be added 892 * @throws IOException If the AttributeTypes cannot be loaded 893 */ 894 private void addAttributeTypes( Schema schema, Registries registries ) throws LdapException, IOException 895 { 896 if ( schema.getSchemaLoader() == null ) 897 { 898 return; 899 } 900 901 for ( Entry entry : schema.getSchemaLoader().loadAttributeTypes( schema ) ) 902 { 903 AttributeType attributeType = factory.getAttributeType( this, entry, registries, schema.getSchemaName() ); 904 905 addSchemaObject( registries, attributeType, schema ); 906 } 907 } 908 909 910 /** 911 * Add all the Schema's comparators 912 * 913 * @param schema The schema in which the Comparators will be added 914 * @param registries The Registries to process 915 * @throws LdapException If the Comparators cannot be added 916 * @throws IOException If the Comparators cannot be loaded 917 */ 918 private void addComparators( Schema schema, Registries registries ) throws LdapException, IOException 919 { 920 if ( schema.getSchemaLoader() == null ) 921 { 922 return; 923 } 924 925 for ( Entry entry : schema.getSchemaLoader().loadComparators( schema ) ) 926 { 927 LdapComparator<?> comparator = factory.getLdapComparator( this, entry, registries, schema.getSchemaName() ); 928 929 addSchemaObject( registries, comparator, schema ); 930 } 931 } 932 933 934 /** 935 * Add all the Schema's DitContentRules 936 */ 937 // Not yet implemented, but may be used 938 // @SuppressWarnings("PMD.UnusedFormalParameter") 939 // private void addDitContentRules( Schema schema, Registries registries ) throws LdapException, IOException 940 // { 941 // if ( !schema.getSchemaLoader().loadDitContentRules( schema ).isEmpty() ) 942 // { 943 // throw new NotImplementedException( I18n.err( I18n.ERR_11003 ) ); 944 // } 945 // } 946 947 /** 948 * Add all the Schema's DitStructureRules 949 */ 950 // Not yet implemented, but may be used 951 // @SuppressWarnings("PMD.UnusedFormalParameter") 952 // private void addDitStructureRules( Schema schema, Registries registries ) throws LdapException, IOException 953 // { 954 // if ( !schema.getSchemaLoader().loadDitStructureRules( schema ).isEmpty() ) 955 // { 956 // throw new NotImplementedException( I18n.err( I18n.ERR_11004 ) ); 957 // } 958 // } 959 960 /** 961 * Add all the Schema's MatchingRules 962 * 963 * @param schema The schema in which the MatchingRules will be added 964 * @param registries The Registries to process 965 * @throws LdapException If the MatchingRules cannot be added 966 * @throws IOException If the MatchingRules cannot be loaded 967 */ 968 private void addMatchingRules( Schema schema, Registries registries ) throws LdapException, IOException 969 { 970 if ( schema.getSchemaLoader() == null ) 971 { 972 return; 973 } 974 975 for ( Entry entry : schema.getSchemaLoader().loadMatchingRules( schema ) ) 976 { 977 MatchingRule matchingRule = factory.getMatchingRule( this, entry, registries, schema.getSchemaName() ); 978 979 addSchemaObject( registries, matchingRule, schema ); 980 } 981 } 982 983 984 /** 985 * Add all the Schema's MatchingRuleUses 986 */ 987 // Not yet implemented, but may be used 988 // @SuppressWarnings("PMD.UnusedFormalParameter") 989 // private void addMatchingRuleUses( Schema schema, Registries registries ) throws LdapException, IOException 990 // { 991 // if ( !schema.getSchemaLoader().loadMatchingRuleUses( schema ).isEmpty() ) 992 // { 993 // throw new NotImplementedException( I18n.err( I18n.ERR_11005 ) ); 994 // } 995 // // for ( Entry entry : schema.getSchemaLoader().loadMatchingRuleUses( schema ) ) 996 // // { 997 // // throw new NotImplementedException( I18n.err( I18n.ERR_11005 ) ); 998 // // } 999 // } 1000 1001 /** 1002 * Add all the Schema's NameForms 1003 */ 1004 // Not yet implemented, but may be used 1005 // @SuppressWarnings("PMD.UnusedFormalParameter") 1006 // private void addNameForms( Schema schema, Registries registries ) throws LdapException, IOException 1007 // { 1008 // if ( !schema.getSchemaLoader().loadNameForms( schema ).isEmpty() ) 1009 // { 1010 // throw new NotImplementedException( I18n.err( I18n.ERR_11006 ) ); 1011 // } 1012 // } 1013 1014 /** 1015 * Add all the Schema's Normalizers 1016 * 1017 * @param schema The schema in which the Normalizers will be added 1018 * @param registries The Registries to process 1019 * @throws LdapException If the Normalizers cannot be added 1020 * @throws IOException If the Normalizers cannot be loaded 1021 */ 1022 private void addNormalizers( Schema schema, Registries registries ) throws LdapException, IOException 1023 { 1024 if ( schema.getSchemaLoader() == null ) 1025 { 1026 return; 1027 } 1028 1029 for ( Entry entry : schema.getSchemaLoader().loadNormalizers( schema ) ) 1030 { 1031 Normalizer normalizer = factory.getNormalizer( this, entry, registries, schema.getSchemaName() ); 1032 1033 addSchemaObject( registries, normalizer, schema ); 1034 } 1035 } 1036 1037 1038 /** 1039 * Add all the Schema's ObjectClasses 1040 * 1041 * @param schema The schema in which the ObjectClasses will be added 1042 * @param registries The Registries to process 1043 * @throws LdapException If the ObjectClasses cannot be added 1044 * @throws IOException If the ObjectClasses cannot be loaded 1045 */ 1046 private void addObjectClasses( Schema schema, Registries registries ) throws LdapException, IOException 1047 { 1048 if ( schema.getSchemaLoader() == null ) 1049 { 1050 return; 1051 } 1052 1053 for ( Entry entry : schema.getSchemaLoader().loadObjectClasses( schema ) ) 1054 { 1055 ObjectClass objectClass = factory.getObjectClass( this, entry, registries, schema.getSchemaName() ); 1056 1057 addSchemaObject( registries, objectClass, schema ); 1058 } 1059 } 1060 1061 1062 /** 1063 * Add all the Schema's Syntaxes 1064 * 1065 * @param schema The schema in which the Syntaxes will be added 1066 * @param registries The Registries to process 1067 * @throws LdapException If the Syntaxes cannot be added 1068 * @throws IOException If the Syntaxes cannot be loaded 1069 */ 1070 private void addSyntaxes( Schema schema, Registries registries ) throws LdapException, IOException 1071 { 1072 if ( schema.getSchemaLoader() == null ) 1073 { 1074 return; 1075 } 1076 1077 for ( Entry entry : schema.getSchemaLoader().loadSyntaxes( schema ) ) 1078 { 1079 LdapSyntax syntax = factory.getSyntax( this, entry, registries, schema.getSchemaName() ); 1080 1081 addSchemaObject( registries, syntax, schema ); 1082 } 1083 } 1084 1085 1086 /** 1087 * Register all the Schema's SyntaxCheckers 1088 * 1089 * @param schema The schema in which the SyntaxChecker will be added 1090 * @param registries The Registries to process 1091 * @throws LdapException If the SyntaxChecker cannot be added 1092 * @throws IOException If the SyntaxChecker cannot be loaded 1093 */ 1094 private void addSyntaxCheckers( Schema schema, Registries registries ) throws LdapException, IOException 1095 { 1096 if ( schema.getSchemaLoader() == null ) 1097 { 1098 return; 1099 } 1100 1101 for ( Entry entry : schema.getSchemaLoader().loadSyntaxCheckers( schema ) ) 1102 { 1103 SyntaxChecker syntaxChecker = factory.getSyntaxChecker( this, entry, registries, schema.getSchemaName() ); 1104 1105 addSchemaObject( registries, syntaxChecker, schema ); 1106 } 1107 } 1108 1109 1110 /** 1111 * Add the schemaObject into the registries. 1112 * 1113 * @param registries The Registries 1114 * @param schemaObject The SchemaObject containing the SchemaObject description 1115 * @param schema The associated schema 1116 * @return the created schemaObject instance 1117 * @throws LdapException If the registering failed 1118 */ 1119 private SchemaObject addSchemaObject( Registries registries, SchemaObject schemaObject, Schema schema ) 1120 throws LdapException 1121 { 1122 if ( registries.isRelaxed() ) 1123 { 1124 if ( registries.isDisabledAccepted() || ( schema.isEnabled() && schemaObject.isEnabled() ) ) 1125 { 1126 registries.add( schemaObject, false ); 1127 } 1128 else 1129 { 1130 // What kind of error is this? TODO: better message 1131 errorHandler.handle( LOG, null, new Throwable() ); 1132 } 1133 } 1134 else 1135 { 1136 if ( schema.isEnabled() && schemaObject.isEnabled() ) 1137 { 1138 registries.add( schemaObject, false ); 1139 } 1140 else 1141 { 1142 // What kind of error is this? TODO: better message 1143 errorHandler.handle( LOG, null, new Throwable() ); 1144 } 1145 } 1146 1147 return schemaObject; 1148 } 1149 1150 1151 /** 1152 * {@inheritDoc} 1153 */ 1154 @Override 1155 public boolean loadAllEnabled() throws LdapException 1156 { 1157 Schema[] schemas = new Schema[schemaMap.size()]; 1158 int i = 0; 1159 1160 for ( Schema schema : schemaMap.values() ) 1161 { 1162 if ( schema.isEnabled() ) 1163 { 1164 schemas[i++] = schema; 1165 } 1166 } 1167 1168 Schema[] enabledSchemas = new Schema[i]; 1169 System.arraycopy( schemas, 0, enabledSchemas, 0, i ); 1170 1171 return loadWithDeps( enabledSchemas ); 1172 } 1173 1174 1175 /** 1176 * {@inheritDoc} 1177 */ 1178 @Override 1179 public boolean loadAllEnabledRelaxed() throws LdapException 1180 { 1181 Schema[] enabledSchemas = new Schema[schemaMap.size()]; 1182 int i = 0; 1183 1184 for ( Schema schema : schemaMap.values() ) 1185 { 1186 if ( schema.isEnabled() ) 1187 { 1188 enabledSchemas[i++] = schema; 1189 } 1190 } 1191 1192 return loadWithDepsRelaxed( enabledSchemas ); 1193 } 1194 1195 1196 /** 1197 * {@inheritDoc} 1198 */ 1199 @Override 1200 public boolean loadDisabled( Schema... schemas ) throws LdapException 1201 { 1202 // Work on a cloned and relaxed registries 1203 Registries clonedRegistries = cloneRegistries(); 1204 1205 // Accept the disabled schemas 1206 clonedRegistries.setDisabledAccepted( true ); 1207 1208 // Load the schemas 1209 for ( Schema schema : schemas ) 1210 { 1211 // Enable the Schema object before loading it 1212 schema.enable(); 1213 load( clonedRegistries, schema ); 1214 } 1215 1216 clonedRegistries.clear(); 1217 1218 // Apply the change to the correct registries if no errors 1219 if ( !errorHandler.wasError() ) 1220 { 1221 // No error, we can enable the schema in the real registries 1222 for ( Schema schema : schemas ) 1223 { 1224 load( registries, schema ); 1225 } 1226 1227 return true; 1228 } 1229 else 1230 { 1231 for ( Schema schema : schemas ) 1232 { 1233 schema.disable(); 1234 } 1235 1236 return false; 1237 } 1238 } 1239 1240 1241 /** 1242 * {@inheritDoc} 1243 */ 1244 @Override 1245 public boolean loadDisabled( String... schemaNames ) throws LdapException 1246 { 1247 Schema[] schemas = toArray( schemaNames ); 1248 1249 return loadDisabled( schemas ); 1250 } 1251 1252 1253 /** 1254 * {@inheritDoc} 1255 */ 1256 @Override 1257 public boolean loadRelaxed( Schema... schemas ) throws LdapException 1258 { 1259 return false; 1260 } 1261 1262 1263 /** 1264 * {@inheritDoc} 1265 */ 1266 @Override 1267 public boolean loadRelaxed( String... schemaNames ) throws LdapException 1268 { 1269 Schema[] schemas = toArray( schemaNames ); 1270 return loadRelaxed( schemas ); 1271 } 1272 1273 1274 /** 1275 * {@inheritDoc} 1276 */ 1277 @Override 1278 public boolean loadWithDeps( Schema... schemas ) throws LdapException 1279 { 1280 boolean loaded = false; 1281 1282 // Reset the errors if not null 1283 errorHandler.reset(); 1284 1285 // Work on a cloned and relaxed registries 1286 Registries clonedRegistries = cloneRegistries(); 1287 clonedRegistries.setRelaxed(); 1288 1289 // Load the schemas 1290 for ( Schema schema : schemas ) 1291 { 1292 loadDepsFirst( clonedRegistries, schema ); 1293 } 1294 1295 // Build the cross references 1296 clonedRegistries.buildReferences(); 1297 1298 if ( !errorHandler.wasError() ) 1299 { 1300 // Ok no errors. Check the registries now 1301 clonedRegistries.checkRefInteg(); 1302 1303 if ( !errorHandler.wasError() ) 1304 { 1305 // We are golden : let's apply the schema in the real registries 1306 registries = clonedRegistries; 1307 registries.setStrict(); 1308 loaded = true; 1309 } 1310 } 1311 else if ( isStrict() ) 1312 { 1313 // clear the cloned registries 1314 clonedRegistries.clear(); 1315 } 1316 else 1317 { 1318 // Relaxed mode 1319 registries = clonedRegistries; 1320 registries.setRelaxed(); 1321 loaded = true; 1322 } 1323 1324 return loaded; 1325 } 1326 1327 1328 /** 1329 * {@inheritDoc} 1330 */ 1331 @Override 1332 public boolean loadWithDeps( String... schemas ) throws LdapException 1333 { 1334 return loadWithDeps( toArray( schemas ) ); 1335 } 1336 1337 1338 /** 1339 * Recursive method which loads schema's with their dependent schemas first 1340 * and tracks what schemas it has seen so the recursion does not go out of 1341 * control with dependency cycle detection. 1342 * 1343 * @param registries The Registries in which the schemas will be loaded 1344 * @param schema the current schema we are attempting to load 1345 * @throws LdapException if there is a cycle detected and/or another 1346 * failure results while loading, producing and or registering schema objects 1347 */ 1348 private void loadDepsFirst( Registries registries, Schema schema ) throws LdapException 1349 { 1350 if ( schema == null ) 1351 { 1352 if ( LOG.isInfoEnabled() ) 1353 { 1354 LOG.info( I18n.msg( I18n.MSG_16013_SCHEMA_IS_NULL ) ); 1355 } 1356 1357 return; 1358 } 1359 1360 if ( schema.isDisabled() && !registries.isDisabledAccepted() ) 1361 { 1362 if ( LOG.isInfoEnabled() ) 1363 { 1364 LOG.info( I18n.msg( I18n.MSG_16017_UNACCEPTED_DISABLED_SCHEMA ) ); 1365 } 1366 1367 return; 1368 } 1369 1370 String schemaName = schema.getSchemaName(); 1371 1372 if ( registries.isSchemaLoaded( schemaName ) ) 1373 { 1374 if ( LOG.isInfoEnabled() ) 1375 { 1376 LOG.info( I18n.msg( I18n.MSG_16018_SCHEMA_ALREADY_LOADED, schema.getSchemaName() ) ); 1377 } 1378 1379 return; 1380 } 1381 1382 String[] deps = schema.getDependencies(); 1383 1384 // if no deps then load this guy and return 1385 if ( ( deps == null ) || ( deps.length == 0 ) ) 1386 { 1387 load( registries, schema ); 1388 1389 return; 1390 } 1391 1392 /* 1393 * We got deps and need to load them before this schema. We go through 1394 * all deps loading them with their deps first if they have not been 1395 * loaded. 1396 */ 1397 for ( String depName : deps ) 1398 { 1399 if ( !registries.isSchemaLoaded( depName ) ) 1400 { 1401 // Call recursively this method 1402 Schema schemaDep = schemaMap.get( depName ); 1403 loadDepsFirst( registries, schemaDep ); 1404 } 1405 } 1406 1407 // Now load the current schema 1408 load( registries, schema ); 1409 } 1410 1411 1412 /** 1413 * {@inheritDoc} 1414 */ 1415 @Override 1416 public boolean loadWithDepsRelaxed( Schema... schemas ) throws LdapException 1417 { 1418 registries.setRelaxed(); 1419 1420 // Load the schemas 1421 for ( Schema schema : schemas ) 1422 { 1423 loadDepsFirstRelaxed( schema ); 1424 } 1425 1426 // Build the cross references 1427 registries.buildReferences(); 1428 1429 // Check the registries now 1430 registries.checkRefInteg(); 1431 1432 return true; 1433 } 1434 1435 1436 /** 1437 * {@inheritDoc} 1438 */ 1439 @Override 1440 public boolean loadWithDepsRelaxed( String... schemas ) throws LdapException 1441 { 1442 return loadWithDepsRelaxed( toArray( schemas ) ); 1443 } 1444 1445 1446 /** 1447 * Recursive method which loads schema's with their dependent schemas first 1448 * and tracks what schemas it has seen so the recursion does not go out of 1449 * control with dependency cycle detection. 1450 * 1451 * @param schema the current schema we are attempting to load 1452 * @throws LdapException if there is a cycle detected and/or another 1453 * failure results while loading, producing and or registering schema objects 1454 */ 1455 private void loadDepsFirstRelaxed( Schema schema ) throws LdapException 1456 { 1457 if ( schema == null ) 1458 { 1459 if ( LOG.isInfoEnabled() ) 1460 { 1461 LOG.info( I18n.msg( I18n.MSG_16013_SCHEMA_IS_NULL ) ); 1462 } 1463 1464 return; 1465 } 1466 1467 if ( schema.isDisabled() && !registries.isDisabledAccepted() ) 1468 { 1469 if ( LOG.isInfoEnabled() ) 1470 { 1471 LOG.info( I18n.msg( I18n.MSG_16017_UNACCEPTED_DISABLED_SCHEMA ) ); 1472 } 1473 1474 return; 1475 } 1476 1477 String schemaName = schema.getSchemaName(); 1478 1479 if ( registries.isSchemaLoaded( schemaName ) ) 1480 { 1481 if ( LOG.isInfoEnabled() ) 1482 { 1483 LOG.info( I18n.msg( I18n.MSG_16018_SCHEMA_ALREADY_LOADED, schema.getSchemaName() ) ); 1484 } 1485 1486 return; 1487 } 1488 1489 String[] deps = schema.getDependencies(); 1490 1491 // if no deps then load this guy and return 1492 if ( ( deps == null ) || ( deps.length == 0 ) ) 1493 { 1494 load( registries, schema ); 1495 1496 return; 1497 } 1498 1499 /* 1500 * We got deps and need to load them before this schema. We go through 1501 * all deps loading them with their deps first if they have not been 1502 * loaded. 1503 */ 1504 for ( String depName : deps ) 1505 { 1506 if ( !registries.isSchemaLoaded( schemaName ) ) 1507 { 1508 // Call recursively this method 1509 Schema schemaDep = schema.getSchemaLoader().getSchema( depName ); 1510 loadDepsFirstRelaxed( schemaDep ); 1511 } 1512 } 1513 1514 // Now load the current schema 1515 load( registries, schema ); 1516 } 1517 1518 1519 /** 1520 * {@inheritDoc} 1521 */ 1522 @Override 1523 public void setRegistries( Registries registries ) 1524 { 1525 this.registries = registries; 1526 } 1527 1528 1529 /** 1530 * {@inheritDoc} 1531 */ 1532 @Override 1533 public boolean unload( Schema... schemas ) throws LdapException 1534 { 1535 boolean unloaded = false; 1536 1537 // Reset the errors if not null 1538 errorHandler.reset(); 1539 1540 // Work on a cloned and relaxed registries 1541 Registries clonedRegistries = cloneRegistries(); 1542 clonedRegistries.setRelaxed(); 1543 1544 // Load the schemas 1545 for ( Schema schema : schemas ) 1546 { 1547 unload( clonedRegistries, schema ); 1548 } 1549 1550 // Build the cross references 1551 clonedRegistries.buildReferences(); 1552 1553 if ( !errorHandler.wasError() ) 1554 { 1555 // Ok no errors. Check the registries now 1556 clonedRegistries.checkRefInteg(); 1557 1558 if ( !errorHandler.wasError() ) 1559 { 1560 // We are golden : let's apply the schema in the real registries 1561 registries.setRelaxed(); 1562 1563 // Load the schemas 1564 for ( Schema schema : schemas ) 1565 { 1566 unload( registries, schema ); 1567 1568 // Update the schema dependences 1569 for ( String dep : schema.getDependencies() ) 1570 { 1571 Set<String> deps = schemaDependencies.get( dep ); 1572 1573 if ( deps != null ) 1574 { 1575 deps.remove( schema.getSchemaName() ); 1576 } 1577 } 1578 1579 schemaMap.remove( schema.getSchemaName() ); 1580 } 1581 1582 // Build the cross references 1583 registries.buildReferences(); 1584 registries.setStrict(); 1585 1586 unloaded = true; 1587 } 1588 } 1589 1590 // clear the cloned registries 1591 clonedRegistries.clear(); 1592 1593 return unloaded; 1594 } 1595 1596 1597 /** 1598 * {@inheritDoc} 1599 */ 1600 @Override 1601 public boolean unload( String... schemaNames ) throws LdapException 1602 { 1603 Schema[] schemas = toArray( schemaNames ); 1604 1605 return unload( schemas ); 1606 } 1607 1608 1609 /** 1610 * {@inheritDoc} 1611 */ 1612 @Override 1613 public boolean verify( Schema... schemas ) throws LdapException 1614 { 1615 errorHandler.reset(); 1616 // Work on a cloned registries 1617 Registries clonedRegistries = cloneRegistries(); 1618 1619 // Loop on all the schemas 1620 for ( Schema schema : schemas ) 1621 { 1622 try 1623 { 1624 // Inject the schema 1625 boolean loaded = load( clonedRegistries, schema ); 1626 1627 if ( !loaded ) 1628 { 1629 // We got an error : exit 1630 clonedRegistries.clear(); 1631 return false; 1632 } 1633 1634 // Now, check the registries 1635 clonedRegistries.checkRefInteg(); 1636 1637 if ( !errorHandler.wasError() ) 1638 { 1639 // We got an error : exit 1640 clonedRegistries.clear(); 1641 return false; 1642 } 1643 } 1644 catch ( Exception e ) 1645 { 1646 // We got an error : exit 1647 clonedRegistries.clear(); 1648 return false; 1649 } 1650 } 1651 1652 // We can now delete the cloned registries before exiting 1653 clonedRegistries.clear(); 1654 1655 return true; 1656 } 1657 1658 1659 /** 1660 * {@inheritDoc} 1661 */ 1662 @Override 1663 public boolean verify( String... schemas ) throws LdapException 1664 { 1665 return verify( toArray( schemas ) ); 1666 } 1667 1668 1669 /** 1670 * @return the namingContext 1671 */ 1672 @Override 1673 public Dn getNamingContext() 1674 { 1675 return namingContext; 1676 } 1677 1678 1679 /** 1680 * Initializes the SchemaService 1681 * 1682 * @throws LdapException If the initialization fails 1683 */ 1684 @Override 1685 public void initialize() throws LdapException 1686 { 1687 } 1688 1689 1690 //----------------------------------------------------------------------------------- 1691 // Immutable accessors 1692 //----------------------------------------------------------------------------------- 1693 /** 1694 * {@inheritDoc} 1695 */ 1696 @Override 1697 public AttributeTypeRegistry getAttributeTypeRegistry() 1698 { 1699 return new ImmutableAttributeTypeRegistry( registries.getAttributeTypeRegistry() ); 1700 } 1701 1702 1703 /** 1704 * {@inheritDoc} 1705 */ 1706 @Override 1707 public ComparatorRegistry getComparatorRegistry() 1708 { 1709 return new ImmutableComparatorRegistry( registries.getComparatorRegistry() ); 1710 } 1711 1712 1713 /** 1714 * {@inheritDoc} 1715 */ 1716 @Override 1717 public DitContentRuleRegistry getDITContentRuleRegistry() 1718 { 1719 return new ImmutableDitContentRuleRegistry( registries.getDitContentRuleRegistry() ); 1720 } 1721 1722 1723 /** 1724 * {@inheritDoc} 1725 */ 1726 @Override 1727 public DitStructureRuleRegistry getDITStructureRuleRegistry() 1728 { 1729 return new ImmutableDitStructureRuleRegistry( registries.getDitStructureRuleRegistry() ); 1730 } 1731 1732 1733 /** 1734 * {@inheritDoc} 1735 */ 1736 @Override 1737 public MatchingRuleRegistry getMatchingRuleRegistry() 1738 { 1739 return new ImmutableMatchingRuleRegistry( registries.getMatchingRuleRegistry() ); 1740 } 1741 1742 1743 /** 1744 * {@inheritDoc} 1745 */ 1746 @Override 1747 public MatchingRuleUseRegistry getMatchingRuleUseRegistry() 1748 { 1749 return new ImmutableMatchingRuleUseRegistry( registries.getMatchingRuleUseRegistry() ); 1750 } 1751 1752 1753 /** 1754 * {@inheritDoc} 1755 */ 1756 @Override 1757 public NameFormRegistry getNameFormRegistry() 1758 { 1759 return new ImmutableNameFormRegistry( registries.getNameFormRegistry() ); 1760 } 1761 1762 1763 /** 1764 * {@inheritDoc} 1765 */ 1766 @Override 1767 public NormalizerRegistry getNormalizerRegistry() 1768 { 1769 return new ImmutableNormalizerRegistry( registries.getNormalizerRegistry() ); 1770 } 1771 1772 1773 /** 1774 * {@inheritDoc} 1775 */ 1776 @Override 1777 public ObjectClassRegistry getObjectClassRegistry() 1778 { 1779 return new ImmutableObjectClassRegistry( registries.getObjectClassRegistry() ); 1780 } 1781 1782 1783 /** 1784 * {@inheritDoc} 1785 */ 1786 @Override 1787 public LdapSyntaxRegistry getLdapSyntaxRegistry() 1788 { 1789 return new ImmutableLdapSyntaxRegistry( registries.getLdapSyntaxRegistry() ); 1790 } 1791 1792 1793 /** 1794 * {@inheritDoc} 1795 */ 1796 @Override 1797 public SyntaxCheckerRegistry getSyntaxCheckerRegistry() 1798 { 1799 return new ImmutableSyntaxCheckerRegistry( registries.getSyntaxCheckerRegistry() ); 1800 } 1801 1802 1803 /** 1804 * Get rid of AT's options (everything after the ';' 1805 * @param oid The AT's OID 1806 * @return The AT without its options 1807 */ 1808 private String stripOptions( String oid ) 1809 { 1810 int semiColonPos = oid.indexOf( ';' ); 1811 1812 if ( semiColonPos != -1 ) 1813 { 1814 return oid.substring( 0, semiColonPos ); 1815 } 1816 else 1817 { 1818 return oid; 1819 } 1820 } 1821 1822 1823 /** 1824 * {@inheritDoc} 1825 */ 1826 @Override 1827 public AttributeType lookupAttributeTypeRegistry( String oid ) throws LdapException 1828 { 1829 String oidTrimmed = Strings.toLowerCaseAscii( oid ).trim(); 1830 String oidNoOption = stripOptions( oidTrimmed ); 1831 return registries.getAttributeTypeRegistry().lookup( oidNoOption ); 1832 } 1833 1834 1835 /** 1836 * {@inheritDoc} 1837 */ 1838 @Override 1839 public AttributeType getAttributeType( String oid ) 1840 { 1841 try 1842 { 1843 // Get rid of the options 1844 String attributeTypeNoOptions = SchemaUtils.stripOptions( oid ); 1845 return registries.getAttributeTypeRegistry().lookup( Strings.toLowerCaseAscii( attributeTypeNoOptions ).trim() ); 1846 } 1847 catch ( LdapException lnsae ) 1848 { 1849 return null; 1850 } 1851 } 1852 1853 1854 /** 1855 * {@inheritDoc} 1856 */ 1857 @Override 1858 public LdapComparator<?> lookupComparatorRegistry( String oid ) throws LdapException 1859 { 1860 return registries.getComparatorRegistry().lookup( oid ); 1861 } 1862 1863 1864 /** 1865 * {@inheritDoc} 1866 */ 1867 @Override 1868 public MatchingRule lookupMatchingRuleRegistry( String oid ) throws LdapException 1869 { 1870 return registries.getMatchingRuleRegistry().lookup( Strings.toLowerCaseAscii( oid ).trim() ); 1871 } 1872 1873 1874 /** 1875 * {@inheritDoc} 1876 */ 1877 @Override 1878 public Normalizer lookupNormalizerRegistry( String oid ) throws LdapException 1879 { 1880 return registries.getNormalizerRegistry().lookup( oid ); 1881 } 1882 1883 1884 /** 1885 * {@inheritDoc} 1886 */ 1887 @Override 1888 public ObjectClass lookupObjectClassRegistry( String oid ) throws LdapException 1889 { 1890 return registries.getObjectClassRegistry().lookup( Strings.toLowerCaseAscii( oid ).trim() ); 1891 } 1892 1893 1894 /** 1895 * {@inheritDoc} 1896 */ 1897 @Override 1898 public LdapSyntax lookupLdapSyntaxRegistry( String oid ) throws LdapException 1899 { 1900 return registries.getLdapSyntaxRegistry().lookup( Strings.toLowerCaseAscii( oid ).trim() ); 1901 } 1902 1903 1904 /** 1905 * {@inheritDoc} 1906 */ 1907 @Override 1908 public SyntaxChecker lookupSyntaxCheckerRegistry( String oid ) throws LdapException 1909 { 1910 return registries.getSyntaxCheckerRegistry().lookup( oid ); 1911 } 1912 1913 1914 /** 1915 * Check that the given OID exists in the globalOidRegistry. 1916 * 1917 * @param schemaObject The SchemaObject to check 1918 * @return <tt>true</tt> if the OID exists 1919 */ 1920 private boolean checkOidExist( SchemaObject schemaObject ) 1921 { 1922 if ( !( schemaObject instanceof LoadableSchemaObject ) ) 1923 { 1924 return registries.getGlobalOidRegistry().contains( schemaObject.getOid() ); 1925 } 1926 1927 if ( schemaObject instanceof LdapComparator<?> ) 1928 { 1929 return registries.getComparatorRegistry().contains( schemaObject.getOid() ); 1930 } 1931 1932 if ( schemaObject instanceof SyntaxChecker ) 1933 { 1934 return registries.getSyntaxCheckerRegistry().contains( schemaObject.getOid() ); 1935 } 1936 1937 if ( schemaObject instanceof Normalizer ) 1938 { 1939 return registries.getNormalizerRegistry().contains( schemaObject.getOid() ); 1940 } 1941 1942 return false; 1943 } 1944 1945 1946 /** 1947 * Get the inner SchemaObject if it's not a C/N/SC 1948 * 1949 * @param schemaObject The SchemaObject to retreive 1950 * @return The found SchemaObject 1951 * @throws LdapException If the SchemaObject can't be found 1952 */ 1953 private SchemaObject getSchemaObject( SchemaObject schemaObject ) throws LdapException 1954 { 1955 if ( schemaObject instanceof LoadableSchemaObject ) 1956 { 1957 return schemaObject; 1958 } 1959 else 1960 { 1961 return registries.getGlobalOidRegistry().getSchemaObject( schemaObject.getOid() ); 1962 } 1963 } 1964 1965 1966 /** 1967 * Retrieve the schema name for a specific SchemaObject, or return "other" if none is found. 1968 * 1969 * @param schemaObject The schemaObject to read 1970 * @return The schema name 1971 */ 1972 private String getSchemaName( SchemaObject schemaObject ) 1973 { 1974 String schemaName = Strings.toLowerCaseAscii( schemaObject.getSchemaName() ); 1975 1976 if ( Strings.isEmpty( schemaName ) ) 1977 { 1978 return MetaSchemaConstants.SCHEMA_OTHER; 1979 } 1980 1981 if ( schemaMap.get( schemaName ) == null ) 1982 { 1983 return null; 1984 } 1985 else 1986 { 1987 return schemaName; 1988 } 1989 } 1990 1991 1992 private SchemaObject copy( SchemaObject schemaObject ) 1993 { 1994 SchemaObject copy = null; 1995 1996 if ( !( schemaObject instanceof LoadableSchemaObject ) ) 1997 { 1998 copy = schemaObject.copy(); 1999 } 2000 else 2001 { 2002 // Check the schemaObject here. 2003 if ( ( ( LoadableSchemaObject ) schemaObject ).isValid() ) 2004 { 2005 copy = schemaObject; 2006 } 2007 else 2008 { 2009 // We have an invalid SchemaObject, no need to go any further 2010 LdapUnwillingToPerformException error = new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM, I18n.err( 2011 I18n.ERR_16079_INVALID_SCHEMA_OBJECT_CANNOT_BE_LOADED, schemaObject.getOid() ) ); 2012 errorHandler.handle( LOG, error.getMessage(), error ); 2013 } 2014 } 2015 2016 return copy; 2017 } 2018 2019 2020 //----------------------------------------------------------------------------------- 2021 // SchemaObject operations 2022 //----------------------------------------------------------------------------------- 2023 /** 2024 * {@inheritDoc} 2025 */ 2026 @Override 2027 public boolean add( SchemaObject schemaObject ) throws LdapException 2028 { 2029 // First, clear the errors 2030 errorHandler.reset(); 2031 2032 // Clone the schemaObject 2033 SchemaObject copy = copy( schemaObject ); 2034 2035 if ( copy == null ) 2036 { 2037 return false; 2038 } 2039 2040 if ( registries.isRelaxed() ) 2041 { 2042 // Apply the addition right away 2043 registries.add( copy, true ); 2044 2045 return !errorHandler.wasError(); 2046 } 2047 else 2048 { 2049 // Clone, apply, check, then apply again if ok 2050 // The new schemaObject's OID must not already exist 2051 if ( checkOidExist( copy ) ) 2052 { 2053 LdapSchemaException ldapSchemaException = new LdapSchemaException( 2054 LdapSchemaExceptionCodes.OID_ALREADY_REGISTERED, I18n.err( I18n.ERR_16036_OID_NOT_UNIQUE, 2055 schemaObject.getOid() ) ); 2056 ldapSchemaException.setSourceObject( schemaObject ); 2057 errorHandler.handle( LOG, ldapSchemaException.getMessage(), ldapSchemaException ); 2058 2059 return false; 2060 } 2061 2062 // Build the new AttributeType from the given entry 2063 String schemaName = getSchemaName( copy ); 2064 2065 if ( schemaName == null ) 2066 { 2067 // The schema associated with the SchemaaObject does not exist. This is not valid. 2068 2069 LdapSchemaException ldapSchemaException = new LdapSchemaException( 2070 LdapSchemaExceptionCodes.NONEXISTENT_SCHEMA, I18n.err( I18n.ERR_16037_NON_EXISTING_SCHEMA, 2071 schemaObject.getOid(), copy.getSchemaName() ) ); 2072 ldapSchemaException.setSourceObject( schemaObject ); 2073 ldapSchemaException.setRelatedId( copy.getSchemaName() ); 2074 errorHandler.handle( LOG, ldapSchemaException.getMessage(), ldapSchemaException ); 2075 2076 return false; 2077 } 2078 2079 // At this point, the constructed AttributeType has not been checked against the 2080 // existing Registries. It may be broken (missing SUP, or such), it will be checked 2081 // there, if the schema and the AttributeType are both enabled. 2082 Schema schema = getLoadedSchema( schemaName ); 2083 2084 if ( schema == null ) 2085 { 2086 // The SchemaObject must be associated with an existing schema 2087 String msg = I18n.err( I18n.ERR_16038_NOT_ASSOCIATED_TO_A_SCHEMA, copy.getOid() ); 2088 Throwable error = new LdapProtocolErrorException( msg ); 2089 errorHandler.handle( LOG, msg, error ); 2090 return false; 2091 } 2092 2093 if ( schema.isEnabled() && copy.isEnabled() ) 2094 { 2095 // As we may break the registries, work on a cloned registries 2096 Registries clonedRegistries = null; 2097 2098 try 2099 { 2100 clonedRegistries = registries.clone(); 2101 } 2102 catch ( CloneNotSupportedException cnse ) 2103 { 2104 throw new LdapOtherException( cnse.getMessage(), cnse ); 2105 } 2106 2107 // Inject the new SchemaObject in the cloned registries 2108 clonedRegistries.add( copy, true ); 2109 2110 // Remove the cloned registries 2111 clonedRegistries.clear(); 2112 2113 // If we didn't get any error, apply the addition to the real registries 2114 if ( !errorHandler.wasError() ) 2115 { 2116 // Copy again as the clonedRegistries clear has removed the previous copy 2117 copy = copy( schemaObject ); 2118 2119 // Apply the addition to the real registries 2120 registries.add( copy, true ); 2121 2122 if ( LOG.isDebugEnabled() ) 2123 { 2124 LOG.debug( I18n.msg( I18n.MSG_16019_ENABLED_SCHEMA_ADDED, copy.getName(), schemaName ) ); 2125 } 2126 2127 return true; 2128 } 2129 else 2130 { 2131 // We have some error : reject the addition and get out 2132 errorHandler.handle( LOG, I18n.msg( I18n.MSG_16020_CANNOT_LOAD_SCHEMAOBJECT, 2133 copy.getOid(), Strings.listToString( errorHandler.getErrors() ) ), null ); 2134 return false; 2135 } 2136 } 2137 else 2138 { 2139 // At least, we register the OID in the globalOidRegistry, and associates it with the 2140 // schema 2141 registries.associateWithSchema( copy ); 2142 2143 if ( LOG.isDebugEnabled() ) 2144 { 2145 LOG.debug( I18n.msg( I18n.MSG_16021_ADDED_INTO_DISABLED_SCHEMA, copy.getName(), schemaName ) ); 2146 } 2147 2148 return !errorHandler.wasError(); 2149 } 2150 } 2151 } 2152 2153 2154 /** 2155 * {@inheritDoc} 2156 */ 2157 @Override 2158 public boolean delete( SchemaObject schemaObject ) throws LdapException 2159 { 2160 // First, clear the errors 2161 errorHandler.reset(); 2162 2163 if ( registries.isRelaxed() ) 2164 { 2165 // Apply the addition right away 2166 registries.delete( schemaObject ); 2167 2168 return !errorHandler.wasError(); 2169 } 2170 else 2171 { 2172 // Clone, apply, check, then apply again if ok 2173 // The new schemaObject's OID must exist 2174 if ( !checkOidExist( schemaObject ) ) 2175 { 2176 Throwable error = new LdapProtocolErrorException( I18n.err( I18n.ERR_16039_OID_DOES_NOT_EXIST, 2177 schemaObject.getOid() ) ); 2178 errorHandler.handle( LOG, error.getMessage(), error ); 2179 return false; 2180 } 2181 2182 // Get the SchemaObject to delete if it's not a LoadableSchemaObject 2183 SchemaObject toDelete = getSchemaObject( schemaObject ); 2184 2185 // First check that this SchemaObject does not have any referencing SchemaObjects 2186 Set<SchemaObjectWrapper> referencing = registries.getReferencing( toDelete ); 2187 2188 if ( ( referencing != null ) && !referencing.isEmpty() ) 2189 { 2190 String msg = I18n.err( I18n.ERR_16040_CANNOT_REMOVE_FROM_REGISTRY, schemaObject.getOid(), 2191 Strings.setToString( referencing ) ); 2192 2193 Throwable error = new LdapProtocolErrorException( msg ); 2194 errorHandler.handle( LOG, msg, error ); 2195 return false; 2196 } 2197 2198 String schemaName = getSchemaName( toDelete ); 2199 2200 // At this point, the deleted AttributeType may be referenced, it will be checked 2201 // there, if the schema and the AttributeType are both enabled. 2202 Schema schema = getLoadedSchema( schemaName ); 2203 2204 if ( schema == null ) 2205 { 2206 // The SchemaObject must be associated with an existing schema 2207 String msg = I18n.err( I18n.ERR_16041_CANNOT_DELETE_SCHEMA_OBJECT, schemaObject.getOid() ); 2208 Throwable error = new LdapProtocolErrorException( msg ); 2209 errorHandler.handle( LOG, msg, error ); 2210 return false; 2211 } 2212 2213 if ( schema.isEnabled() && schemaObject.isEnabled() ) 2214 { 2215 // As we may break the registries, work on a cloned registries 2216 Registries clonedRegistries = null; 2217 2218 try 2219 { 2220 clonedRegistries = registries.clone(); 2221 } 2222 catch ( CloneNotSupportedException cnse ) 2223 { 2224 throw new LdapOtherException( cnse.getMessage(), cnse ); 2225 } 2226 2227 // Delete the SchemaObject from the cloned registries 2228 clonedRegistries.delete( toDelete ); 2229 2230 // Remove the cloned registries 2231 clonedRegistries.clear(); 2232 2233 // If we didn't get any error, apply the deletion to the real retistries 2234 if ( !errorHandler.wasError() ) 2235 { 2236 // Apply the deletion to the real registries 2237 registries.delete( toDelete ); 2238 2239 if ( LOG.isDebugEnabled() ) 2240 { 2241 LOG.debug( I18n.msg( I18n.MSG_16022_REMOVED_FROM_ENABLED_SCHEMA, toDelete.getName(), schemaName ) ); 2242 } 2243 2244 return true; 2245 } 2246 else 2247 { 2248 // We have some error : reject the deletion and get out 2249 errorHandler.handle( LOG, I18n.msg( I18n.MSG_16023_CANNOT_DELETE_SCHEMAOBJECT, 2250 schemaObject.getOid(), Strings.listToString( errorHandler.getErrors() ) ), null ); 2251 2252 return false; 2253 } 2254 } 2255 else 2256 { 2257 // At least, we register the OID in the globalOidRegistry, and associates it with the 2258 // schema 2259 registries.associateWithSchema( schemaObject ); 2260 2261 if ( LOG.isDebugEnabled() ) 2262 { 2263 LOG.debug( I18n.msg( I18n.MSG_16024_REMOVED_FROM_DISABLED_SCHEMA, schemaObject.getName(), schemaName ) ); 2264 } 2265 2266 return !errorHandler.wasError(); 2267 } 2268 } 2269 } 2270 2271 2272 /** 2273 * {@inheritDoc} 2274 */ 2275 @Override 2276 public Map<String, OidNormalizer> getNormalizerMapping() 2277 { 2278 return registries.getAttributeTypeRegistry().getNormalizerMapping(); 2279 } 2280 2281 2282 /** 2283 * {@inheritDoc} 2284 */ 2285 @SuppressWarnings("rawtypes") 2286 @Override 2287 public OidRegistry getGlobalOidRegistry() 2288 { 2289 return registries.getGlobalOidRegistry(); 2290 } 2291 2292 2293 /** 2294 * {@inheritDoc} 2295 */ 2296 @Override 2297 public Schema getLoadedSchema( String schemaName ) 2298 { 2299 return schemaMap.get( schemaName ); 2300 } 2301 2302 2303 /** 2304 * {@inheritDoc} 2305 */ 2306 @Override 2307 public boolean isSchemaLoaded( String schemaName ) 2308 { 2309 try 2310 { 2311 Schema schema = schemaMap.get( schemaName ); 2312 2313 return schema != null; 2314 } 2315 catch ( Exception e ) 2316 { 2317 return false; 2318 } 2319 } 2320 2321 2322 /** 2323 * {@inheritDoc} 2324 */ 2325 @Override 2326 public SchemaObject unregisterAttributeType( String attributeTypeOid ) throws LdapException 2327 { 2328 return registries.getAttributeTypeRegistry().unregister( attributeTypeOid ); 2329 } 2330 2331 2332 /** 2333 * {@inheritDoc} 2334 */ 2335 @Override 2336 public SchemaObject unregisterComparator( String comparatorOid ) throws LdapException 2337 { 2338 return registries.getComparatorRegistry().unregister( comparatorOid ); 2339 } 2340 2341 2342 /** 2343 * {@inheritDoc} 2344 */ 2345 @Override 2346 public SchemaObject unregisterDitControlRule( String ditControlRuleOid ) throws LdapException 2347 { 2348 return registries.getDitContentRuleRegistry().unregister( ditControlRuleOid ); 2349 } 2350 2351 2352 /** 2353 * {@inheritDoc} 2354 */ 2355 @Override 2356 public SchemaObject unregisterDitStructureRule( String ditStructureRuleOid ) throws LdapException 2357 { 2358 return registries.getDitStructureRuleRegistry().unregister( ditStructureRuleOid ); 2359 } 2360 2361 2362 /** 2363 * {@inheritDoc} 2364 */ 2365 @Override 2366 public SchemaObject unregisterLdapSyntax( String ldapSyntaxOid ) throws LdapException 2367 { 2368 return registries.getLdapSyntaxRegistry().unregister( ldapSyntaxOid ); 2369 } 2370 2371 2372 /** 2373 * {@inheritDoc} 2374 */ 2375 @Override 2376 public SchemaObject unregisterMatchingRule( String matchingRuleOid ) throws LdapException 2377 { 2378 return registries.getMatchingRuleRegistry().unregister( matchingRuleOid ); 2379 } 2380 2381 2382 /** 2383 * {@inheritDoc} 2384 */ 2385 @Override 2386 public SchemaObject unregisterMatchingRuleUse( String matchingRuleUseOid ) throws LdapException 2387 { 2388 return registries.getMatchingRuleUseRegistry().unregister( matchingRuleUseOid ); 2389 } 2390 2391 2392 /** 2393 * {@inheritDoc} 2394 */ 2395 @Override 2396 public SchemaObject unregisterNameForm( String nameFormOid ) throws LdapException 2397 { 2398 return registries.getNameFormRegistry().unregister( nameFormOid ); 2399 } 2400 2401 2402 /** 2403 * {@inheritDoc} 2404 */ 2405 @Override 2406 public SchemaObject unregisterNormalizer( String normalizerOid ) throws LdapException 2407 { 2408 return registries.getNormalizerRegistry().unregister( normalizerOid ); 2409 } 2410 2411 2412 /** 2413 * {@inheritDoc} 2414 */ 2415 @Override 2416 public SchemaObject unregisterObjectClass( String objectClassOid ) throws LdapException 2417 { 2418 return registries.getObjectClassRegistry().unregister( objectClassOid ); 2419 } 2420 2421 2422 /** 2423 * {@inheritDoc} 2424 */ 2425 @Override 2426 public SchemaObject unregisterSyntaxChecker( String syntaxCheckerOid ) throws LdapException 2427 { 2428 return registries.getSyntaxCheckerRegistry().unregister( syntaxCheckerOid ); 2429 } 2430 2431 2432 /** 2433 * Tells if the SchemaManager is permissive or if it must be checked 2434 * against inconsistencies. 2435 * 2436 * @return True if SchemaObjects can be added even if they break the consistency 2437 */ 2438 @Override 2439 public boolean isRelaxed() 2440 { 2441 return isRelaxed; 2442 } 2443 2444 2445 /** 2446 * Tells if the SchemaManager is strict. 2447 * 2448 * @return True if SchemaObjects cannot be added if they break the consistency 2449 */ 2450 @Override 2451 public boolean isStrict() 2452 { 2453 return !isRelaxed; 2454 } 2455 2456 2457 /** 2458 * {@inheritDoc} 2459 */ 2460 @Override 2461 public Set<String> listDependentSchemaNames( String schemaName ) 2462 { 2463 return schemaDependencies.get( schemaName ); 2464 } 2465 2466 2467 /** 2468 * Change the SchemaManager to a relaxed mode, where invalid SchemaObjects 2469 * can be registered. 2470 */ 2471 @Override 2472 public void setRelaxed() 2473 { 2474 isRelaxed = RELAXED; 2475 } 2476 2477 2478 /** 2479 * Change the SchemaManager to a strict mode, where invalid SchemaObjects 2480 * cannot be registered. 2481 */ 2482 @Override 2483 public void setStrict() 2484 { 2485 isRelaxed = STRICT; 2486 } 2487 2488 2489 public SchemaErrorHandler getErrorHandler() 2490 { 2491 return errorHandler; 2492 } 2493 2494 2495 public void setErrorHandler( SchemaErrorHandler errorHandler ) 2496 { 2497 this.errorHandler = errorHandler; 2498 registries.setErrorHandler( errorHandler ); 2499 } 2500 2501 2502 /** 2503 * {@inheritDoc} 2504 */ 2505 @Override 2506 public boolean isDisabled( String schemaName ) 2507 { 2508 Schema schema = registries.getLoadedSchema( schemaName ); 2509 2510 return ( schema != null ) && schema.isDisabled(); 2511 } 2512 2513 2514 /** 2515 * {@inheritDoc} 2516 */ 2517 @Override 2518 public boolean isDisabled( Schema schema ) 2519 { 2520 return ( schema != null ) && schema.isDisabled(); 2521 } 2522 2523 2524 /** 2525 * {@inheritDoc} 2526 */ 2527 @Override 2528 public boolean isEnabled( String schemaName ) 2529 { 2530 Schema schema = registries.getLoadedSchema( schemaName ); 2531 2532 return ( schema != null ) && schema.isEnabled(); 2533 } 2534 2535 2536 /** 2537 * {@inheritDoc} 2538 */ 2539 @Override 2540 public boolean isEnabled( Schema schema ) 2541 { 2542 return ( schema != null ) && schema.isEnabled(); 2543 } 2544}