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.shared.ldap.schema.manager.impl; 021 022 023 import java.util.ArrayList; 024 import java.util.HashMap; 025 import java.util.HashSet; 026 import java.util.List; 027 import java.util.Map; 028 import java.util.Set; 029 030 import org.apache.directory.shared.i18n.I18n; 031 import org.apache.directory.shared.ldap.NotImplementedException; 032 import org.apache.directory.shared.ldap.constants.MetaSchemaConstants; 033 import org.apache.directory.shared.ldap.constants.SchemaConstants; 034 import org.apache.directory.shared.ldap.entry.Entry; 035 import org.apache.directory.shared.ldap.exception.LdapException; 036 import org.apache.directory.shared.ldap.exception.LdapInvalidDnException; 037 import org.apache.directory.shared.ldap.exception.LdapProtocolErrorException; 038 import org.apache.directory.shared.ldap.exception.LdapUnwillingToPerformException; 039 //import org.apache.directory.shared.ldap.exception.LdapSchemaViolationException; 040 import org.apache.directory.shared.ldap.message.ResultCodeEnum; 041 import org.apache.directory.shared.ldap.name.DN; 042 import org.apache.directory.shared.ldap.schema.AttributeType; 043 import org.apache.directory.shared.ldap.schema.EntityFactory; 044 import org.apache.directory.shared.ldap.schema.LdapComparator; 045 import org.apache.directory.shared.ldap.schema.LdapSyntax; 046 import org.apache.directory.shared.ldap.schema.LoadableSchemaObject; 047 import org.apache.directory.shared.ldap.schema.MatchingRule; 048 import org.apache.directory.shared.ldap.schema.Normalizer; 049 import org.apache.directory.shared.ldap.schema.ObjectClass; 050 import org.apache.directory.shared.ldap.schema.SchemaManager; 051 import org.apache.directory.shared.ldap.schema.SchemaObject; 052 import org.apache.directory.shared.ldap.schema.SchemaObjectWrapper; 053 import org.apache.directory.shared.ldap.schema.SyntaxChecker; 054 import org.apache.directory.shared.ldap.schema.loader.ldif.SchemaEntityFactory; 055 import org.apache.directory.shared.ldap.schema.normalizers.OidNormalizer; 056 import org.apache.directory.shared.ldap.schema.registries.AttributeTypeRegistry; 057 import org.apache.directory.shared.ldap.schema.registries.ComparatorRegistry; 058 import org.apache.directory.shared.ldap.schema.registries.DITContentRuleRegistry; 059 import org.apache.directory.shared.ldap.schema.registries.DITStructureRuleRegistry; 060 import org.apache.directory.shared.ldap.schema.registries.ImmutableAttributeTypeRegistry; 061 import org.apache.directory.shared.ldap.schema.registries.ImmutableComparatorRegistry; 062 import org.apache.directory.shared.ldap.schema.registries.ImmutableDITContentRuleRegistry; 063 import org.apache.directory.shared.ldap.schema.registries.ImmutableDITStructureRuleRegistry; 064 import org.apache.directory.shared.ldap.schema.registries.ImmutableLdapSyntaxRegistry; 065 import org.apache.directory.shared.ldap.schema.registries.ImmutableMatchingRuleRegistry; 066 import org.apache.directory.shared.ldap.schema.registries.ImmutableMatchingRuleUseRegistry; 067 import org.apache.directory.shared.ldap.schema.registries.ImmutableNameFormRegistry; 068 import org.apache.directory.shared.ldap.schema.registries.ImmutableNormalizerRegistry; 069 import org.apache.directory.shared.ldap.schema.registries.ImmutableObjectClassRegistry; 070 import org.apache.directory.shared.ldap.schema.registries.ImmutableSyntaxCheckerRegistry; 071 import org.apache.directory.shared.ldap.schema.registries.LdapSyntaxRegistry; 072 import org.apache.directory.shared.ldap.schema.registries.MatchingRuleRegistry; 073 import org.apache.directory.shared.ldap.schema.registries.MatchingRuleUseRegistry; 074 import org.apache.directory.shared.ldap.schema.registries.NameFormRegistry; 075 import org.apache.directory.shared.ldap.schema.registries.NormalizerRegistry; 076 import org.apache.directory.shared.ldap.schema.registries.ObjectClassRegistry; 077 import org.apache.directory.shared.ldap.schema.registries.OidRegistry; 078 import org.apache.directory.shared.ldap.schema.registries.Registries; 079 import org.apache.directory.shared.ldap.schema.registries.Schema; 080 import org.apache.directory.shared.ldap.schema.registries.SchemaLoader; 081 import org.apache.directory.shared.ldap.schema.registries.SyntaxCheckerRegistry; 082 import org.apache.directory.shared.ldap.util.StringTools; 083 import org.slf4j.Logger; 084 import org.slf4j.LoggerFactory; 085 086 087 /** 088 * The SchemaManager class : it handles all the schema operations (addition, removal, 089 * modification). 090 * 091 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 092 * @version $Rev$, $Date$ 093 */ 094 public class DefaultSchemaManager implements SchemaManager 095 { 096 /** static class logger */ 097 private static final Logger LOG = LoggerFactory.getLogger( DefaultSchemaManager.class ); 098 099 /** The NamingContext this SchemaManager is associated with */ 100 private DN namingContext; 101 102 /** The global registries for this namingContext */ 103 private volatile Registries registries; 104 105 /** The list of errors produced when loading some schema elements */ 106 private List<Throwable> errors; 107 108 /** The Schema schemaLoader used by this SchemaManager */ 109 private SchemaLoader schemaLoader; 110 111 /** the factory that generates respective SchemaObjects from LDIF entries */ 112 protected final EntityFactory factory; 113 114 /** the normalized name for the schema modification attributes */ 115 private DN schemaModificationAttributesDN; 116 117 /** A Map containing all the schema being dependent from a schema */ 118 private Map<String, Set<String>> schemaDependences = new HashMap<String, Set<String>>(); 119 120 /** A flag indicating that the SchemaManager is relaxed or not */ 121 private boolean isRelaxed = STRICT; 122 123 /** Two flags for RELAXED and STRUCT */ 124 public static final boolean STRICT = false; 125 public static final boolean RELAXED = true; 126 127 128 /** 129 * Creates a new instance of DefaultSchemaManager with the default schema schemaLoader 130 * 131 * @param loader The schema loader to use 132 */ 133 public DefaultSchemaManager( SchemaLoader loader ) throws Exception 134 { 135 // Default to the the root (one schemaManager for all the entries 136 namingContext = DN.EMPTY_DN; 137 this.schemaLoader = loader; 138 errors = new ArrayList<Throwable>(); 139 registries = new Registries( this ); 140 factory = new SchemaEntityFactory(); 141 isRelaxed = STRICT; 142 } 143 144 145 /** 146 * Creates a new instance of DefaultSchemaManager, for a specific 147 * naming context 148 * 149 * @param loader The schema loader to use 150 * @param namingContext The associated NamingContext 151 */ 152 public DefaultSchemaManager( SchemaLoader loader, DN namingContext ) throws Exception 153 { 154 this.namingContext = namingContext; 155 this.schemaLoader = loader; 156 errors = new ArrayList<Throwable>(); 157 registries = new Registries( this ); 158 factory = new SchemaEntityFactory(); 159 isRelaxed = STRICT; 160 } 161 162 163 //----------------------------------------------------------------------- 164 // Helper methods 165 //----------------------------------------------------------------------- 166 /** 167 * Clone the registries before doing any modification on it. Relax it 168 * too so that we can update it. 169 */ 170 private Registries cloneRegistries() throws Exception 171 { 172 // Relax the controls at first 173 errors = new ArrayList<Throwable>(); 174 175 // Clone the Registries 176 Registries clonedRegistries = registries.clone(); 177 178 // And update references. We may have errors, that may be fixed 179 // by the new loaded schemas. 180 errors = clonedRegistries.checkRefInteg(); 181 182 // Now, relax the cloned Registries if there is no error 183 clonedRegistries.setRelaxed(); 184 185 return clonedRegistries; 186 } 187 188 189 /** 190 * Transform a String[] array of schema to a Schema[] 191 */ 192 private Schema[] toArray( String... schemas ) throws Exception 193 { 194 Schema[] schemaArray = new Schema[schemas.length]; 195 int n = 0; 196 197 for ( String schemaName : schemas ) 198 { 199 Schema schema = schemaLoader.getSchema( schemaName ); 200 201 if ( schema != null ) 202 { 203 schemaArray[n++] = schema; 204 } 205 else 206 { 207 throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM, I18n.err( I18n.ERR_11001, schemaName ) ); 208 } 209 } 210 211 return schemaArray; 212 } 213 214 215 private void addSchemaObjects( Schema schema, Registries registries ) throws Exception 216 { 217 // Create a content container for this schema 218 registries.addSchema( schema.getSchemaName() ); 219 220 // And inject any existig SchemaObject into the registries 221 addComparators( schema, registries ); 222 addNormalizers( schema, registries ); 223 addSyntaxCheckers( schema, registries ); 224 addSyntaxes( schema, registries ); 225 addMatchingRules( schema, registries ); 226 addAttributeTypes( schema, registries ); 227 addObjectClasses( schema, registries ); 228 addMatchingRuleUses( schema, registries ); 229 addDitContentRules( schema, registries ); 230 addNameForms( schema, registries ); 231 addDitStructureRules( schema, registries ); 232 233 // TODO Add some listener handling at this point 234 //notifyListenerOrRegistries( schema, registries ); 235 } 236 237 238 /** 239 * Delete all the schemaObjects for a given schema from the registries 240 */ 241 private void deleteSchemaObjects( Schema schema, Registries registries ) throws Exception 242 { 243 Map<String, Set<SchemaObjectWrapper>> schemaObjects = registries.getObjectBySchemaName(); 244 Set<SchemaObjectWrapper> content = schemaObjects.get( StringTools.toLowerCase( schema.getSchemaName() ) ); 245 246 List<SchemaObject> toBeDeleted = new ArrayList<SchemaObject>(); 247 248 // Buid an intermediate list to avoid concurrent modifications 249 for ( SchemaObjectWrapper schemaObjectWrapper : content ) 250 { 251 toBeDeleted.add( schemaObjectWrapper.get() ); 252 } 253 254 for ( SchemaObject schemaObject : toBeDeleted ) 255 { 256 registries.delete( errors, schemaObject ); 257 } 258 } 259 260 261 /** 262 * Tells if there are schemaObjects for a given schema from the registries 263 */ 264 private boolean hasSchemaObjects( Schema schema, Registries registries ) throws Exception 265 { 266 Map<String, Set<SchemaObjectWrapper>> schemaObjects = registries.getObjectBySchemaName(); 267 Set<SchemaObjectWrapper> content = schemaObjects.get( StringTools.toLowerCase( schema.getSchemaName() ) ); 268 269 if ( ( content == null ) || content.isEmpty() ) 270 { 271 return false; 272 } 273 else 274 { 275 return true; 276 } 277 } 278 279 280 //----------------------------------------------------------------------- 281 // API methods 282 //----------------------------------------------------------------------- 283 /** 284 * {@inheritDoc} 285 */ 286 public boolean disable( Schema... schemas ) throws Exception 287 { 288 boolean disabled = false; 289 290 // Reset the errors if not null 291 if ( errors != null ) 292 { 293 errors.clear(); 294 } 295 296 // Work on a cloned and relaxed registries 297 Registries clonedRegistries = cloneRegistries(); 298 clonedRegistries.setRelaxed(); 299 300 for ( Schema schema : schemas ) 301 { 302 unload( clonedRegistries, schema ); 303 } 304 305 // Build the cross references 306 errors = clonedRegistries.buildReferences(); 307 308 // Destroy the clonedRegistry 309 clonedRegistries.clear(); 310 311 if ( errors.isEmpty() ) 312 { 313 // Ok no errors. Check the registries now 314 errors = clonedRegistries.checkRefInteg(); 315 316 if ( errors.isEmpty() ) 317 { 318 // We are golden : let's apply the schemas in the real registries 319 for ( Schema schema : schemas ) 320 { 321 unload( registries, schema ); 322 schema.disable(); 323 } 324 325 // Build the cross references 326 errors = registries.buildReferences(); 327 registries.setStrict(); 328 329 disabled = true; 330 } 331 } 332 333 // clear the cloned registries 334 clonedRegistries.clear(); 335 336 return disabled; 337 } 338 339 340 /** 341 * {@inheritDoc} 342 */ 343 public boolean disable( String... schemaNames ) throws Exception 344 { 345 Schema[] schemas = toArray( schemaNames ); 346 347 return disable( schemas ); 348 } 349 350 351 /** 352 * {@inheritDoc} 353 */ 354 public boolean disabledRelaxed( Schema... schemas ) 355 { 356 // TODO Auto-generated method stub 357 return false; 358 } 359 360 361 /** 362 * {@inheritDoc} 363 */ 364 public boolean disabledRelaxed( String... schemas ) 365 { 366 // TODO Auto-generated method stub 367 return false; 368 } 369 370 371 /** 372 * {@inheritDoc} 373 */ 374 public List<Schema> getDisabled() 375 { 376 List<Schema> disabled = new ArrayList<Schema>(); 377 378 for ( Schema schema : registries.getLoadedSchemas().values() ) 379 { 380 if ( schema.isDisabled() ) 381 { 382 disabled.add( schema ); 383 } 384 } 385 386 return disabled; 387 } 388 389 390 /** 391 * {@inheritDoc} 392 */ 393 public boolean enable( Schema... schemas ) throws Exception 394 { 395 boolean enabled = false; 396 397 // Reset the errors if not null 398 if ( errors != null ) 399 { 400 errors.clear(); 401 } 402 403 // Work on a cloned and relaxed registries 404 Registries clonedRegistries = cloneRegistries(); 405 clonedRegistries.setRelaxed(); 406 407 for ( Schema schema : schemas ) 408 { 409 schema.enable(); 410 load( clonedRegistries, schema ); 411 } 412 413 // Build the cross references 414 errors = clonedRegistries.buildReferences(); 415 416 // Destroy the clonedRegistry 417 clonedRegistries.clear(); 418 419 if ( errors.isEmpty() ) 420 { 421 // Ok no errors. Check the registries now 422 errors = clonedRegistries.checkRefInteg(); 423 424 if ( errors.isEmpty() ) 425 { 426 // We are golden : let's apply the schemas in the real registries 427 for ( Schema schema : schemas ) 428 { 429 schema.enable(); 430 load( registries, schema ); 431 } 432 433 // Build the cross references 434 errors = registries.buildReferences(); 435 registries.setStrict(); 436 437 enabled = true; 438 } 439 } 440 441 // clear the cloned registries 442 clonedRegistries.clear(); 443 444 return enabled; 445 } 446 447 448 /** 449 * {@inheritDoc} 450 */ 451 public boolean enable( String... schemaNames ) throws Exception 452 { 453 Schema[] schemas = toArray( schemaNames ); 454 return enable( schemas ); 455 } 456 457 458 /** 459 * {@inheritDoc} 460 */ 461 public boolean enableRelaxed( Schema... schemas ) 462 { 463 // TODO Auto-generated method stub 464 return false; 465 } 466 467 468 /** 469 * {@inheritDoc} 470 */ 471 public boolean enableRelaxed( String... schemas ) 472 { 473 // TODO Auto-generated method stub 474 return false; 475 } 476 477 478 /** 479 * {@inheritDoc} 480 */ 481 public List<Schema> getEnabled() 482 { 483 List<Schema> enabled = new ArrayList<Schema>(); 484 485 for ( Schema schema : registries.getLoadedSchemas().values() ) 486 { 487 if ( schema.isEnabled() ) 488 { 489 enabled.add( schema ); 490 } 491 } 492 493 return enabled; 494 } 495 496 497 /** 498 * {@inheritDoc} 499 */ 500 public List<Throwable> getErrors() 501 { 502 return errors; 503 } 504 505 506 /** 507 * {@inheritDoc} 508 */ 509 public Registries getRegistries() 510 { 511 return registries; 512 } 513 514 515 /** 516 * {@inheritDoc} 517 */ 518 public boolean isDisabledAccepted() 519 { 520 // TODO Auto-generated method stub 521 return false; 522 } 523 524 525 /** 526 * {@inheritDoc} 527 */ 528 public boolean load( Schema... schemas ) throws Exception 529 { 530 if ( schemas.length == 0 ) 531 { 532 return true; 533 } 534 535 boolean loaded = false; 536 537 // Reset the errors if not null 538 if ( errors != null ) 539 { 540 errors.clear(); 541 } 542 543 // Work on a cloned and relaxed registries 544 Registries clonedRegistries = cloneRegistries(); 545 clonedRegistries.setRelaxed(); 546 547 // Load the schemas 548 for ( Schema schema : schemas ) 549 { 550 if ( !load( clonedRegistries, schema ) && ( ! errors.isEmpty() ) ) 551 { 552 return false; 553 } 554 } 555 556 // Build the cross references 557 errors = clonedRegistries.buildReferences(); 558 559 if ( errors.isEmpty() ) 560 { 561 // Ok no errors. Check the registries now 562 errors = clonedRegistries.checkRefInteg(); 563 564 if ( errors.isEmpty() ) 565 { 566 // We are golden : let's apply the schema in the real registries 567 registries.setRelaxed(); 568 569 // Load the schemas 570 for ( Schema schema : schemas ) 571 { 572 load( registries, schema ); 573 574 // Update the schema dependences if needed 575 576 if ( schema.getDependencies() != null ) 577 { 578 for ( String dep : schema.getDependencies() ) 579 { 580 Set<String> deps = schemaDependences.get( dep ); 581 582 if ( deps == null ) 583 { 584 deps = new HashSet<String>(); 585 deps.add( schema.getSchemaName() ); 586 } 587 588 // Replace the dependences 589 schemaDependences.put( dep, deps ); 590 } 591 } 592 593 // add the schema to the schemaLoader 594 schemaLoader.addSchema( schema ); 595 } 596 597 // Build the cross references 598 errors = registries.buildReferences(); 599 registries.setStrict(); 600 601 loaded = true; 602 } 603 } 604 605 // clear the cloned registries 606 clonedRegistries.clear(); 607 608 return loaded; 609 } 610 611 612 /** 613 * {@inheritDoc} 614 */ 615 public boolean load( String... schemaNames ) throws Exception 616 { 617 if ( schemaNames.length == 0 ) 618 { 619 return true; 620 } 621 622 Schema[] schemas = toArray( schemaNames ); 623 624 return load( schemas ); 625 } 626 627 628 /** 629 * Load the schema in the registries. We will load everything accordingly to the two flags : 630 * - isRelaxed 631 * - disabledAccepted 632 */ 633 private boolean load( Registries registries, Schema schema ) throws Exception 634 { 635 if ( schema == null ) 636 { 637 LOG.info( "The schema is null" ); 638 return false; 639 } 640 641 // First avoid loading twice the same schema 642 if ( registries.isSchemaLoaded( schema.getSchemaName() ) ) 643 { 644 return true; 645 } 646 647 if ( schema.isDisabled() ) 648 { 649 if ( registries.isDisabledAccepted() ) 650 { 651 LOG.info( "Loading {} disbaled schema: \n{}", schema.getSchemaName(), schema ); 652 653 registries.schemaLoaded( schema ); 654 addSchemaObjects( schema, registries ); 655 } 656 else 657 { 658 return false; 659 } 660 } 661 else 662 { 663 LOG.info( "Loading {} enabled schema: \n{}", schema.getSchemaName(), schema ); 664 665 // Check that the dependencies, if any, are correct 666 if ( schema.getDependencies() != null ) 667 { 668 for ( String dependency : schema.getDependencies() ) 669 { 670 if ( schemaLoader.getSchema( dependency ) == null ) 671 { 672 // The dependency has not been loaded. 673 String msg = I18n.err( I18n.ERR_11002, schema.getSchemaName() ); 674 LOG.info( msg ); 675 Throwable error = new LdapProtocolErrorException( msg ); 676 errors.add( error ); 677 return false; 678 } 679 } 680 } 681 682 registries.schemaLoaded( schema ); 683 addSchemaObjects( schema, registries ); 684 } 685 686 return true; 687 } 688 689 690 /** 691 * Unload the schema from the registries. We will unload everything accordingly to the two flags : 692 * - isRelaxed 693 * - disabledAccepted 694 */ 695 private boolean unload( Registries registries, Schema schema ) throws Exception 696 { 697 if ( schema == null ) 698 { 699 LOG.info( "The schema is null" ); 700 return false; 701 } 702 703 // First avoid unloading twice the same schema 704 if ( !registries.isSchemaLoaded( schema.getSchemaName() ) ) 705 { 706 return true; 707 } 708 709 if ( schema.isEnabled() ) 710 { 711 LOG.info( "Unloading {} schema: \n{}", schema.getSchemaName(), schema ); 712 713 deleteSchemaObjects( schema, registries ); 714 registries.schemaUnloaded( schema ); 715 } 716 717 return true; 718 } 719 720 721 /** 722 * Add all the Schema's AttributeTypes 723 */ 724 private void addAttributeTypes( Schema schema, Registries registries ) throws Exception 725 { 726 for ( Entry entry : schemaLoader.loadAttributeTypes( schema ) ) 727 { 728 AttributeType attributeType = factory.getAttributeType( this, entry, registries, schema.getSchemaName() ); 729 730 addSchemaObject( registries, attributeType, schema ); 731 } 732 } 733 734 735 /** 736 * Add all the Schema's comparators 737 */ 738 private void addComparators( Schema schema, Registries registries ) throws Exception 739 { 740 for ( Entry entry : schemaLoader.loadComparators( schema ) ) 741 { 742 LdapComparator<?> comparator = factory.getLdapComparator( this, entry, registries, schema.getSchemaName() ); 743 744 addSchemaObject( registries, comparator, schema ); 745 } 746 } 747 748 749 /** 750 * Add all the Schema's DitContentRules 751 */ 752 private void addDitContentRules( Schema schema, Registries registries ) throws Exception 753 { 754 for ( Entry entry : schemaLoader.loadDitContentRules( schema ) ) 755 { 756 throw new NotImplementedException( I18n.err( I18n.ERR_11003 ) ); 757 } 758 } 759 760 761 /** 762 * Add all the Schema's DitStructureRules 763 */ 764 private void addDitStructureRules( Schema schema, Registries registries ) throws Exception 765 { 766 for ( Entry entry : schemaLoader.loadDitStructureRules( schema ) ) 767 { 768 throw new NotImplementedException( I18n.err( I18n.ERR_11004 ) ); 769 } 770 } 771 772 773 /** 774 * Add all the Schema's MatchingRules 775 */ 776 private void addMatchingRules( Schema schema, Registries registries ) throws Exception 777 { 778 for ( Entry entry : schemaLoader.loadMatchingRules( schema ) ) 779 { 780 MatchingRule matchingRule = factory.getMatchingRule( this, entry, registries, schema.getSchemaName() ); 781 782 addSchemaObject( registries, matchingRule, schema ); 783 } 784 } 785 786 787 /** 788 * Add all the Schema's MatchingRuleUses 789 */ 790 private void addMatchingRuleUses( Schema schema, Registries registries ) throws Exception 791 { 792 for ( Entry entry : schemaLoader.loadMatchingRuleUses( schema ) ) 793 { 794 throw new NotImplementedException( I18n.err( I18n.ERR_11005 ) ); 795 } 796 } 797 798 799 /** 800 * Add all the Schema's NameForms 801 */ 802 private void addNameForms( Schema schema, Registries registries ) throws Exception 803 { 804 for ( Entry entry : schemaLoader.loadNameForms( schema ) ) 805 { 806 throw new NotImplementedException( I18n.err( I18n.ERR_11006 ) ); 807 } 808 } 809 810 811 /** 812 * Add all the Schema's Normalizers 813 */ 814 private void addNormalizers( Schema schema, Registries registries ) throws Exception 815 { 816 for ( Entry entry : schemaLoader.loadNormalizers( schema ) ) 817 { 818 Normalizer normalizer = factory.getNormalizer( this, entry, registries, schema.getSchemaName() ); 819 820 addSchemaObject( registries, normalizer, schema ); 821 } 822 } 823 824 825 /** 826 * Add all the Schema's ObjectClasses 827 */ 828 private void addObjectClasses( Schema schema, Registries registries ) throws Exception 829 { 830 for ( Entry entry : schemaLoader.loadObjectClasses( schema ) ) 831 { 832 ObjectClass objectClass = factory.getObjectClass( this, entry, registries, schema.getSchemaName() ); 833 834 addSchemaObject( registries, objectClass, schema ); 835 } 836 } 837 838 839 /** 840 * Add all the Schema's Syntaxes 841 */ 842 private void addSyntaxes( Schema schema, Registries registries ) throws Exception 843 { 844 for ( Entry entry : schemaLoader.loadSyntaxes( schema ) ) 845 { 846 LdapSyntax syntax = factory.getSyntax( this, entry, registries, schema.getSchemaName() ); 847 848 addSchemaObject( registries, syntax, schema ); 849 } 850 } 851 852 853 /**Add 854 * Register all the Schema's SyntaxCheckers 855 */ 856 private void addSyntaxCheckers( Schema schema, Registries registries ) throws Exception 857 { 858 for ( Entry entry : schemaLoader.loadSyntaxCheckers( schema ) ) 859 { 860 SyntaxChecker syntaxChecker = factory.getSyntaxChecker( this, entry, registries, schema.getSchemaName() ); 861 862 addSchemaObject( registries, syntaxChecker, schema ); 863 } 864 } 865 866 867 /** 868 * Add the schemaObject into the registries. 869 * 870 * @param registries The Registries 871 * @param schemaObject The SchemaObject containing the SchemaObject description 872 * @param schema The associated schema 873 * @return the created schemaObject instance 874 * @throws Exception If the registering failed 875 */ 876 private SchemaObject addSchemaObject( Registries registries, SchemaObject schemaObject, Schema schema ) 877 throws Exception 878 { 879 if ( registries.isRelaxed() ) 880 { 881 if ( registries.isDisabledAccepted() || ( schema.isEnabled() && schemaObject.isEnabled() ) ) 882 { 883 registries.add( errors, schemaObject ); 884 } 885 else 886 { 887 errors.add( new Throwable() ); 888 } 889 } 890 else 891 { 892 if ( schema.isEnabled() && schemaObject.isEnabled() ) 893 { 894 registries.add( errors, schemaObject ); 895 } 896 else 897 { 898 errors.add( new Throwable() ); 899 } 900 } 901 902 return schemaObject; 903 } 904 905 906 /** 907 * {@inheritDoc} 908 */ 909 public boolean loadAllEnabled() throws Exception 910 { 911 Schema[] schemas = schemaLoader.getAllEnabled().toArray( new Schema[0] ); 912 913 return loadWithDeps( schemas ); 914 } 915 916 917 /** 918 * {@inheritDoc} 919 */ 920 public boolean loadAllEnabledRelaxed() throws Exception 921 { 922 // TODO Auto-generated method stub 923 return false; 924 } 925 926 927 /** 928 * {@inheritDoc} 929 */ 930 public boolean loadDisabled( Schema... schemas ) throws Exception 931 { 932 // Work on a cloned and relaxed registries 933 Registries clonedRegistries = cloneRegistries(); 934 935 // Accept the disabled schemas 936 clonedRegistries.setDisabledAccepted( true ); 937 938 // Load the schemas 939 for ( Schema schema : schemas ) 940 { 941 // Enable the Schema object before loading it 942 schema.enable(); 943 load( clonedRegistries, schema ); 944 } 945 946 clonedRegistries.clear(); 947 948 // Apply the change to the correct registries if no errors 949 if ( errors.size() == 0 ) 950 { 951 // No error, we can enable the schema in the real registries 952 for ( Schema schema : schemas ) 953 { 954 load( registries, schema ); 955 } 956 957 return true; 958 } 959 else 960 { 961 for ( Schema schema : schemas ) 962 { 963 schema.disable(); 964 } 965 966 return false; 967 } 968 } 969 970 971 /** 972 * {@inheritDoc} 973 */ 974 public boolean loadDisabled( String... schemaNames ) throws Exception 975 { 976 Schema[] schemas = toArray( schemaNames ); 977 978 return loadDisabled( schemas ); 979 } 980 981 982 /** 983 * {@inheritDoc} 984 */ 985 public boolean loadRelaxed( Schema... schemas ) throws Exception 986 { 987 // TODO Auto-generated method stub 988 return false; 989 } 990 991 992 /** 993 * {@inheritDoc} 994 */ 995 public boolean loadRelaxed( String... schemaNames ) throws Exception 996 { 997 Schema[] schemas = toArray( schemaNames ); 998 return false; 999 } 1000 1001 1002 /** 1003 * {@inheritDoc} 1004 */ 1005 public boolean loadWithDeps( Schema... schemas ) throws Exception 1006 { 1007 boolean loaded = false; 1008 1009 // Reset the errors if not null 1010 if ( errors != null ) 1011 { 1012 errors.clear(); 1013 } 1014 1015 // Work on a cloned and relaxed registries 1016 Registries clonedRegistries = cloneRegistries(); 1017 clonedRegistries.setRelaxed(); 1018 1019 // Load the schemas 1020 for ( Schema schema : schemas ) 1021 { 1022 loadDepsFirst( clonedRegistries, schema ); 1023 } 1024 1025 // Build the cross references 1026 errors = clonedRegistries.buildReferences(); 1027 1028 if ( errors.isEmpty() ) 1029 { 1030 // Ok no errors. Check the registries now 1031 errors = clonedRegistries.checkRefInteg(); 1032 1033 if ( errors.isEmpty() ) 1034 { 1035 // We are golden : let's apply the schema in the real registries 1036 registries.setRelaxed(); 1037 1038 // Load the schemas 1039 for ( Schema schema : schemas ) 1040 { 1041 loadDepsFirst( registries, schema ); 1042 } 1043 1044 // Build the cross references 1045 errors = registries.buildReferences(); 1046 registries.setStrict(); 1047 1048 loaded = true; 1049 } 1050 } 1051 1052 // clear the cloned registries 1053 clonedRegistries.clear(); 1054 1055 return loaded; 1056 } 1057 1058 1059 /** 1060 * {@inheritDoc} 1061 */ 1062 public boolean loadWithDeps( String... schemas ) throws Exception 1063 { 1064 return loadWithDeps( toArray( schemas ) ); 1065 } 1066 1067 1068 /** 1069 * Recursive method which loads schema's with their dependent schemas first 1070 * and tracks what schemas it has seen so the recursion does not go out of 1071 * control with dependency cycle detection. 1072 * 1073 * @param registries The Registries in which the schemas will be loaded 1074 * @param schema the current schema we are attempting to load 1075 * @throws Exception if there is a cycle detected and/or another 1076 * failure results while loading, producing and or registering schema objects 1077 */ 1078 private final void loadDepsFirst( Registries registries, Schema schema ) throws Exception 1079 { 1080 if ( schema == null ) 1081 { 1082 LOG.info( "The schema is null" ); 1083 return; 1084 } 1085 1086 if ( schema.isDisabled() && !registries.isDisabledAccepted() ) 1087 { 1088 LOG.info( "The schema is disabled and the registries does not accepted disabled schema" ); 1089 return; 1090 } 1091 1092 String schemaName = schema.getSchemaName(); 1093 1094 if ( registries.isSchemaLoaded( schemaName ) ) 1095 { 1096 LOG.info( "{} schema has already been loaded" + schema.getSchemaName() ); 1097 return; 1098 } 1099 1100 String[] deps = schema.getDependencies(); 1101 1102 // if no deps then load this guy and return 1103 if ( ( deps == null ) || ( deps.length == 0 ) ) 1104 { 1105 load( registries, schema ); 1106 1107 return; 1108 } 1109 1110 /* 1111 * We got deps and need to load them before this schema. We go through 1112 * all deps loading them with their deps first if they have not been 1113 * loaded. 1114 */ 1115 for ( String depName : deps ) 1116 { 1117 if ( registries.isSchemaLoaded( schemaName ) ) 1118 { 1119 // The schema is already loaded. Loop on the next schema 1120 continue; 1121 } 1122 else 1123 { 1124 // Call recursively this method 1125 Schema schemaDep = schemaLoader.getSchema( depName ); 1126 loadDepsFirst( registries, schemaDep ); 1127 } 1128 } 1129 1130 // Now load the current schema 1131 load( registries, schema ); 1132 } 1133 1134 1135 /** 1136 * {@inheritDoc} 1137 */ 1138 public boolean loadWithDepsRelaxed( Schema... schemas ) throws Exception 1139 { 1140 // TODO Auto-generated method stub 1141 return false; 1142 } 1143 1144 1145 /** 1146 * {@inheritDoc} 1147 */ 1148 public boolean loadWithDepsRelaxed( String... schemas ) throws Exception 1149 { 1150 // TODO Auto-generated method stub 1151 return false; 1152 } 1153 1154 1155 /** 1156 * {@inheritDoc} 1157 */ 1158 public void setRegistries( Registries registries ) 1159 { 1160 // TODO Auto-generated method stub 1161 1162 } 1163 1164 1165 /** 1166 * {@inheritDoc} 1167 */ 1168 public boolean unload( Schema... schemas ) throws Exception 1169 { 1170 boolean unloaded = false; 1171 1172 // Reset the errors if not null 1173 if ( errors != null ) 1174 { 1175 errors.clear(); 1176 } 1177 1178 // Work on a cloned and relaxed registries 1179 Registries clonedRegistries = cloneRegistries(); 1180 clonedRegistries.setRelaxed(); 1181 1182 // Load the schemas 1183 for ( Schema schema : schemas ) 1184 { 1185 unload( clonedRegistries, schema ); 1186 } 1187 1188 // Build the cross references 1189 errors = clonedRegistries.buildReferences(); 1190 1191 if ( errors.isEmpty() ) 1192 { 1193 // Ok no errors. Check the registries now 1194 errors = clonedRegistries.checkRefInteg(); 1195 1196 if ( errors.isEmpty() ) 1197 { 1198 // We are golden : let's apply the schema in the real registries 1199 registries.setRelaxed(); 1200 1201 // Load the schemas 1202 for ( Schema schema : schemas ) 1203 { 1204 unload( registries, schema ); 1205 1206 // Update the schema dependences 1207 for ( String dep : schema.getDependencies() ) 1208 { 1209 Set<String> deps = schemaDependences.get( dep ); 1210 1211 if ( deps != null ) 1212 { 1213 deps.remove( schema.getSchemaName() ); 1214 } 1215 } 1216 1217 schemaLoader.removeSchema( schema ); 1218 } 1219 1220 // Build the cross references 1221 errors = registries.buildReferences(); 1222 registries.setStrict(); 1223 1224 unloaded = true; 1225 } 1226 } 1227 1228 // clear the cloned registries 1229 clonedRegistries.clear(); 1230 1231 return unloaded; 1232 } 1233 1234 1235 /** 1236 * {@inheritDoc} 1237 */ 1238 public boolean unload( String... schemaNames ) throws Exception 1239 { 1240 Schema[] schemas = toArray( schemaNames ); 1241 1242 return unload( schemas ); 1243 } 1244 1245 1246 /** 1247 * {@inheritDoc} 1248 */ 1249 public boolean verify( Schema... schemas ) throws Exception 1250 { 1251 // Work on a cloned registries 1252 Registries clonedRegistries = cloneRegistries(); 1253 1254 // Loop on all the schemas 1255 for ( Schema schema : schemas ) 1256 { 1257 try 1258 { 1259 // Inject the schema 1260 boolean loaded = load( clonedRegistries, schema ); 1261 1262 if ( !loaded ) 1263 { 1264 // We got an error : exit 1265 clonedRegistries.clear(); 1266 return false; 1267 } 1268 1269 // Now, check the registries 1270 List<Throwable> errors = clonedRegistries.checkRefInteg(); 1271 1272 if ( errors.size() != 0 ) 1273 { 1274 // We got an error : exit 1275 clonedRegistries.clear(); 1276 return false; 1277 } 1278 } 1279 catch ( Exception e ) 1280 { 1281 // We got an error : exit 1282 clonedRegistries.clear(); 1283 return false; 1284 } 1285 } 1286 1287 // We can now delete the cloned registries before exiting 1288 clonedRegistries.clear(); 1289 1290 return true; 1291 } 1292 1293 1294 /** 1295 * {@inheritDoc} 1296 */ 1297 public boolean verify( String... schemas ) throws Exception 1298 { 1299 return verify( toArray( schemas ) ); 1300 } 1301 1302 1303 /** 1304 * {@inheritDoc} 1305 */ 1306 public void setSchemaLoader( SchemaLoader schemaLoader ) 1307 { 1308 this.schemaLoader = schemaLoader; 1309 } 1310 1311 1312 /** 1313 * @return the namingContext 1314 */ 1315 public DN getNamingContext() 1316 { 1317 return namingContext; 1318 } 1319 1320 1321 /** 1322 * Initializes the SchemaService 1323 * 1324 * @throws Exception If the initialization fails 1325 */ 1326 public void initialize() throws Exception 1327 { 1328 try 1329 { 1330 schemaModificationAttributesDN = new DN( SchemaConstants.SCHEMA_MODIFICATIONS_DN ); 1331 schemaModificationAttributesDN 1332 .normalize( getRegistries().getAttributeTypeRegistry().getNormalizerMapping() ); 1333 } 1334 catch ( LdapInvalidDnException e ) 1335 { 1336 throw new RuntimeException( e ); 1337 } 1338 } 1339 1340 1341 /** 1342 * {@inheritDoc} 1343 */ 1344 public SchemaLoader getLoader() 1345 { 1346 return schemaLoader; 1347 } 1348 1349 1350 //----------------------------------------------------------------------------------- 1351 // Immutable accessors 1352 //----------------------------------------------------------------------------------- 1353 /** 1354 * {@inheritDoc} 1355 */ 1356 public AttributeTypeRegistry getAttributeTypeRegistry() 1357 { 1358 return new ImmutableAttributeTypeRegistry( registries.getAttributeTypeRegistry() ); 1359 } 1360 1361 1362 /** 1363 * {@inheritDoc} 1364 */ 1365 public ComparatorRegistry getComparatorRegistry() 1366 { 1367 return new ImmutableComparatorRegistry( registries.getComparatorRegistry() ); 1368 } 1369 1370 1371 /** 1372 * {@inheritDoc} 1373 */ 1374 public DITContentRuleRegistry getDITContentRuleRegistry() 1375 { 1376 return new ImmutableDITContentRuleRegistry( registries.getDitContentRuleRegistry() ); 1377 } 1378 1379 1380 /** 1381 * {@inheritDoc} 1382 */ 1383 public DITStructureRuleRegistry getDITStructureRuleRegistry() 1384 { 1385 return new ImmutableDITStructureRuleRegistry( registries.getDitStructureRuleRegistry() ); 1386 } 1387 1388 1389 /** 1390 * {@inheritDoc} 1391 */ 1392 public MatchingRuleRegistry getMatchingRuleRegistry() 1393 { 1394 return new ImmutableMatchingRuleRegistry( registries.getMatchingRuleRegistry() ); 1395 } 1396 1397 1398 /** 1399 * {@inheritDoc} 1400 */ 1401 public MatchingRuleUseRegistry getMatchingRuleUseRegistry() 1402 { 1403 return new ImmutableMatchingRuleUseRegistry( registries.getMatchingRuleUseRegistry() ); 1404 } 1405 1406 1407 /** 1408 * {@inheritDoc} 1409 */ 1410 public NameFormRegistry getNameFormRegistry() 1411 { 1412 return new ImmutableNameFormRegistry( registries.getNameFormRegistry() ); 1413 } 1414 1415 1416 /** 1417 * {@inheritDoc} 1418 */ 1419 public NormalizerRegistry getNormalizerRegistry() 1420 { 1421 return new ImmutableNormalizerRegistry( registries.getNormalizerRegistry() ); 1422 } 1423 1424 1425 /** 1426 * {@inheritDoc} 1427 */ 1428 public ObjectClassRegistry getObjectClassRegistry() 1429 { 1430 return new ImmutableObjectClassRegistry( registries.getObjectClassRegistry() ); 1431 } 1432 1433 1434 /** 1435 * {@inheritDoc} 1436 */ 1437 public LdapSyntaxRegistry getLdapSyntaxRegistry() 1438 { 1439 return new ImmutableLdapSyntaxRegistry( registries.getLdapSyntaxRegistry() ); 1440 } 1441 1442 1443 /** 1444 * {@inheritDoc} 1445 */ 1446 public SyntaxCheckerRegistry getSyntaxCheckerRegistry() 1447 { 1448 return new ImmutableSyntaxCheckerRegistry( registries.getSyntaxCheckerRegistry() ); 1449 } 1450 1451 1452 /** 1453 * {@inheritDoc} 1454 */ 1455 public AttributeType lookupAttributeTypeRegistry( String oid ) throws LdapException 1456 { 1457 return registries.getAttributeTypeRegistry().lookup( StringTools.toLowerCase( oid ).trim() ); 1458 } 1459 1460 1461 /** 1462 * {@inheritDoc} 1463 */ 1464 public LdapComparator<?> lookupComparatorRegistry( String oid ) throws LdapException 1465 { 1466 return registries.getComparatorRegistry().lookup( oid ); 1467 } 1468 1469 1470 /** 1471 * {@inheritDoc} 1472 */ 1473 public MatchingRule lookupMatchingRuleRegistry( String oid ) throws LdapException 1474 { 1475 return registries.getMatchingRuleRegistry().lookup( StringTools.toLowerCase( oid ).trim() ); 1476 } 1477 1478 1479 /** 1480 * {@inheritDoc} 1481 */ 1482 public Normalizer lookupNormalizerRegistry( String oid ) throws LdapException 1483 { 1484 return registries.getNormalizerRegistry().lookup( oid ); 1485 } 1486 1487 1488 /** 1489 * {@inheritDoc} 1490 */ 1491 public ObjectClass lookupObjectClassRegistry( String oid ) throws LdapException 1492 { 1493 return registries.getObjectClassRegistry().lookup( StringTools.toLowerCase( oid ).trim() ); 1494 } 1495 1496 1497 /** 1498 * {@inheritDoc} 1499 */ 1500 public LdapSyntax lookupLdapSyntaxRegistry( String oid ) throws LdapException 1501 { 1502 return registries.getLdapSyntaxRegistry().lookup( StringTools.toLowerCase( oid ).trim() ); 1503 } 1504 1505 1506 /** 1507 * {@inheritDoc} 1508 */ 1509 public SyntaxChecker lookupSyntaxCheckerRegistry( String oid ) throws LdapException 1510 { 1511 return registries.getSyntaxCheckerRegistry().lookup( oid ); 1512 } 1513 1514 1515 /** 1516 * Check that the given OID exists in the globalOidRegistry. 1517 */ 1518 private boolean checkOidExist( SchemaObject schemaObject ) 1519 { 1520 if ( !( schemaObject instanceof LoadableSchemaObject ) ) 1521 { 1522 return registries.getGlobalOidRegistry().contains( schemaObject.getOid() ); 1523 } 1524 1525 if ( schemaObject instanceof LdapComparator<?> ) 1526 { 1527 return registries.getComparatorRegistry().contains( schemaObject.getOid() ); 1528 } 1529 1530 if ( schemaObject instanceof SyntaxChecker ) 1531 { 1532 return registries.getSyntaxCheckerRegistry().contains( schemaObject.getOid() ); 1533 } 1534 1535 if ( schemaObject instanceof Normalizer ) 1536 { 1537 return registries.getNormalizerRegistry().contains( schemaObject.getOid() ); 1538 } 1539 1540 return false; 1541 } 1542 1543 1544 /** 1545 * Get the inner SchemaObject if it's not a C/N/SC 1546 */ 1547 private SchemaObject getSchemaObject( SchemaObject schemaObject ) throws LdapException 1548 { 1549 if ( schemaObject instanceof LoadableSchemaObject ) 1550 { 1551 return schemaObject; 1552 } 1553 else 1554 { 1555 return registries.getGlobalOidRegistry().getSchemaObject( schemaObject.getOid() ); 1556 } 1557 } 1558 1559 1560 /** 1561 * Retrieve the schema name for a specific SchemaObject, or return "other" if none is found. 1562 */ 1563 private String getSchemaName( SchemaObject schemaObject ) 1564 { 1565 String schemaName = StringTools.toLowerCase( schemaObject.getSchemaName() ); 1566 1567 if ( StringTools.isEmpty( schemaName ) ) 1568 { 1569 return MetaSchemaConstants.SCHEMA_OTHER; 1570 } 1571 1572 if ( schemaLoader.getSchema( schemaName ) == null ) 1573 { 1574 return null; 1575 } 1576 else 1577 { 1578 return schemaName; 1579 } 1580 } 1581 1582 1583 private SchemaObject copy( SchemaObject schemaObject ) 1584 { 1585 SchemaObject copy = null; 1586 1587 if ( !( schemaObject instanceof LoadableSchemaObject ) ) 1588 { 1589 copy = schemaObject.copy(); 1590 } 1591 else 1592 { 1593 // Check the schemaObject here. 1594 if ( ( ( LoadableSchemaObject ) schemaObject ).isValid() ) 1595 { 1596 copy = schemaObject; 1597 } 1598 else 1599 { 1600 // We have an invalid SchemaObject, no need to go any further 1601 Throwable error = new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM, 1602 I18n.err( I18n.ERR_11007, schemaObject.getOid() ) ); 1603 errors.add( error ); 1604 } 1605 } 1606 1607 return copy; 1608 } 1609 1610 1611 //----------------------------------------------------------------------------------- 1612 // SchemaObject operations 1613 //----------------------------------------------------------------------------------- 1614 /** 1615 * {@inheritDoc} 1616 */ 1617 public boolean add( SchemaObject schemaObject ) throws Exception 1618 { 1619 // First, clear the errors 1620 errors.clear(); 1621 1622 // Clone the schemaObject 1623 SchemaObject copy = copy( schemaObject ); 1624 1625 if ( copy == null ) 1626 { 1627 return false; 1628 } 1629 1630 if ( registries.isRelaxed() ) 1631 { 1632 // Apply the addition right away 1633 registries.add( errors, copy ); 1634 1635 return errors.isEmpty(); 1636 } 1637 else 1638 { 1639 // Clone, apply, check, then apply again if ok 1640 // The new schemaObject's OID must not already exist 1641 if ( checkOidExist( copy ) ) 1642 { 1643 Throwable error = new LdapProtocolErrorException( 1644 I18n.err( I18n.ERR_11008, schemaObject.getOid() ) ); 1645 errors.add( error ); 1646 1647 return false; 1648 } 1649 1650 // Build the new AttributeType from the given entry 1651 String schemaName = getSchemaName( copy ); 1652 1653 if ( schemaName == null ) 1654 { 1655 // The schema associated with the SchemzaObject does not exist. This is not valid. 1656 Throwable error = new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM, I18n.err( I18n.ERR_11009, schemaObject.getOid(), 1657 copy.getSchemaName() ) ); 1658 errors.add( error ); 1659 1660 return false; 1661 } 1662 1663 // At this point, the constructed AttributeType has not been checked against the 1664 // existing Registries. It may be broken (missing SUP, or such), it will be checked 1665 // there, if the schema and the AttributeType are both enabled. 1666 Schema schema = getLoadedSchema( schemaName ); 1667 1668 if ( schema == null ) 1669 { 1670 // The SchemaObject must be associated with an existing schema 1671 String msg = I18n.err( I18n.ERR_11010, copy.getOid() ); 1672 LOG.info( msg ); 1673 Throwable error = new LdapProtocolErrorException( msg ); 1674 errors.add( error ); 1675 return false; 1676 } 1677 1678 if ( schema.isEnabled() && copy.isEnabled() ) 1679 { 1680 // As we may break the registries, work on a cloned registries 1681 Registries clonedRegistries = registries.clone(); 1682 1683 // Inject the new SchemaObject in the cloned registries 1684 clonedRegistries.add( errors, copy ); 1685 1686 // Remove the cloned registries 1687 clonedRegistries.clear(); 1688 1689 // If we didn't get any error, apply the addition to the real retistries 1690 if ( errors.isEmpty() ) 1691 { 1692 // Copy again as the clonedRegistries clear has removed the previous copy 1693 copy = copy( schemaObject ); 1694 1695 // Apply the addition to the real registries 1696 registries.add( errors, copy ); 1697 1698 LOG.debug( "Added {} into the enabled schema {}", copy.getName(), schemaName ); 1699 1700 return true; 1701 } 1702 else 1703 { 1704 // We have some error : reject the addition and get out 1705 String msg = "Cannot add the SchemaObject " + copy.getOid() + " into the registries, " 1706 + "the resulting registries would be inconsistent :" + StringTools.listToString( errors ); 1707 LOG.info( msg ); 1708 1709 return false; 1710 } 1711 } 1712 else 1713 { 1714 // At least, we register the OID in the globalOidRegistry, and associates it with the 1715 // schema 1716 registries.associateWithSchema( errors, copy ); 1717 1718 LOG.debug( "Added {} into the disabled schema {}", copy.getName(), schemaName ); 1719 return errors.isEmpty(); 1720 } 1721 } 1722 } 1723 1724 1725 /** 1726 * {@inheritDoc} 1727 */ 1728 public boolean delete( SchemaObject schemaObject ) throws Exception 1729 { 1730 // First, clear the errors 1731 errors.clear(); 1732 1733 if ( registries.isRelaxed() ) 1734 { 1735 // Apply the addition right away 1736 registries.delete( errors, schemaObject ); 1737 1738 return errors.isEmpty(); 1739 } 1740 else 1741 { 1742 // Clone, apply, check, then apply again if ok 1743 // The new schemaObject's OID must exist 1744 if ( !checkOidExist( schemaObject ) ) 1745 { 1746 Throwable error = new LdapProtocolErrorException( 1747 I18n.err( I18n.ERR_11011, schemaObject.getOid() ) ); 1748 errors.add( error ); 1749 return false; 1750 } 1751 1752 // Get the SchemaObject to delete if it's not a LoadableSchemaObject 1753 SchemaObject toDelete = getSchemaObject( schemaObject ); 1754 1755 // First check that this SchemaObject does not have any referencing SchemaObjects 1756 Set<SchemaObjectWrapper> referencing = registries.getReferencing( toDelete ); 1757 1758 if ( ( referencing != null ) && !referencing.isEmpty() ) 1759 { 1760 String msg = I18n.err( I18n.ERR_11012, schemaObject.getOid(), StringTools.setToString( referencing ) ); 1761 1762 Throwable error = new LdapProtocolErrorException( msg ); 1763 errors.add( error ); 1764 return false; 1765 } 1766 1767 String schemaName = getSchemaName( toDelete ); 1768 1769 // At this point, the deleted AttributeType may be referenced, it will be checked 1770 // there, if the schema and the AttributeType are both enabled. 1771 Schema schema = getLoadedSchema( schemaName ); 1772 1773 if ( schema == null ) 1774 { 1775 // The SchemaObject must be associated with an existing schema 1776 String msg = I18n.err( I18n.ERR_11013, schemaObject.getOid() ); 1777 LOG.info( msg ); 1778 Throwable error = new LdapProtocolErrorException( msg ); 1779 errors.add( error ); 1780 return false; 1781 } 1782 1783 if ( schema.isEnabled() && schemaObject.isEnabled() ) 1784 { 1785 // As we may break the registries, work on a cloned registries 1786 Registries clonedRegistries = registries.clone(); 1787 1788 // Delete the SchemaObject from the cloned registries 1789 clonedRegistries.delete( errors, toDelete ); 1790 1791 // Remove the cloned registries 1792 clonedRegistries.clear(); 1793 1794 // If we didn't get any error, apply the deletion to the real retistries 1795 if ( errors.isEmpty() ) 1796 { 1797 // Apply the deletion to the real registries 1798 registries.delete( errors, toDelete ); 1799 1800 LOG.debug( "Removed {} from the enabled schema {}", toDelete.getName(), schemaName ); 1801 1802 return true; 1803 } 1804 else 1805 { 1806 // We have some error : reject the deletion and get out 1807 String msg = "Cannot delete the SchemaObject " + schemaObject.getOid() + " from the registries, " 1808 + "the resulting registries would be inconsistent :" + StringTools.listToString( errors ); 1809 LOG.info( msg ); 1810 1811 return false; 1812 } 1813 } 1814 else 1815 { 1816 // At least, we register the OID in the globalOidRegistry, and associates it with the 1817 // schema 1818 registries.associateWithSchema( errors, schemaObject ); 1819 1820 LOG.debug( "Removed {} from the disabled schema {}", schemaObject.getName(), schemaName ); 1821 return errors.isEmpty(); 1822 } 1823 } 1824 } 1825 1826 1827 /** 1828 * {@inheritDoc} 1829 */ 1830 public Map<String, OidNormalizer> getNormalizerMapping() 1831 { 1832 return registries.getAttributeTypeRegistry().getNormalizerMapping(); 1833 } 1834 1835 1836 /** 1837 * {@inheritDoc} 1838 */ 1839 public OidRegistry getGlobalOidRegistry() 1840 { 1841 return registries.getGlobalOidRegistry(); 1842 } 1843 1844 1845 /** 1846 * {@inheritDoc} 1847 */ 1848 public Schema getLoadedSchema( String schemaName ) 1849 { 1850 return schemaLoader.getSchema( schemaName ); 1851 } 1852 1853 1854 /** 1855 * {@inheritDoc} 1856 */ 1857 public boolean isSchemaLoaded( String schemaName ) 1858 { 1859 try 1860 { 1861 Schema schema = schemaLoader.getSchema( schemaName ); 1862 return schema != null; 1863 } 1864 catch ( Exception e ) 1865 { 1866 return false; 1867 } 1868 } 1869 1870 1871 /** 1872 * {@inheritDoc} 1873 */ 1874 public SchemaObject unregisterAttributeType( String attributeTypeOid ) throws LdapException 1875 { 1876 return registries.getAttributeTypeRegistry().unregister( attributeTypeOid ); 1877 } 1878 1879 1880 /** 1881 * {@inheritDoc} 1882 */ 1883 public SchemaObject unregisterComparator( String comparatorOid ) throws LdapException 1884 { 1885 return registries.getComparatorRegistry().unregister( comparatorOid ); 1886 } 1887 1888 1889 /** 1890 * {@inheritDoc} 1891 */ 1892 public SchemaObject unregisterDitControlRule( String ditControlRuleOid ) throws LdapException 1893 { 1894 return registries.getDitContentRuleRegistry().unregister( ditControlRuleOid ); 1895 } 1896 1897 1898 /** 1899 * {@inheritDoc} 1900 */ 1901 public SchemaObject unregisterDitStructureRule( String ditStructureRuleOid ) throws LdapException 1902 { 1903 return registries.getDitStructureRuleRegistry().unregister( ditStructureRuleOid ); 1904 } 1905 1906 1907 /** 1908 * {@inheritDoc} 1909 */ 1910 public SchemaObject unregisterLdapSyntax( String ldapSyntaxOid ) throws LdapException 1911 { 1912 return registries.getLdapSyntaxRegistry().unregister( ldapSyntaxOid ); 1913 } 1914 1915 1916 /** 1917 * {@inheritDoc} 1918 */ 1919 public SchemaObject unregisterMatchingRule( String matchingRuleOid ) throws LdapException 1920 { 1921 return registries.getMatchingRuleRegistry().unregister( matchingRuleOid ); 1922 } 1923 1924 1925 /** 1926 * {@inheritDoc} 1927 */ 1928 public SchemaObject unregisterMatchingRuleUse( String matchingRuleUseOid ) throws LdapException 1929 { 1930 return registries.getMatchingRuleUseRegistry().unregister( matchingRuleUseOid ); 1931 } 1932 1933 1934 /** 1935 * {@inheritDoc} 1936 */ 1937 public SchemaObject unregisterNameForm( String nameFormOid ) throws LdapException 1938 { 1939 return registries.getNameFormRegistry().unregister( nameFormOid ); 1940 } 1941 1942 1943 /** 1944 * {@inheritDoc} 1945 */ 1946 public SchemaObject unregisterNormalizer( String normalizerOid ) throws LdapException 1947 { 1948 return registries.getNormalizerRegistry().unregister( normalizerOid ); 1949 } 1950 1951 1952 /** 1953 * {@inheritDoc} 1954 */ 1955 public SchemaObject unregisterObjectClass( String objectClassOid ) throws LdapException 1956 { 1957 return registries.getObjectClassRegistry().unregister( objectClassOid ); 1958 } 1959 1960 1961 /** 1962 * {@inheritDoc} 1963 */ 1964 public SchemaObject unregisterSyntaxChecker( String syntaxCheckerOid ) throws LdapException 1965 { 1966 return registries.getSyntaxCheckerRegistry().unregister( syntaxCheckerOid ); 1967 } 1968 1969 1970 /** 1971 * Tells if the SchemaManager is permissive or if it must be checked 1972 * against inconsistencies. 1973 * 1974 * @return True if SchemaObjects can be added even if they break the consistency 1975 */ 1976 public boolean isRelaxed() 1977 { 1978 return isRelaxed; 1979 } 1980 1981 1982 /** 1983 * Tells if the SchemaManager is strict. 1984 * 1985 * @return True if SchemaObjects cannot be added if they break the consistency 1986 */ 1987 public boolean isStrict() 1988 { 1989 return !isRelaxed; 1990 } 1991 1992 1993 /** 1994 * {@inheritDoc} 1995 */ 1996 public Set<String> listDependentSchemaNames( String schemaName ) 1997 { 1998 return schemaDependences.get( schemaName ); 1999 } 2000 2001 2002 /** 2003 * Change the SchemaManager to a relaxed mode, where invalid SchemaObjects 2004 * can be registered. 2005 */ 2006 public void setRelaxed() 2007 { 2008 isRelaxed = RELAXED; 2009 } 2010 2011 2012 /** 2013 * Change the SchemaManager to a strict mode, where invalid SchemaObjects 2014 * cannot be registered. 2015 */ 2016 public void setStrict() 2017 { 2018 isRelaxed = STRICT; 2019 } 2020 2021 2022 /** 2023 * {@inheritDoc} 2024 */ 2025 public boolean isDisabled( String schemaName ) 2026 { 2027 Schema schema = registries.getLoadedSchema( schemaName ); 2028 2029 return ( schema != null ) && schema.isDisabled(); 2030 } 2031 2032 2033 /** 2034 * {@inheritDoc} 2035 */ 2036 public boolean isDisabled( Schema schema ) 2037 { 2038 return ( schema != null ) && schema.isDisabled(); 2039 } 2040 2041 2042 /** 2043 * {@inheritDoc} 2044 */ 2045 public boolean isEnabled( String schemaName ) 2046 { 2047 Schema schema = registries.getLoadedSchema( schemaName ); 2048 2049 return ( schema != null ) && schema.isEnabled(); 2050 } 2051 2052 2053 /** 2054 * {@inheritDoc} 2055 */ 2056 public boolean isEnabled( Schema schema ) 2057 { 2058 return ( schema != null ) && schema.isEnabled(); 2059 } 2060 }