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.shared.ldap.model.schema.registries; 021 022 023import java.util.ArrayList; 024import java.util.Collection; 025import java.util.HashMap; 026import java.util.HashSet; 027import java.util.List; 028import java.util.Map; 029import java.util.Set; 030 031import org.apache.directory.shared.i18n.I18n; 032import org.apache.directory.shared.ldap.model.constants.MetaSchemaConstants; 033import org.apache.directory.shared.ldap.model.constants.SchemaConstants; 034import org.apache.directory.shared.ldap.model.entry.Entry; 035import org.apache.directory.shared.ldap.model.entry.Attribute; 036import org.apache.directory.shared.ldap.model.entry.Value; 037import org.apache.directory.shared.util.StringConstants; 038import org.apache.directory.shared.util.Strings; 039 040 041/** 042 * An abstract class with a utility method and setListener() implemented. 043 * 044 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 045 */ 046public abstract class AbstractSchemaLoader implements SchemaLoader 047{ 048 049 /** The listener. */ 050 protected SchemaLoaderListener listener; 051 052 /** 053 * A map of all available schema names to schema objects. This map is 054 * populated when this class is created with all the schemas present in 055 * the LDIF based schema repository. 056 */ 057 protected final Map<String, Schema> schemaMap = new LowerCaseKeyMap(); 058 059 /** 060 * a map implementation which converts the keys to lower case before inserting 061 */ 062 private static class LowerCaseKeyMap extends HashMap<String,Schema> 063 { 064 private static final long serialVersionUID = 1L; 065 066 @Override 067 public Schema put( String key, Schema value ) 068 { 069 return super.put( Strings.lowerCase(key), value ); 070 } 071 072 @Override 073 public void putAll( Map<? extends String, ? extends Schema> map ) 074 { 075 for( Map.Entry<? extends String, ? extends Schema> e : map.entrySet() ) 076 { 077 put( e.getKey(), e.getValue() ); 078 } 079 } 080 } 081 082 /** 083 * {@inheritDoc} 084 */ 085 public void setListener( SchemaLoaderListener listener ) 086 { 087 this.listener = listener; 088 } 089 090 091 /** 092 * Notify listener or registries. 093 * 094 * @param schema the schema 095 * @param registries the registries 096 */ 097 protected final void notifyListenerOrRegistries( Schema schema, Registries registries ) 098 { 099 if ( listener != null ) 100 { 101 listener.schemaLoaded( schema ); 102 } 103 104 if ( registries != listener ) 105 { 106 registries.schemaLoaded( schema ); 107 } 108 } 109 110 111 /** 112 * {@inheritDoc} 113 */ 114 public final Collection<Schema> getAllEnabled() throws Exception 115 { 116 Collection<Schema> enabledSchemas = new ArrayList<Schema>(); 117 118 for ( Schema schema : schemaMap.values() ) 119 { 120 if ( schema.isEnabled() ) 121 { 122 enabledSchemas.add( schema ); 123 } 124 } 125 126 return enabledSchemas; 127 } 128 129 130 /** 131 * {@inheritDoc} 132 */ 133 public final Collection<Schema> getAllSchemas() throws Exception 134 { 135 return schemaMap.values(); 136 } 137 138 139 /** 140 * {@inheritDoc} 141 */ 142 public Schema getSchema( String schemaName ) 143 { 144 return schemaMap.get( Strings.toLowerCase(schemaName) ); 145 } 146 147 148 /** 149 * {@inheritDoc} 150 */ 151 public void addSchema( Schema schema ) 152 { 153 schemaMap.put( schema.getSchemaName(), schema ); 154 } 155 156 157 /** 158 * {@inheritDoc} 159 */ 160 public void removeSchema( Schema schema ) 161 { 162 schemaMap.remove( Strings.toLowerCase(schema.getSchemaName()) ); 163 } 164 165 166 /** 167 * Gets the schema. 168 * 169 * @param entry the entry 170 * @return the schema 171 * @throws Exception the exception 172 */ 173 protected Schema getSchema( Entry entry ) throws Exception 174 { 175 if ( entry == null ) 176 { 177 throw new IllegalArgumentException( I18n.err( I18n.ERR_04261 ) ); 178 } 179 180 Attribute objectClasses = entry.get( SchemaConstants.OBJECT_CLASS_AT ); 181 boolean isSchema = false; 182 183 for ( Value<?> value : objectClasses ) 184 { 185 if ( MetaSchemaConstants.META_SCHEMA_OC.equalsIgnoreCase( value.getString() ) ) 186 { 187 isSchema = true; 188 break; 189 } 190 } 191 192 if ( !isSchema ) 193 { 194 return null; 195 } 196 197 String name; 198 String owner; 199 String[] dependencies = StringConstants.EMPTY_STRINGS; 200 boolean isDisabled = false; 201 202 if ( entry.get( SchemaConstants.CN_AT ) == null ) 203 { 204 throw new IllegalArgumentException( I18n.err( I18n.ERR_04262 ) ); 205 } 206 207 name = entry.get( SchemaConstants.CN_AT ).getString(); 208 209 if ( entry.get( SchemaConstants.CREATORS_NAME_AT ) == null ) 210 { 211 throw new IllegalArgumentException( "entry must have a valid " + SchemaConstants.CREATORS_NAME_AT 212 + " attribute" ); 213 } 214 215 owner = entry.get( SchemaConstants.CREATORS_NAME_AT ).getString(); 216 217 if ( entry.get( MetaSchemaConstants.M_DISABLED_AT ) != null ) 218 { 219 String value = entry.get( MetaSchemaConstants.M_DISABLED_AT ).getString(); 220 value = value.toUpperCase(); 221 isDisabled = value.equals( "TRUE" ); 222 } 223 224 if ( entry.get( MetaSchemaConstants.M_DEPENDENCIES_AT ) != null ) 225 { 226 Set<String> depsSet = new HashSet<String>(); 227 Attribute depsAttr = entry.get( MetaSchemaConstants.M_DEPENDENCIES_AT ); 228 229 for ( Value<?> value : depsAttr ) 230 { 231 depsSet.add( value.getString() ); 232 } 233 234 dependencies = depsSet.toArray( StringConstants.EMPTY_STRINGS ); 235 } 236 237 return new DefaultSchema( name, owner, dependencies, isDisabled ); 238 } 239 240 // TODO: clean commented code 241 242 /* 243 * {@inheritDoc} 244 * 245 public List<Throwable> loadWithDependencies( Registries registries, boolean check, Schema... schemas ) throws Exception 246 { 247 // Relax the controls at first 248 List<Throwable> errors = new ArrayList<Throwable>(); 249 boolean wasRelaxed = registries.isRelaxed(); 250 registries.setRelaxed( true ); 251 252 Map<String,Schema> notLoaded = new HashMap<String,Schema>(); 253 254 for ( Schema schema : schemas ) 255 { 256 if ( ! registries.isSchemaLoaded( schema.getSchemaName() ) ) 257 { 258 notLoaded.put( schema.getSchemaName(), schema ); 259 } 260 } 261 262 for ( Schema schema : notLoaded.values() ) 263 { 264 Stack<String> beenthere = new Stack<String>(); 265 loadDepsFirst( schema, beenthere, notLoaded, schema, registries ); 266 } 267 268 // At the end, check the registries if required 269 if ( check ) 270 { 271 errors = registries.checkRefInteg(); 272 } 273 274 // Restore the Registries isRelaxed flag 275 registries.setRelaxed( wasRelaxed ); 276 277 return errors; 278 } 279 280 281 /** 282 * Register the comparator contained in the given LdifEntry into the registries. 283 * 284 * @param registries The Registries 285 * @param entry The LdifEntry containing the comparator description 286 * @param schema The associated schema 287 * @throws Exception If the registering failed 288 * 289 protected LdapComparator<?> registerComparator( Registries registries, LdifEntry entry, Schema schema ) 290 throws Exception 291 { 292 return registerComparator( registries, entry.getEntry(), schema ); 293 } 294 295 296 /** 297 * Register the comparator contained in the given Entry into the registries. 298 * 299 * @param registries The Registries 300 * @param entry The Entry containing the comparator description 301 * @param schema The associated schema 302 * @throws Exception If the registering failed 303 * 304 protected LdapComparator<?> registerComparator( Registries registries, Entry entry, Schema schema ) 305 throws Exception 306 { 307 LdapComparator<?> comparator = 308 factory.getLdapComparator( entry, registries, schema.getSchemaName() ); 309 comparator.setOid( entry.get( MetaSchemaConstants.M_OID_AT ).getString() ); 310 311 if ( registries.isRelaxed() ) 312 { 313 if ( registries.acceptDisabled() ) 314 { 315 registries.register( comparator ); 316 } 317 else if ( schema.isEnabled() && comparator.isEnabled() ) 318 { 319 registries.register( comparator ); 320 } 321 } 322 else 323 { 324 if ( schema.isEnabled() && comparator.isEnabled() ) 325 { 326 registries.register( comparator ); 327 } 328 } 329 330 return comparator; 331 } 332 333 334 /** 335 * Register the SyntaxChecker contained in the given LdifEntry into the registries. 336 * 337 * @param registries The Registries 338 * @param entry The LdifEntry containing the SyntaxChecker description 339 * @param schema The associated schema 340 * @return the created SyntaxChecker instance 341 * @throws Exception If the registering failed 342 * 343 protected SyntaxChecker registerSyntaxChecker( Registries registries, LdifEntry entry, Schema schema) 344 throws Exception 345 { 346 SyntaxChecker syntaxChecker = 347 factory.getSyntaxChecker( entry.getEntry(), registries, schema.getSchemaName() ); 348 syntaxChecker.setOid( entry.get( MetaSchemaConstants.M_OID_AT ).getString() ); 349 350 if ( registries.isRelaxed() ) 351 { 352 if ( registries.acceptDisabled() ) 353 { 354 registries.register( syntaxChecker ); 355 } 356 else if ( schema.isEnabled() && syntaxChecker.isEnabled() ) 357 { 358 registries.register( syntaxChecker ); 359 } 360 } 361 else 362 { 363 if ( schema.isEnabled() && syntaxChecker.isEnabled() ) 364 { 365 registries.register( syntaxChecker ); 366 } 367 } 368 369 return syntaxChecker; 370 } 371 372 373 /** 374 * Register the Normalizer contained in the given LdifEntry into the registries. 375 * 376 * @param registries The Registries 377 * @param entry The LdifEntry containing the Normalizer description 378 * @param schema The associated schema 379 * @return the created Normalizer instance 380 * @throws Exception If the registering failed 381 * 382 protected Normalizer registerNormalizer( Registries registries, LdifEntry entry, Schema schema) 383 throws Exception 384 { 385 Normalizer normalizer = 386 factory.getNormalizer( entry.getEntry(), registries, schema.getSchemaName() ); 387 388 if ( registries.isRelaxed() ) 389 { 390 if ( registries.acceptDisabled() ) 391 { 392 registries.register( normalizer ); 393 } 394 else if ( schema.isEnabled() && normalizer.isEnabled() ) 395 { 396 registries.register( normalizer ); 397 } 398 } 399 else 400 { 401 if ( schema.isEnabled() && normalizer.isEnabled() ) 402 { 403 registries.register( normalizer ); 404 } 405 } 406 407 return normalizer; 408 } 409 410 411 /** 412 * Register the MatchingRule contained in the given LdifEntry into the registries. 413 * 414 * @param registries The Registries 415 * @param entry The LdifEntry containing the MatchingRule description 416 * @param schema The associated schema 417 * @return the created MatchingRule instance 418 * @throws Exception If the registering failed 419 * 420 protected MatchingRule registerMatchingRule( Registries registries, LdifEntry entry, Schema schema) 421 throws Exception 422 { 423 MatchingRule matchingRule = factory.getMatchingRule( 424 entry.getEntry(), registries, schema.getSchemaName() ); 425 426 if ( registries.isRelaxed() ) 427 { 428 if ( registries.acceptDisabled() ) 429 { 430 registries.register( matchingRule ); 431 } 432 else if ( schema.isEnabled() && matchingRule.isEnabled() ) 433 { 434 registries.register( matchingRule ); 435 } 436 } 437 else 438 { 439 if ( schema.isEnabled() && matchingRule.isEnabled() ) 440 { 441 registries.register( matchingRule ); 442 } 443 } 444 445 return matchingRule; 446 } 447 448 449 /** 450 * Register the Syntax contained in the given LdifEntry into the registries. 451 * 452 * @param registries The Registries 453 * @param entry The LdifEntry containing the Syntax description 454 * @param schema The associated schema 455 * @return the created Syntax instance 456 * @throws Exception If the registering failed 457 * 458 protected LdapSyntax registerSyntax( Registries registries, LdifEntry entry, Schema schema) 459 throws Exception 460 { 461 LdapSyntax syntax = factory.getSyntax( 462 entry.getEntry(), registries, schema.getSchemaName() ); 463 464 if ( registries.isRelaxed() ) 465 { 466 if ( registries.acceptDisabled() ) 467 { 468 registries.register( syntax ); 469 } 470 else if ( schema.isEnabled() && syntax.isEnabled() ) 471 { 472 registries.register( syntax ); 473 } 474 } 475 else 476 { 477 if ( schema.isEnabled() && syntax.isEnabled() ) 478 { 479 registries.register( syntax ); 480 } 481 } 482 483 return syntax; 484 } 485 486 487 /** 488 * Register the AttributeType contained in the given LdifEntry into the registries. 489 * 490 * @param registries The Registries 491 * @param entry The LdifEntry containing the AttributeType description 492 * @param schema The associated schema 493 * @return the created AttributeType instance 494 * @throws Exception If the registering failed 495 * 496 protected AttributeType registerAttributeType( Registries registries, LdifEntry entry, Schema schema ) 497 throws Exception 498 { 499 AttributeType attributeType = factory.getAttributeType( entry.getEntry(), registries, schema.getSchemaName() ); 500 501 if ( registries.isRelaxed() ) 502 { 503 if ( registries.acceptDisabled() ) 504 { 505 registries.register( attributeType ); 506 } 507 else if ( schema.isEnabled() && attributeType.isEnabled() ) 508 { 509 registries.register( attributeType ); 510 } 511 } 512 else 513 { 514 if ( schema.isEnabled() && attributeType.isEnabled() ) 515 { 516 registries.register( attributeType ); 517 } 518 } 519 520 return attributeType; 521 } 522 523 524 /** 525 * Register the MatchingRuleUse contained in the given LdifEntry into the registries. 526 * 527 * @param registries The Registries 528 * @param entry The LdifEntry containing the MatchingRuleUse description 529 * @param schema The associated schema 530 * @return the created MatchingRuleUse instance 531 * @throws Exception If the registering failed 532 * 533 protected MatchingRuleUse registerMatchingRuleUse( Registries registries, LdifEntry entry, Schema schema) 534 throws Exception 535 { 536 throw new NotImplementedException( "Need to implement factory " + 537 "method for creating a MatchingRuleUse" ); 538 } 539 540 541 /** 542 * Register the NameForm contained in the given LdifEntry into the registries. 543 * 544 * @param registries The Registries 545 * @param entry The LdifEntry containing the NameForm description 546 * @param schema The associated schema 547 * @return the created NameForm instance 548 * @throws Exception If the registering failed 549 * 550 protected NameForm registerNameForm( Registries registries, LdifEntry entry, Schema schema) 551 throws Exception 552 { 553 throw new NotImplementedException( "Need to implement factory " + 554 "method for creating a NameForm" ); 555 } 556 557 558 /** 559 * Register the DitContentRule contained in the given LdifEntry into the registries. 560 * 561 * @param registries The Registries 562 * @param entry The LdifEntry containing the DitContentRule description 563 * @param schema The associated schema 564 * @return the created DitContentRule instance 565 * @throws Exception If the registering failed 566 * 567 protected DITContentRule registerDitContentRule( Registries registries, LdifEntry entry, Schema schema) 568 throws Exception 569 { 570 throw new NotImplementedException( "Need to implement factory " + 571 "method for creating a DitContentRule" ); 572 } 573 574 575 /** 576 * Register the DitStructureRule contained in the given LdifEntry into the registries. 577 * 578 * @param registries The Registries 579 * @param entry The LdifEntry containing the DitStructureRule description 580 * @param schema The associated schema 581 * @return the created DitStructureRule instance 582 * @throws Exception If the registering failed 583 * 584 protected DITStructureRule registerDitStructureRule( Registries registries, LdifEntry entry, Schema schema) 585 throws Exception 586 { 587 throw new NotImplementedException( "Need to implement factory " + 588 "method for creating a DitStructureRule" ); 589 } 590 591 592 /** 593 * Register the ObjectClass contained in the given LdifEntry into the registries. 594 * 595 * @param registries The Registries 596 * @param entry The LdifEntry containing the ObjectClass description 597 * @param schema The associated schema 598 * @return the created ObjectClass instance 599 * @throws Exception If the registering failed 600 * 601 protected ObjectClass registerObjectClass( Registries registries, LdifEntry entry, Schema schema) 602 throws Exception 603 { 604 return registerObjectClass( registries, entry.getEntry(), schema ); 605 } 606 607 608 /** 609 * Register the ObjectClass contained in the given LdifEntry into the registries. 610 * 611 * @param registries The Registries 612 * @param entry The Entry containing the ObjectClass description 613 * @param schema The associated schema 614 * @return the created ObjectClass instance 615 * @throws Exception If the registering failed 616 * 617 protected ObjectClass registerObjectClass( Registries registries, Entry entry, Schema schema) 618 throws Exception 619 { 620 ObjectClass objectClass = factory.getObjectClass( entry, registries, schema.getSchemaName() ); 621 622 if ( registries.isRelaxed() ) 623 { 624 if ( registries.acceptDisabled() ) 625 { 626 registries.register( objectClass ); 627 } 628 else if ( schema.isEnabled() && objectClass.isEnabled() ) 629 { 630 registries.register( objectClass ); 631 } 632 } 633 else 634 { 635 if ( schema.isEnabled() && objectClass.isEnabled() ) 636 { 637 registries.register( objectClass ); 638 } 639 } 640 641 return objectClass; 642 } 643 644 645 public EntityFactory getFactory() 646 { 647 return factory; 648 } 649 */ 650 651 // TODO: is this used? 652 public Object getDao() 653 { 654 return null; 655 } 656 657 658 private Schema[] buildSchemaArray( String... schemaNames ) throws Exception 659 { 660 Schema[] schemas = new Schema[schemaNames.length]; 661 int pos = 0; 662 663 for ( String schemaName : schemaNames ) 664 { 665 schemas[pos++] = getSchema( schemaName ); 666 } 667 668 return schemas; 669 } 670 671 672 /** 673 * {@inheritDoc} 674 */ 675 public List<Entry> loadAttributeTypes( String... schemaNames ) throws Exception 676 { 677 if ( schemaNames == null ) 678 { 679 return new ArrayList<Entry>(); 680 } 681 682 return loadAttributeTypes( buildSchemaArray( schemaNames ) ); 683 } 684 685 686 /** 687 * {@inheritDoc} 688 */ 689 public List<Entry> loadComparators( String... schemaNames ) throws Exception 690 { 691 if ( schemaNames == null ) 692 { 693 return new ArrayList<Entry>(); 694 } 695 696 return loadComparators( buildSchemaArray( schemaNames ) ); 697 } 698 699 700 /** 701 * {@inheritDoc} 702 */ 703 public List<Entry> loadDitContentRules( String... schemaNames ) throws Exception 704 { 705 if ( schemaNames == null ) 706 { 707 return new ArrayList<Entry>(); 708 } 709 710 return loadDitContentRules( buildSchemaArray( schemaNames ) ); 711 } 712 713 714 /** 715 * {@inheritDoc} 716 */ 717 public List<Entry> loadDitStructureRules( String... schemaNames ) throws Exception 718 { 719 if ( schemaNames == null ) 720 { 721 return new ArrayList<Entry>(); 722 } 723 724 return loadDitStructureRules( buildSchemaArray( schemaNames ) ); 725 } 726 727 728 /** 729 * {@inheritDoc} 730 */ 731 public List<Entry> loadMatchingRules( String... schemaNames ) throws Exception 732 { 733 if ( schemaNames == null ) 734 { 735 return new ArrayList<Entry>(); 736 } 737 738 return loadMatchingRules( buildSchemaArray( schemaNames ) ); 739 } 740 741 742 /** 743 * {@inheritDoc} 744 */ 745 public List<Entry> loadMatchingRuleUses( String... schemaNames ) throws Exception 746 { 747 if ( schemaNames == null ) 748 { 749 return new ArrayList<Entry>(); 750 } 751 752 return loadMatchingRuleUses( buildSchemaArray( schemaNames ) ); 753 } 754 755 756 /** 757 * {@inheritDoc} 758 */ 759 public List<Entry> loadNameForms( String... schemaNames ) throws Exception 760 { 761 if ( schemaNames == null ) 762 { 763 return new ArrayList<Entry>(); 764 } 765 766 return loadNameForms( buildSchemaArray( schemaNames ) ); 767 } 768 769 770 /** 771 * {@inheritDoc} 772 */ 773 public List<Entry> loadNormalizers( String... schemaNames ) throws Exception 774 { 775 if ( schemaNames == null ) 776 { 777 return new ArrayList<Entry>(); 778 } 779 780 return loadNormalizers( buildSchemaArray( schemaNames ) ); 781 } 782 783 784 /** 785 * {@inheritDoc} 786 */ 787 public List<Entry> loadObjectClasses( String... schemaNames ) throws Exception 788 { 789 if ( schemaNames == null ) 790 { 791 return new ArrayList<Entry>(); 792 } 793 794 return loadObjectClasses( buildSchemaArray( schemaNames ) ); 795 } 796 797 798 /** 799 * {@inheritDoc} 800 */ 801 public List<Entry> loadSyntaxes( String... schemaNames ) throws Exception 802 { 803 if ( schemaNames == null ) 804 { 805 return new ArrayList<Entry>(); 806 } 807 808 return loadSyntaxes( buildSchemaArray( schemaNames ) ); 809 } 810 811 812 /** 813 * {@inheritDoc} 814 */ 815 public List<Entry> loadSyntaxCheckers( String... schemaNames ) throws Exception 816 { 817 if ( schemaNames == null ) 818 { 819 return new ArrayList<Entry>(); 820 } 821 822 return loadSyntaxCheckers( buildSchemaArray( schemaNames ) ); 823 } 824}