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.schemaloader; 021 022 023import java.io.File; 024import java.io.FileNotFoundException; 025import java.io.FilenameFilter; 026import java.io.IOException; 027import java.util.ArrayList; 028import java.util.List; 029 030import org.apache.directory.shared.i18n.I18n; 031import org.apache.directory.shared.ldap.model.constants.SchemaConstants; 032import org.apache.directory.shared.ldap.model.entry.Entry; 033import org.apache.directory.shared.ldap.model.exception.LdapException; 034import org.apache.directory.shared.ldap.model.ldif.LdifEntry; 035import org.apache.directory.shared.ldap.model.ldif.LdifReader; 036import org.apache.directory.shared.ldap.model.schema.registries.Schema; 037import org.apache.directory.shared.ldap.model.schema.registries.AbstractSchemaLoader; 038import org.apache.directory.shared.util.Strings; 039import org.slf4j.Logger; 040import org.slf4j.LoggerFactory; 041 042 043/** 044 * Loads schema data from LDIF files containing entries representing schema 045 * objects, using the meta schema format. 046 * 047 * This class is used only for tests. 048 * 049 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 050 */ 051public class LdifSchemaLoader extends AbstractSchemaLoader 052{ 053 /** ldif file extension used */ 054 private static final String LDIF_EXT = "ldif"; 055 056 /** ou=schema LDIF file name */ 057 private static final String OU_SCHEMA_LDIF = "ou=schema." + LDIF_EXT; 058 059 /** static class logger */ 060 private static final Logger LOG = LoggerFactory.getLogger( LdifSchemaLoader.class ); 061 062 /** Speedup for DEBUG mode */ 063 private static final boolean IS_DEBUG = LOG.isDebugEnabled(); 064 065 /** directory containing the schema LDIF file for ou=schema */ 066 private final File baseDirectory; 067 068 /** a filter for listing all the LDIF files within a directory */ 069 private final FilenameFilter ldifFilter = new FilenameFilter() 070 { 071 public boolean accept( File file, String name ) 072 { 073 return name.endsWith( LDIF_EXT ); 074 } 075 }; 076 077 078 /** 079 * Creates a new LDIF based SchemaLoader. The constructor checks to make 080 * sure the supplied base directory exists and contains a schema.ldif file 081 * and if not complains about it. 082 * 083 * @param baseDirectory the schema LDIF base directory 084 * @throws Exception if the base directory does not exist or does not 085 * a valid schema.ldif file 086 */ 087 public LdifSchemaLoader( File baseDirectory ) throws Exception 088 { 089 this.baseDirectory = baseDirectory; 090 091 if ( !baseDirectory.exists() ) 092 { 093 String msg = "Provided baseDirectory '" + baseDirectory.getAbsolutePath() + "' does not exist."; 094 LOG.error( msg ); 095 throw new IllegalArgumentException( msg ); 096 } 097 098 File schemaLdif = new File( baseDirectory, OU_SCHEMA_LDIF ); 099 100 if ( !schemaLdif.exists() ) 101 { 102 String msg = I18n.err( I18n.ERR_10004, schemaLdif.getAbsolutePath() ); 103 LOG.error( msg ); 104 throw new FileNotFoundException( msg ); 105 } 106 107 if ( IS_DEBUG ) 108 { 109 LOG.debug( "Using '{}' as the base schema load directory.", baseDirectory ); 110 } 111 112 initializeSchemas(); 113 } 114 115 116 /** 117 * Scans for LDIF files just describing the various schema contained in 118 * the schema repository. 119 * 120 * @throws Exception 121 */ 122 private void initializeSchemas() throws Exception 123 { 124 if ( IS_DEBUG ) 125 { 126 LOG.debug( "Initializing schema" ); 127 } 128 129 File schemaDirectory = new File( baseDirectory, SchemaConstants.OU_SCHEMA ); 130 String[] ldifFiles = schemaDirectory.list( ldifFilter ); 131 132 for ( String ldifFile : ldifFiles ) 133 { 134 File file = new File( schemaDirectory, ldifFile ); 135 136 try 137 { 138 LdifReader reader = new LdifReader( file ); 139 LdifEntry entry = reader.next(); 140 reader.close(); 141 Schema schema = getSchema( entry.getEntry() ); 142 143 if ( schema == null ) 144 { 145 // The entry was not a schema, skip it 146 continue; 147 } 148 149 schemaMap.put( schema.getSchemaName(), schema ); 150 151 if ( IS_DEBUG ) 152 { 153 LOG.debug( "Schema Initialized ... \n{}", schema ); 154 } 155 } 156 catch ( Exception e ) 157 { 158 LOG.error( I18n.err( I18n.ERR_10003, ldifFile ), e ); 159 throw e; 160 } 161 } 162 } 163 164 165 /** 166 * {@inheritDoc} 167 * 168 public List<Throwable> loadWithDependencies( Schema schema, Registries registries, boolean check ) throws Exception 169 { 170 // Relax the controls at first 171 List<Throwable> errors = new ArrayList<Throwable>(); 172 boolean wasRelaxed = registries.isRelaxed(); 173 registries.setRelaxed( true ); 174 175 Stack<String> beenthere = new Stack<String>(); 176 Map<String,Schema> notLoaded = new HashMap<String,Schema>(); 177 notLoaded.put( schema.getSchemaName(), schema ); 178 super.loadDepsFirst( schema, beenthere, notLoaded, schema, registries ); 179 180 // At the end, check the registries if required 181 if ( check ) 182 { 183 errors = registries.checkRefInteg(); 184 } 185 186 // Restore the Registries isRelaxed flag 187 registries.setRelaxed( wasRelaxed ); 188 189 return errors; 190 } 191 192 193 /** 194 * Loads a single schema if it has not been loaded already. If the schema 195 * load request was made because some other schema depends on this one then 196 * the schema is checked to see if it is disabled. If disabled it is 197 * enabled with a write to disk and then loaded. Listeners are notified that 198 * the schema has been loaded. 199 * 200 * {@inheritDoc} 201 * 202 public void load( Schema schema, Registries registries, boolean isDepLoad ) throws Exception 203 { 204 // if we're loading a dependency and it has not been enabled on 205 // disk then enable it on disk before we proceed to load it 206 if ( schema.isDisabled() && isDepLoad ) 207 { 208 enableSchema( schema ); 209 } 210 211 if ( registries.isSchemaLoaded( schema.getSchemaName() ) ) 212 { 213 LOG.info( "Will not attempt to load already loaded '{}' " + 214 "schema: \n{}", schema.getSchemaName(), schema ); 215 return; 216 } 217 218 LOG.info( "Loading {} schema: \n{}", schema.getSchemaName(), schema ); 219 220 registries.schemaLoaded( schema ); 221 222 loadComparators( schema ); 223 loadNormalizers( schema, registries ); 224 loadSyntaxCheckers( schema, registries ); 225 loadSyntaxes( schema, registries ); 226 loadMatchingRules( schema, registries ); 227 loadAttributeTypes( schema, registries ); 228 loadObjectClasses( schema, registries ); 229 loadMatchingRuleUses( schema, registries ); 230 loadDitContentRules( schema, registries ); 231 loadNameForms( schema, registries ); 232 loadDitStructureRules( schema, registries ); 233 234 notifyListenerOrRegistries( schema, registries ); 235 } 236 237 238 /** 239 * Utility method to get the file for a schema directory. 240 * 241 * @param schema the schema to get the file for 242 * @return the file for the specific schema directory 243 */ 244 private File getSchemaDirectory( Schema schema ) 245 { 246 return new File( new File( baseDirectory, SchemaConstants.OU_SCHEMA ), "cn=" + Strings.lowerCase(schema.getSchemaName()) ); 247 } 248 249 250 /** 251 * {@inheritDoc} 252 */ 253 public List<Entry> loadComparators( Schema... schemas ) throws LdapException, IOException 254 { 255 List<Entry> comparatorList = new ArrayList<Entry>(); 256 257 if ( schemas == null ) 258 { 259 return comparatorList; 260 } 261 262 for ( Schema schema : schemas ) 263 { 264 File comparatorsDirectory = new File( getSchemaDirectory( schema ), SchemaConstants.COMPARATORS_PATH ); 265 266 if ( !comparatorsDirectory.exists() ) 267 { 268 return comparatorList; 269 } 270 271 File[] comparators = comparatorsDirectory.listFiles( ldifFilter ); 272 273 for ( File ldifFile : comparators ) 274 { 275 LdifReader reader = new LdifReader( ldifFile ); 276 LdifEntry entry = reader.next(); 277 reader.close(); 278 279 comparatorList.add( entry.getEntry() ); 280 } 281 } 282 283 return comparatorList; 284 } 285 286 287 /** 288 * {@inheritDoc} 289 */ 290 public List<Entry> loadSyntaxCheckers( Schema... schemas ) throws LdapException, IOException 291 { 292 List<Entry> syntaxCheckerList = new ArrayList<Entry>(); 293 294 if ( schemas == null ) 295 { 296 return syntaxCheckerList; 297 } 298 299 for ( Schema schema : schemas ) 300 { 301 File syntaxCheckersDirectory = new File( getSchemaDirectory( schema ), SchemaConstants.SYNTAX_CHECKERS_PATH ); 302 303 if ( !syntaxCheckersDirectory.exists() ) 304 { 305 return syntaxCheckerList; 306 } 307 308 File[] syntaxCheckerFiles = syntaxCheckersDirectory.listFiles( ldifFilter ); 309 310 for ( File ldifFile : syntaxCheckerFiles ) 311 { 312 LdifReader reader = new LdifReader( ldifFile ); 313 LdifEntry entry = reader.next(); 314 reader.close(); 315 316 syntaxCheckerList.add( entry.getEntry() ); 317 } 318 } 319 320 return syntaxCheckerList; 321 } 322 323 324 /** 325 * {@inheritDoc} 326 */ 327 public List<Entry> loadNormalizers( Schema... schemas ) throws LdapException, IOException 328 { 329 List<Entry> normalizerList = new ArrayList<Entry>(); 330 331 if ( schemas == null ) 332 { 333 return normalizerList; 334 } 335 336 for ( Schema schema : schemas ) 337 { 338 File normalizersDirectory = new File( getSchemaDirectory( schema ), SchemaConstants.NORMALIZERS_PATH ); 339 340 if ( !normalizersDirectory.exists() ) 341 { 342 return normalizerList; 343 } 344 345 File[] normalizerFiles = normalizersDirectory.listFiles( ldifFilter ); 346 347 for ( File ldifFile : normalizerFiles ) 348 { 349 LdifReader reader = new LdifReader( ldifFile ); 350 LdifEntry entry = reader.next(); 351 reader.close(); 352 353 normalizerList.add( entry.getEntry() ); 354 } 355 } 356 357 return normalizerList; 358 } 359 360 361 /** 362 * {@inheritDoc} 363 */ 364 public List<Entry> loadMatchingRules( Schema... schemas ) throws LdapException, IOException 365 { 366 List<Entry> matchingRuleList = new ArrayList<Entry>(); 367 368 if ( schemas == null ) 369 { 370 return matchingRuleList; 371 } 372 373 for ( Schema schema : schemas ) 374 { 375 File matchingRulesDirectory = new File( getSchemaDirectory( schema ), SchemaConstants.MATCHING_RULES_PATH ); 376 377 if ( !matchingRulesDirectory.exists() ) 378 { 379 return matchingRuleList; 380 } 381 382 File[] matchingRuleFiles = matchingRulesDirectory.listFiles( ldifFilter ); 383 384 for ( File ldifFile : matchingRuleFiles ) 385 { 386 LdifReader reader = new LdifReader( ldifFile ); 387 LdifEntry entry = reader.next(); 388 reader.close(); 389 390 matchingRuleList.add( entry.getEntry() ); 391 } 392 } 393 394 return matchingRuleList; 395 } 396 397 398 /** 399 * {@inheritDoc} 400 */ 401 public List<Entry> loadSyntaxes( Schema... schemas ) throws LdapException, IOException 402 { 403 List<Entry> syntaxList = new ArrayList<Entry>(); 404 405 if ( schemas == null ) 406 { 407 return syntaxList; 408 } 409 410 for ( Schema schema : schemas ) 411 { 412 File syntaxesDirectory = new File( getSchemaDirectory( schema ), SchemaConstants.SYNTAXES_PATH ); 413 414 if ( !syntaxesDirectory.exists() ) 415 { 416 return syntaxList; 417 } 418 419 File[] syntaxFiles = syntaxesDirectory.listFiles( ldifFilter ); 420 421 for ( File ldifFile : syntaxFiles ) 422 { 423 LdifReader reader = new LdifReader( ldifFile ); 424 LdifEntry entry = reader.next(); 425 reader.close(); 426 427 syntaxList.add( entry.getEntry() ); 428 } 429 } 430 431 return syntaxList; 432 } 433 434 435 /** 436 * {@inheritDoc} 437 */ 438 public List<Entry> loadAttributeTypes( Schema... schemas ) throws LdapException, IOException 439 { 440 List<Entry> attributeTypeList = new ArrayList<Entry>(); 441 442 if ( schemas == null ) 443 { 444 return attributeTypeList; 445 } 446 447 for ( Schema schema : schemas ) 448 { 449 // check that the attributeTypes directory exists for the schema 450 File attributeTypesDirectory = new File( getSchemaDirectory( schema ), SchemaConstants.ATTRIBUTE_TYPES_PATH ); 451 452 if ( !attributeTypesDirectory.exists() ) 453 { 454 return attributeTypeList; 455 } 456 457 // get list of attributeType LDIF schema files in attributeTypes 458 File[] attributeTypeFiles = attributeTypesDirectory.listFiles( ldifFilter ); 459 460 for ( File ldifFile : attributeTypeFiles ) 461 { 462 LdifReader reader = new LdifReader( ldifFile ); 463 LdifEntry entry = reader.next(); 464 reader.close(); 465 466 attributeTypeList.add( entry.getEntry() ); 467 } 468 } 469 470 return attributeTypeList; 471 } 472 473 474 /** 475 * {@inheritDoc} 476 */ 477 public List<Entry> loadMatchingRuleUses( Schema... schemas ) throws LdapException, IOException 478 { 479 List<Entry> matchingRuleUseList = new ArrayList<Entry>(); 480 481 if ( schemas == null ) 482 { 483 return matchingRuleUseList; 484 } 485 486 for ( Schema schema : schemas ) 487 { 488 File matchingRuleUsesDirectory = new File( getSchemaDirectory( schema ), 489 SchemaConstants.MATCHING_RULE_USE_PATH ); 490 491 if ( !matchingRuleUsesDirectory.exists() ) 492 { 493 return matchingRuleUseList; 494 } 495 496 File[] matchingRuleUseFiles = matchingRuleUsesDirectory.listFiles( ldifFilter ); 497 498 for ( File ldifFile : matchingRuleUseFiles ) 499 { 500 LdifReader reader = new LdifReader( ldifFile ); 501 LdifEntry entry = reader.next(); 502 reader.close(); 503 504 matchingRuleUseList.add( entry.getEntry() ); 505 } 506 } 507 508 return matchingRuleUseList; 509 } 510 511 512 /** 513 * {@inheritDoc} 514 */ 515 public List<Entry> loadNameForms( Schema... schemas ) throws LdapException, IOException 516 { 517 List<Entry> nameFormList = new ArrayList<Entry>(); 518 519 if ( schemas == null ) 520 { 521 return nameFormList; 522 } 523 524 for ( Schema schema : schemas ) 525 { 526 File nameFormsDirectory = new File( getSchemaDirectory( schema ), SchemaConstants.NAME_FORMS_PATH ); 527 528 if ( !nameFormsDirectory.exists() ) 529 { 530 return nameFormList; 531 } 532 533 File[] nameFormFiles = nameFormsDirectory.listFiles( ldifFilter ); 534 535 for ( File ldifFile : nameFormFiles ) 536 { 537 LdifReader reader = new LdifReader( ldifFile ); 538 LdifEntry entry = reader.next(); 539 reader.close(); 540 541 nameFormList.add( entry.getEntry() ); 542 } 543 } 544 545 return nameFormList; 546 } 547 548 549 /** 550 * {@inheritDoc} 551 */ 552 public List<Entry> loadDitContentRules( Schema... schemas ) throws LdapException, IOException 553 { 554 List<Entry> ditContentRuleList = new ArrayList<Entry>(); 555 556 if ( schemas == null ) 557 { 558 return ditContentRuleList; 559 } 560 561 for ( Schema schema : schemas ) 562 { 563 File ditContentRulesDirectory = new File( getSchemaDirectory( schema ), 564 SchemaConstants.DIT_CONTENT_RULES_PATH ); 565 566 if ( !ditContentRulesDirectory.exists() ) 567 { 568 return ditContentRuleList; 569 } 570 571 File[] ditContentRuleFiles = ditContentRulesDirectory.listFiles( ldifFilter ); 572 573 for ( File ldifFile : ditContentRuleFiles ) 574 { 575 LdifReader reader = new LdifReader( ldifFile ); 576 LdifEntry entry = reader.next(); 577 reader.close(); 578 579 ditContentRuleList.add( entry.getEntry() ); 580 } 581 } 582 583 return ditContentRuleList; 584 } 585 586 587 /** 588 * {@inheritDoc} 589 */ 590 public List<Entry> loadDitStructureRules( Schema... schemas ) throws LdapException, IOException 591 { 592 List<Entry> ditStructureRuleList = new ArrayList<Entry>(); 593 594 if ( schemas == null ) 595 { 596 return ditStructureRuleList; 597 } 598 599 for ( Schema schema : schemas ) 600 { 601 File ditStructureRulesDirectory = new File( getSchemaDirectory( schema ), 602 SchemaConstants.DIT_STRUCTURE_RULES_PATH ); 603 604 if ( !ditStructureRulesDirectory.exists() ) 605 { 606 return ditStructureRuleList; 607 } 608 609 File[] ditStructureRuleFiles = ditStructureRulesDirectory.listFiles( ldifFilter ); 610 611 for ( File ldifFile : ditStructureRuleFiles ) 612 { 613 LdifReader reader = new LdifReader( ldifFile ); 614 LdifEntry entry = reader.next(); 615 reader.close(); 616 617 ditStructureRuleList.add( entry.getEntry() ); 618 } 619 } 620 621 return ditStructureRuleList; 622 } 623 624 625 /** 626 * {@inheritDoc} 627 */ 628 public List<Entry> loadObjectClasses( Schema... schemas ) throws LdapException, IOException 629 { 630 List<Entry> objectClassList = new ArrayList<Entry>(); 631 632 if ( schemas == null ) 633 { 634 return objectClassList; 635 } 636 637 for ( Schema schema : schemas ) 638 { 639 // get objectClasses directory, check if exists, return if not 640 File objectClassesDirectory = new File( getSchemaDirectory( schema ), SchemaConstants.OBJECT_CLASSES_PATH ); 641 642 if ( !objectClassesDirectory.exists() ) 643 { 644 return objectClassList; 645 } 646 647 // get list of objectClass LDIF files from directory and load 648 File[] objectClassFiles = objectClassesDirectory.listFiles( ldifFilter ); 649 650 for ( File ldifFile : objectClassFiles ) 651 { 652 LdifReader reader = new LdifReader( ldifFile ); 653 LdifEntry entry = reader.next(); 654 reader.close(); 655 656 objectClassList.add( entry.getEntry() ); 657 } 658 } 659 660 return objectClassList; 661 } 662}