001/* 002 * The contents of this file are subject to the terms of the Common Development and 003 * Distribution License (the License). You may not use this file except in compliance with the 004 * License. 005 * 006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the 007 * specific language governing permission and limitations under the License. 008 * 009 * When distributing Covered Software, include this CDDL Header Notice in each file and include 010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL 011 * Header, with the fields enclosed by brackets [] replaced by your own identifying 012 * information: "Portions Copyright [year] [name of copyright owner]". 013 * 014 * Copyright 2006-2010 Sun Microsystems, Inc. 015 * Portions Copyright 2011-2016 ForgeRock AS. 016 */ 017package org.opends.server.core; 018 019import java.io.File; 020import java.io.FilenameFilter; 021import java.util.ArrayList; 022import java.util.Arrays; 023import java.util.LinkedList; 024import java.util.List; 025 026import org.forgerock.i18n.LocalizableMessage; 027import org.forgerock.i18n.slf4j.LocalizedLogger; 028import org.forgerock.opendj.config.server.ConfigException; 029import org.forgerock.opendj.ldap.ByteString; 030import org.forgerock.opendj.ldap.ModificationType; 031import org.forgerock.opendj.ldap.ResultCode; 032import org.forgerock.opendj.ldap.schema.AttributeType; 033import org.forgerock.opendj.ldap.schema.CoreSchema; 034import org.forgerock.opendj.ldap.schema.Syntax; 035import org.opends.server.schema.DITContentRuleSyntax; 036import org.opends.server.schema.DITStructureRuleSyntax; 037import org.opends.server.schema.MatchingRuleUseSyntax; 038import org.opends.server.schema.NameFormSyntax; 039import org.opends.server.schema.ObjectClassSyntax; 040import org.opends.server.types.Attribute; 041import org.opends.server.types.DITContentRule; 042import org.opends.server.types.DITStructureRule; 043import org.opends.server.types.DirectoryException; 044import org.opends.server.types.Entry; 045import org.opends.server.types.InitializationException; 046import org.opends.server.types.LDIFImportConfig; 047import org.opends.server.types.MatchingRuleUse; 048import org.opends.server.types.Modification; 049import org.opends.server.types.NameForm; 050import org.opends.server.types.ObjectClass; 051import org.opends.server.types.Schema; 052import org.opends.server.util.LDIFReader; 053import org.opends.server.util.StaticUtils; 054 055import static org.opends.messages.ConfigMessages.*; 056import static org.opends.server.config.ConfigConstants.*; 057import static org.opends.server.schema.SchemaConstants.*; 058import static org.opends.server.types.CommonSchemaElements.*; 059import static org.opends.server.util.ServerConstants.*; 060import static org.opends.server.util.StaticUtils.*; 061 062/** 063 * This class defines a utility that will be used to manage the interaction with 064 * the Directory Server schema. It will be used to initially load all of the 065 * matching rules and attribute syntaxes that have been defined in the 066 * configuration, and will then read the actual schema definitions. At present, 067 * only attribute types and objectclasses are supported in the schema config 068 * files. Other components like DIT content rules, DIT structure rules, name 069 * forms, and matching rule use definitions will be ignored. 070 */ 071public class SchemaConfigManager 072{ 073 private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); 074 075 /** The schema that has been parsed from the server configuration. */ 076 private Schema schema; 077 078 private final ServerContext serverContext; 079 080 /** 081 * Creates a new instance of this schema config manager. 082 * 083 * @param serverContext 084 * The server context. 085 */ 086 public SchemaConfigManager(ServerContext serverContext) 087 { 088 this.serverContext = serverContext; 089 try 090 { 091 // the manager will build the schema from scratch, but we need to start from core schema for SDK schema 092 schema = new Schema(org.forgerock.opendj.ldap.schema.Schema.getCoreSchema()); 093 } 094 catch (DirectoryException unexpected) 095 { 096 // the core schema should not have any warning 097 throw new RuntimeException(unexpected); 098 } 099 } 100 101 102 103 /** 104 * Retrieves the path to the directory containing the server schema files. 105 * 106 * @return The path to the directory containing the server schema files. 107 */ 108 public static String getSchemaDirectoryPath() 109 { 110 File schemaDir = 111 DirectoryServer.getEnvironmentConfig().getSchemaDirectory(); 112 if (schemaDir != null) { 113 return schemaDir.getAbsolutePath(); 114 } 115 return null; 116 } 117 118 119 120 /** 121 * Retrieves a reference to the schema information that has been read from the 122 * server configuration. Note that this information will not be complete 123 * until the <CODE>initializeMatchingRules</CODE>, 124 * <CODE>initializeAttributeSyntaxes</CODE>, and 125 * <CODE>initializeAttributeTypesAndObjectClasses</CODE> methods have been 126 * called. 127 * 128 * @return A reference to the schema information that has been read from the 129 * server configuration. 130 */ 131 public Schema getSchema() 132 { 133 return schema; 134 } 135 136 137 138 /** 139 * Initializes all the matching rules defined in the Directory Server 140 * configuration. This should only be called at Directory Server startup. 141 * 142 * @throws ConfigException If a configuration problem causes the matching 143 * rule initialization process to fail. 144 * 145 * @throws InitializationException If a problem occurs while initializing 146 * the matching rules that is not related to 147 * the server configuration. 148 */ 149 public void initializeMatchingRules() 150 throws ConfigException, InitializationException 151 { 152 MatchingRuleConfigManager matchingRuleConfigManager = new MatchingRuleConfigManager(serverContext); 153 matchingRuleConfigManager.initializeMatchingRules(); 154 } 155 156 157 158 /** 159 * Initializes all the attribute syntaxes defined in the Directory Server 160 * configuration. This should only be called at Directory Server startup. 161 * 162 * @throws ConfigException If a configuration problem causes the syntax 163 * initialization process to fail. 164 * 165 * @throws InitializationException If a problem occurs while initializing 166 * the syntaxes that is not related to the 167 * server configuration. 168 */ 169 public void initializeAttributeSyntaxes() 170 throws ConfigException, InitializationException 171 { 172 AttributeSyntaxConfigManager syntaxConfigManager = 173 new AttributeSyntaxConfigManager(serverContext); 174 syntaxConfigManager.initializeAttributeSyntaxes(); 175 } 176 177 178 179 /** 180 * Filter implementation that accepts only ldif files. 181 */ 182 public static class SchemaFileFilter implements FilenameFilter 183 { 184 /** {@inheritDoc} */ 185 @Override 186 public boolean accept(File directory, String filename) 187 { 188 return filename.endsWith(".ldif"); 189 } 190 } 191 192 193 194 /** 195 * Initializes all the attribute type, object class, name form, DIT content 196 * rule, DIT structure rule, and matching rule use definitions by reading the 197 * server schema files. These files will be located in a single directory and 198 * will be processed in lexicographic order. However, to make the order 199 * easier to understand, they may be prefixed with a two digit number (with a 200 * leading zero if necessary) so that they will be read in numeric order. 201 * This should only be called at Directory Server startup. 202 * 203 * @throws ConfigException If a configuration problem causes the schema 204 * element initialization to fail. 205 * 206 * @throws InitializationException If a problem occurs while initializing 207 * the schema elements that is not related 208 * to the server configuration. 209 */ 210 public void initializeSchemaFromFiles() 211 throws ConfigException, InitializationException 212 { 213 // Construct the path to the directory that should contain the schema files 214 // and make sure that it exists and is a directory. Get a list of the files 215 // in that directory sorted in alphabetic order. 216 String schemaInstanceDirPath = getSchemaDirectoryPath(); 217 File schemaInstanceDir = null; 218 219 try 220 { 221 if (schemaInstanceDirPath != null) 222 { 223 schemaInstanceDir = new File(schemaInstanceDirPath); 224 } 225 } catch (Exception e) 226 { 227 schemaInstanceDir = null; 228 } 229 long oldestModificationTime = -1L; 230 long youngestModificationTime = -1L; 231 String[] fileNames; 232 233 try 234 { 235 if (schemaInstanceDir == null || ! schemaInstanceDir.exists()) 236 { 237 LocalizableMessage message = 238 ERR_CONFIG_SCHEMA_NO_SCHEMA_DIR.get(schemaInstanceDirPath); 239 throw new InitializationException(message); 240 } 241 if (! schemaInstanceDir.isDirectory()) 242 { 243 LocalizableMessage message = 244 ERR_CONFIG_SCHEMA_DIR_NOT_DIRECTORY.get(schemaInstanceDirPath); 245 throw new InitializationException(message); 246 } 247 248 249 FilenameFilter filter = new SchemaFileFilter(); 250 File[] schemaInstanceDirFiles = 251 schemaInstanceDir.listFiles(filter); 252 int fileNumber = schemaInstanceDirFiles.length ; 253 ArrayList<String> fileList = new ArrayList<>(fileNumber); 254 255 for (File f : schemaInstanceDirFiles) 256 { 257 if (f.isFile()) 258 { 259 fileList.add(f.getName()); 260 } 261 262 long modificationTime = f.lastModified(); 263 if (oldestModificationTime <= 0L || 264 modificationTime < oldestModificationTime) 265 { 266 oldestModificationTime = modificationTime; 267 } 268 269 if (youngestModificationTime <= 0 || 270 modificationTime > youngestModificationTime) 271 { 272 youngestModificationTime = modificationTime; 273 } 274 } 275 276 fileNames = new String[fileList.size()]; 277 fileList.toArray(fileNames); 278 Arrays.sort(fileNames); 279 } 280 catch (InitializationException ie) 281 { 282 logger.traceException(ie); 283 284 throw ie; 285 } 286 catch (Exception e) 287 { 288 logger.traceException(e); 289 290 LocalizableMessage message = ERR_CONFIG_SCHEMA_CANNOT_LIST_FILES.get( 291 schemaInstanceDirPath, getExceptionMessage(e)); 292 throw new InitializationException(message, e); 293 } 294 295 296 // If the oldest and youngest modification timestamps didn't get set for 297 // some reason, then set them to the current time. 298 if (oldestModificationTime <= 0) 299 { 300 oldestModificationTime = System.currentTimeMillis(); 301 } 302 303 if (youngestModificationTime <= 0) 304 { 305 youngestModificationTime = oldestModificationTime; 306 } 307 308 schema.setOldestModificationTime(oldestModificationTime); 309 schema.setYoungestModificationTime(youngestModificationTime); 310 311 312 // Iterate through the schema files and read them as an LDIF file containing 313 // a single entry. Then get the attributeTypes and objectClasses attributes 314 // from that entry and parse them to initialize the server schema. 315 for (String schemaFile : fileNames) 316 { 317 loadSchemaFile(schema, schemaFile, false); 318 } 319 } 320 321 322 323 /** 324 * Loads the contents of the specified schema file into the provided schema. 325 * 326 * @param schema The schema in which the contents of the schema file are 327 * to be loaded. 328 * @param schemaFile The name of the schema file to be loaded into the 329 * provided schema. 330 * 331 * @return A list of the modifications that could be performed in order to 332 * obtain the contents of the file. 333 * 334 * @throws ConfigException If a configuration problem causes the schema 335 * element initialization to fail. 336 * 337 * @throws InitializationException If a problem occurs while initializing 338 * the schema elements that is not related 339 * to the server configuration. 340 */ 341 public static List<Modification> loadSchemaFile(Schema schema, String schemaFile) 342 throws ConfigException, InitializationException 343 { 344 return loadSchemaFile(schema, schemaFile, true); 345 } 346 347 348 349 /** 350 * Loads the contents of the specified schema file into the provided schema. 351 * 352 * @param schema The schema in which the contents of the schema file 353 * are to be loaded. 354 * @param schemaFile The name of the schema file to be loaded into the 355 * provided schema. 356 * @param failOnError If {@code true}, indicates that this method should 357 * throw an exception if certain kinds of errors occur. 358 * If {@code false}, indicates that this method should 359 * log an error message and return without an exception. 360 * This should only be {@code false} when called from 361 * {@code initializeSchemaFromFiles}. 362 * 363 * @return A list of the modifications that could be performed in order to 364 * obtain the contents of the file, or {@code null} if a problem 365 * occurred and {@code failOnError} is {@code false}. 366 * 367 * @throws ConfigException If a configuration problem causes the schema 368 * element initialization to fail. 369 * 370 * @throws InitializationException If a problem occurs while initializing 371 * the schema elements that is not related 372 * to the server configuration. 373 */ 374 private static List<Modification> loadSchemaFile(Schema schema, String schemaFile, 375 boolean failOnError) throws ConfigException, InitializationException 376 { 377 // Create an LDIF reader to use when reading the files. 378 String schemaDirPath = getSchemaDirectoryPath(); 379 File f = new File(schemaDirPath, schemaFile); 380 LDIFReader reader; 381 try 382 { 383 reader = new LDIFReader(new LDIFImportConfig(f.getAbsolutePath())); 384 } 385 catch (Exception e) 386 { 387 logger.traceException(e); 388 389 LocalizableMessage message = WARN_CONFIG_SCHEMA_CANNOT_OPEN_FILE.get( 390 schemaFile, schemaDirPath, getExceptionMessage(e)); 391 392 if (failOnError) 393 { 394 throw new ConfigException(message); 395 } 396 else 397 { 398 logger.error(message); 399 return null; 400 } 401 } 402 403 404 // Read the LDIF entry from the file and close the file. 405 Entry entry; 406 try 407 { 408 entry = reader.readEntry(false); 409 410 if (entry == null) 411 { 412 // The file was empty -- skip it. 413 reader.close(); 414 return new LinkedList<>(); 415 } 416 } 417 catch (Exception e) 418 { 419 logger.traceException(e); 420 421 LocalizableMessage message = WARN_CONFIG_SCHEMA_CANNOT_READ_LDIF_ENTRY.get( 422 schemaFile, schemaDirPath, getExceptionMessage(e)); 423 424 if (failOnError) 425 { 426 throw new InitializationException(message, e); 427 } 428 else 429 { 430 logger.error(message); 431 StaticUtils.close(reader); 432 return null; 433 } 434 } 435 436 // If there are any more entries in the file, then print a warning message. 437 try 438 { 439 Entry e = reader.readEntry(false); 440 if (e != null) 441 { 442 logger.warn(WARN_CONFIG_SCHEMA_MULTIPLE_ENTRIES_IN_FILE, schemaFile, schemaDirPath); 443 } 444 } 445 catch (Exception e) 446 { 447 logger.traceException(e); 448 449 logger.warn(WARN_CONFIG_SCHEMA_UNPARSEABLE_EXTRA_DATA_IN_FILE, schemaFile, schemaDirPath, getExceptionMessage(e)); 450 } 451 finally 452 { 453 StaticUtils.close(reader); 454 } 455 456 // Get the attributeTypes attribute from the entry. 457 List<Modification> mods = new LinkedList<>(); 458 459 //parse the syntaxes first because attributes rely on these. 460 List<Attribute> ldapSyntaxList = getLdapSyntaxesAttributes(schema, entry, mods); 461 List<Attribute> attrList = getAttributeTypeAttributes(schema, entry, mods); 462 List<Attribute> ocList = getObjectClassesAttributes(schema, entry, mods); 463 List<Attribute> nfList = getNameFormsAttributes(schema, entry, mods); 464 List<Attribute> dcrList = getDITContentRulesAttributes(schema, entry, mods); 465 List<Attribute> dsrList = getDITStructureRulesAttributes(schema, entry, mods); 466 List<Attribute> mruList = getMatchingRuleUsesAttributes(schema, entry, mods); 467 468 // Loop on all the attribute of the schema entry to 469 // find the extra attribute that should be loaded in the Schema. 470 for (Attribute attribute : entry.getAttributes()) 471 { 472 if (!isSchemaAttribute(attribute)) 473 { 474 schema.addExtraAttribute(attribute.getName(), attribute); 475 } 476 } 477 478 parseLdapSyntaxesDefinitions(schema, schemaFile, failOnError, ldapSyntaxList); 479 parseAttributeTypeDefinitions(schema, schemaFile, failOnError, attrList); 480 parseObjectclassDefinitions(schema, schemaFile, failOnError, ocList); 481 parseNameFormDefinitions(schema, schemaFile, failOnError, nfList); 482 parseDITContentRuleDefinitions(schema, schemaFile, failOnError, dcrList); 483 parseDITStructureRuleDefinitions(schema, schemaFile, failOnError, dsrList); 484 parseMatchingRuleUseDefinitions(schema, schemaFile, failOnError, mruList); 485 486 return mods; 487 } 488 489 private static List<Attribute> getLdapSyntaxesAttributes(Schema schema, 490 Entry entry, List<Modification> mods) throws ConfigException 491 { 492 Syntax syntax = schema.getSyntax(SYNTAX_LDAP_SYNTAX_OID); 493 if (syntax == null) 494 { 495 syntax = CoreSchema.getLDAPSyntaxDescriptionSyntax(); 496 } 497 498 AttributeType ldapSyntaxAttrType = schema.getAttributeType(ATTR_LDAP_SYNTAXES, syntax); 499 return createAddModifications(entry, mods, ldapSyntaxAttrType); 500 } 501 502 private static List<Attribute> getAttributeTypeAttributes(Schema schema, 503 Entry entry, List<Modification> mods) throws ConfigException, 504 InitializationException 505 { 506 Syntax syntax = schema.getSyntax(SYNTAX_ATTRIBUTE_TYPE_OID); 507 if (syntax == null) 508 { 509 syntax = CoreSchema.getAttributeTypeDescriptionSyntax(); 510 } 511 AttributeType attributeAttrType = schema.getAttributeType(ATTR_ATTRIBUTE_TYPES, syntax); 512 return createAddModifications(entry, mods, attributeAttrType); 513 } 514 515 /** Get the objectClasses attribute from the entry. */ 516 private static List<Attribute> getObjectClassesAttributes(Schema schema, 517 Entry entry, List<Modification> mods) throws ConfigException, 518 InitializationException 519 { 520 Syntax syntax = schema.getSyntax(SYNTAX_OBJECTCLASS_OID); 521 if (syntax == null) 522 { 523 syntax = CoreSchema.getObjectClassDescriptionSyntax(); 524 } 525 AttributeType objectclassAttrType = schema.getAttributeType(ATTR_OBJECTCLASSES, syntax); 526 return createAddModifications(entry, mods, objectclassAttrType); 527 } 528 529 /** Get the name forms attribute from the entry. */ 530 private static List<Attribute> getNameFormsAttributes(Schema schema, 531 Entry entry, List<Modification> mods) throws ConfigException, 532 InitializationException 533 { 534 Syntax syntax = schema.getSyntax(SYNTAX_NAME_FORM_OID); 535 if (syntax == null) 536 { 537 syntax = CoreSchema.getNameFormDescriptionSyntax(); 538 } 539 AttributeType nameFormAttrType = schema.getAttributeType(ATTR_NAME_FORMS, syntax); 540 return createAddModifications(entry, mods, nameFormAttrType); 541 } 542 543 /** Get the DIT content rules attribute from the entry. */ 544 private static List<Attribute> getDITContentRulesAttributes(Schema schema, 545 Entry entry, List<Modification> mods) throws ConfigException, 546 InitializationException 547 { 548 Syntax syntax = schema.getSyntax(SYNTAX_DIT_CONTENT_RULE_OID); 549 if (syntax == null) 550 { 551 syntax = CoreSchema.getDITContentRuleDescriptionSyntax(); 552 } 553 AttributeType dcrAttrType = schema.getAttributeType(ATTR_DIT_CONTENT_RULES, syntax); 554 return createAddModifications(entry, mods, dcrAttrType); 555 } 556 557 /** Get the DIT structure rules attribute from the entry. */ 558 private static List<Attribute> getDITStructureRulesAttributes(Schema schema, 559 Entry entry, List<Modification> mods) throws ConfigException, 560 InitializationException 561 { 562 Syntax syntax = schema.getSyntax(SYNTAX_DIT_STRUCTURE_RULE_OID); 563 if (syntax == null) 564 { 565 syntax = CoreSchema.getDITStructureRuleDescriptionSyntax(); 566 } 567 AttributeType dsrAttrType = schema.getAttributeType(ATTR_DIT_STRUCTURE_RULES, syntax); 568 return createAddModifications(entry, mods, dsrAttrType); 569 } 570 571 /** Get the matching rule uses attribute from the entry. */ 572 private static List<Attribute> getMatchingRuleUsesAttributes(Schema schema, 573 Entry entry, List<Modification> mods) throws ConfigException, 574 InitializationException 575 { 576 Syntax syntax = schema.getSyntax(SYNTAX_MATCHING_RULE_USE_OID); 577 if (syntax == null) 578 { 579 syntax = CoreSchema.getMatchingRuleUseDescriptionSyntax(); 580 } 581 AttributeType mruAttrType = schema.getAttributeType(ATTR_MATCHING_RULE_USE, syntax); 582 return createAddModifications(entry, mods, mruAttrType); 583 } 584 585 private static List<Attribute> createAddModifications(Entry entry, 586 List<Modification> mods, AttributeType attrType) 587 { 588 List<Attribute> attributes = entry.getAttribute(attrType); 589 for (Attribute a : attributes) 590 { 591 mods.add(new Modification(ModificationType.ADD, a)); 592 } 593 return attributes; 594 } 595 596 /** Parse the ldapsyntaxes definitions if there are any. */ 597 private static void parseLdapSyntaxesDefinitions(Schema schema, 598 String schemaFile, boolean failOnError, List<Attribute> ldapSyntaxList) 599 throws ConfigException 600 { 601 if (ldapSyntaxList != null) 602 { 603 for (Attribute a : ldapSyntaxList) 604 { 605 for (ByteString v : a) 606 { 607 final String definition = Schema.addSchemaFileToElementDefinitionIfAbsent(v.toString(), schemaFile); 608 try 609 { 610 schema.registerLdapSyntaxDescription(definition, failOnError); 611 } 612 catch (DirectoryException de) 613 { 614 logger.traceException(de); 615 616 if (de.getResultCode().equals(ResultCode.CONSTRAINT_VIOLATION)) 617 { 618 // Register it with the schema. We will allow duplicates, with the 619 // later definition overriding any earlier definition, but we want 620 // to trap them and log a warning. 621 logger.warn(WARN_CONFIG_SCHEMA_CONFLICTING_LDAP_SYNTAX, schemaFile, de.getMessageObject()); 622 try 623 { 624 schema.registerLdapSyntaxDescription(definition, true); 625 } 626 catch (Exception e) 627 { 628 // This should never happen. 629 logger.traceException(e); 630 } 631 } 632 else 633 { 634 LocalizableMessage message = WARN_CONFIG_SCHEMA_CANNOT_PARSE_LDAP_SYNTAX.get( 635 schemaFile, de.getMessageObject()); 636 reportError(failOnError, de, message); 637 } 638 } 639 } 640 } 641 } 642 } 643 644 /** Parse the attribute type definitions if there are any. */ 645 private static void parseAttributeTypeDefinitions( 646 Schema schema, String schemaFile, boolean failOnError, List<Attribute> attrList) 647 throws ConfigException 648 { 649 if (attrList != null) 650 { 651 List<String> definitions = new ArrayList<>(); 652 for (Attribute a : attrList) 653 { 654 for (ByteString v : a) 655 { 656 definitions.add(v.toString()); 657 } 658 } 659 try 660 { 661 schema.registerAttributeTypes(definitions, schemaFile, !failOnError); 662 } 663 catch (DirectoryException de) 664 { 665 logger.traceException(de); 666 667 if (de.getResultCode().equals(ResultCode.CONSTRAINT_VIOLATION)) 668 { 669 // Register it with the schema. We will allow duplicates, with the 670 // later definition overriding any earlier definition, but we want 671 // to trap them and log a warning. 672 logger.warn(WARN_CONFIG_SCHEMA_CONFLICTING_ATTR_TYPE, schemaFile, de.getMessageObject()); 673 try 674 { 675 schema.registerAttributeTypes(definitions, schemaFile, true); 676 } 677 catch (DirectoryException e) 678 { 679 // This should never happen 680 logger.traceException(e); 681 } 682 } 683 else 684 { 685 LocalizableMessage message = WARN_CONFIG_SCHEMA_CANNOT_PARSE_ATTR_TYPE.get(schemaFile, de.getMessageObject()); 686 reportError(failOnError, de, message); 687 } 688 } 689 } 690 } 691 692 /** Parse the objectclass definitions if there are any. */ 693 private static void parseObjectclassDefinitions(Schema schema, 694 String schemaFile, boolean failOnError, List<Attribute> ocList) 695 throws ConfigException 696 { 697 if (ocList != null) 698 { 699 for (Attribute a : ocList) 700 { 701 for (ByteString v : a) 702 { 703 // Parse the objectclass. 704 ObjectClass oc; 705 try 706 { 707 oc = ObjectClassSyntax.decodeObjectClass(v, schema, false); 708 setExtraProperty(oc, SCHEMA_PROPERTY_FILENAME, null); 709 setSchemaFile(oc, schemaFile); 710 } 711 catch (DirectoryException de) 712 { 713 logger.traceException(de); 714 715 LocalizableMessage message = WARN_CONFIG_SCHEMA_CANNOT_PARSE_OC.get( 716 schemaFile, 717 de.getMessageObject()); 718 reportError(failOnError, de, message); 719 continue; 720 } 721 catch (Exception e) 722 { 723 logger.traceException(e); 724 725 LocalizableMessage message = WARN_CONFIG_SCHEMA_CANNOT_PARSE_OC.get( 726 schemaFile, v + ": " + getExceptionMessage(e)); 727 reportError(failOnError, e, message); 728 continue; 729 } 730 731 // Register it with the schema. We will allow duplicates, with the 732 // later definition overriding any earlier definition, but we want 733 // to trap them and log a warning. 734 try 735 { 736 schema.registerObjectClass(oc, failOnError); 737 } 738 catch (DirectoryException de) 739 { 740 logger.traceException(de); 741 742 logger.warn(WARN_CONFIG_SCHEMA_CONFLICTING_OC, schemaFile, de.getMessageObject()); 743 744 try 745 { 746 schema.registerObjectClass(oc, true); 747 } 748 catch (Exception e) 749 { 750 // This should never happen. 751 logger.traceException(e); 752 } 753 } 754 } 755 } 756 } 757 } 758 759 /** Parse the name form definitions if there are any. */ 760 private static void parseNameFormDefinitions(Schema schema, 761 String schemaFile, boolean failOnError, List<Attribute> nfList) 762 throws ConfigException 763 { 764 if (nfList != null) 765 { 766 for (Attribute a : nfList) 767 { 768 for (ByteString v : a) 769 { 770 // Parse the name form. 771 NameForm nf; 772 try 773 { 774 nf = NameFormSyntax.decodeNameForm(v, schema, false); 775 nf.getExtraProperties().remove(SCHEMA_PROPERTY_FILENAME); 776 setSchemaFile(nf, schemaFile); 777 } 778 catch (DirectoryException de) 779 { 780 logger.traceException(de); 781 782 LocalizableMessage message = WARN_CONFIG_SCHEMA_CANNOT_PARSE_NAME_FORM.get( 783 schemaFile, de.getMessageObject()); 784 reportError(failOnError, de, message); 785 continue; 786 } 787 catch (Exception e) 788 { 789 logger.traceException(e); 790 791 LocalizableMessage message = WARN_CONFIG_SCHEMA_CANNOT_PARSE_NAME_FORM.get( 792 schemaFile, v + ": " + getExceptionMessage(e)); 793 reportError(failOnError, e, message); 794 continue; 795 } 796 797 // Register it with the schema. We will allow duplicates, with the 798 // later definition overriding any earlier definition, but we want 799 // to trap them and log a warning. 800 try 801 { 802 schema.registerNameForm(nf, failOnError); 803 } 804 catch (DirectoryException de) 805 { 806 logger.traceException(de); 807 808 logger.warn(WARN_CONFIG_SCHEMA_CONFLICTING_NAME_FORM, schemaFile, de.getMessageObject()); 809 810 try 811 { 812 schema.registerNameForm(nf, true); 813 } 814 catch (Exception e) 815 { 816 // This should never happen. 817 logger.traceException(e); 818 } 819 } 820 } 821 } 822 } 823 } 824 825 /** Parse the DIT content rule definitions if there are any. */ 826 private static void parseDITContentRuleDefinitions(Schema schema, 827 String schemaFile, boolean failOnError, List<Attribute> dcrList) 828 throws ConfigException 829 { 830 if (dcrList != null) 831 { 832 for (Attribute a : dcrList) 833 { 834 for (ByteString v : a) 835 { 836 // Parse the DIT content rule. 837 DITContentRule dcr; 838 try 839 { 840 dcr = DITContentRuleSyntax.decodeDITContentRule(v, schema, false); 841 dcr.getExtraProperties().remove(SCHEMA_PROPERTY_FILENAME); 842 setSchemaFile(dcr, schemaFile); 843 } 844 catch (DirectoryException de) 845 { 846 logger.traceException(de); 847 848 LocalizableMessage message = WARN_CONFIG_SCHEMA_CANNOT_PARSE_DCR.get( 849 schemaFile, de.getMessageObject()); 850 reportError(failOnError, de, message); 851 continue; 852 } 853 catch (Exception e) 854 { 855 logger.traceException(e); 856 857 LocalizableMessage message = WARN_CONFIG_SCHEMA_CANNOT_PARSE_DCR.get( 858 schemaFile, v + ": " + getExceptionMessage(e)); 859 reportError(failOnError, e, message); 860 continue; 861 } 862 863 // Register it with the schema. We will allow duplicates, with the 864 // later definition overriding any earlier definition, but we want 865 // to trap them and log a warning. 866 try 867 { 868 schema.registerDITContentRule(dcr, failOnError); 869 } 870 catch (DirectoryException de) 871 { 872 logger.traceException(de); 873 874 logger.warn(WARN_CONFIG_SCHEMA_CONFLICTING_DCR, schemaFile, de.getMessageObject()); 875 876 try 877 { 878 schema.registerDITContentRule(dcr, true); 879 } 880 catch (Exception e) 881 { 882 // This should never happen. 883 logger.traceException(e); 884 } 885 } 886 } 887 } 888 } 889 } 890 891 private static void reportError(boolean failOnError, Exception e, 892 LocalizableMessage message) throws ConfigException 893 { 894 if (failOnError) 895 { 896 throw new ConfigException(message, e); 897 } 898 logger.error(message); 899 } 900 901 /** Parse the DIT structure rule definitions if there are any. */ 902 private static void parseDITStructureRuleDefinitions(Schema schema, 903 String schemaFile, boolean failOnError, List<Attribute> dsrList) 904 throws ConfigException 905 { 906 if (dsrList != null) 907 { 908 for (Attribute a : dsrList) 909 { 910 for (ByteString v : a) 911 { 912 // Parse the DIT content rule. 913 DITStructureRule dsr; 914 try 915 { 916 dsr = DITStructureRuleSyntax.decodeDITStructureRule(v, schema, false); 917 dsr.getExtraProperties().remove(SCHEMA_PROPERTY_FILENAME); 918 setSchemaFile(dsr, schemaFile); 919 } 920 catch (DirectoryException de) 921 { 922 logger.traceException(de); 923 924 LocalizableMessage message = WARN_CONFIG_SCHEMA_CANNOT_PARSE_DSR.get( 925 schemaFile, de.getMessageObject()); 926 reportError(failOnError, de, message); 927 continue; 928 } 929 catch (Exception e) 930 { 931 logger.traceException(e); 932 933 LocalizableMessage message = WARN_CONFIG_SCHEMA_CANNOT_PARSE_DSR.get( 934 schemaFile, v + ": " + getExceptionMessage(e)); 935 reportError(failOnError, e, message); 936 continue; 937 } 938 939 // Register it with the schema. We will allow duplicates, with the 940 // later definition overriding any earlier definition, but we want 941 // to trap them and log a warning. 942 try 943 { 944 schema.registerDITStructureRule(dsr, failOnError); 945 } 946 catch (DirectoryException de) 947 { 948 logger.traceException(de); 949 950 logger.warn(WARN_CONFIG_SCHEMA_CONFLICTING_DSR, schemaFile, de.getMessageObject()); 951 952 try 953 { 954 schema.registerDITStructureRule(dsr, true); 955 } 956 catch (Exception e) 957 { 958 // This should never happen. 959 logger.traceException(e); 960 } 961 } 962 } 963 } 964 } 965 } 966 967 /** Parse the matching rule use definitions if there are any. */ 968 private static void parseMatchingRuleUseDefinitions(Schema schema, 969 String schemaFile, boolean failOnError, List<Attribute> mruList) 970 throws ConfigException 971 { 972 if (mruList != null) 973 { 974 for (Attribute a : mruList) 975 { 976 for (ByteString v : a) 977 { 978 // Parse the matching rule use definition. 979 MatchingRuleUse mru; 980 try 981 { 982 mru = MatchingRuleUseSyntax.decodeMatchingRuleUse(v, schema, false); 983 mru.getExtraProperties().remove(SCHEMA_PROPERTY_FILENAME); 984 setSchemaFile(mru, schemaFile); 985 } 986 catch (DirectoryException de) 987 { 988 logger.traceException(de); 989 990 LocalizableMessage message = WARN_CONFIG_SCHEMA_CANNOT_PARSE_MRU.get( 991 schemaFile, de.getMessageObject()); 992 reportError(failOnError, de, message); 993 continue; 994 } 995 catch (Exception e) 996 { 997 logger.traceException(e); 998 999 LocalizableMessage message = WARN_CONFIG_SCHEMA_CANNOT_PARSE_MRU.get( 1000 schemaFile, v + ": " + getExceptionMessage(e)); 1001 reportError(failOnError, e, message); 1002 continue; 1003 } 1004 1005 // Register it with the schema. We will allow duplicates, with the 1006 // later definition overriding any earlier definition, but we want 1007 // to trap them and log a warning. 1008 try 1009 { 1010 schema.registerMatchingRuleUse(mru, failOnError); 1011 } 1012 catch (DirectoryException de) 1013 { 1014 logger.traceException(de); 1015 1016 logger.warn(WARN_CONFIG_SCHEMA_CONFLICTING_MRU, schemaFile, de.getMessageObject()); 1017 1018 try 1019 { 1020 schema.registerMatchingRuleUse(mru, true); 1021 } 1022 catch (Exception e) 1023 { 1024 // This should never happen. 1025 logger.traceException(e); 1026 } 1027 } 1028 } 1029 } 1030 } 1031 } 1032 1033 1034 1035 /** 1036 * This method checks if a given attribute is an attribute that 1037 * is used by the definition of the schema. 1038 * 1039 * @param attribute The attribute to be checked. 1040 * @return true if the attribute is part of the schema definition, 1041 * false if the attribute is not part of the schema 1042 * definition. 1043 */ 1044 public static boolean isSchemaAttribute(Attribute attribute) 1045 { 1046 String attributeOid = attribute.getAttributeDescription().getAttributeType().getOID(); 1047 return attributeOid.equals("2.5.21.1") || 1048 attributeOid.equals("2.5.21.2") || 1049 attributeOid.equals("2.5.21.4") || 1050 attributeOid.equals("2.5.21.5") || 1051 attributeOid.equals("2.5.21.6") || 1052 attributeOid.equals("2.5.21.7") || 1053 attributeOid.equals("2.5.21.8") || 1054 attributeOid.equals("2.5.4.3") || 1055 attributeOid.equals("1.3.6.1.4.1.1466.101.120.16") || 1056 attributeOid.equals("cn-oid") || 1057 attributeOid.equals("attributetypes-oid") || 1058 attributeOid.equals("objectclasses-oid") || 1059 attributeOid.equals("matchingrules-oid") || 1060 attributeOid.equals("matchingruleuse-oid") || 1061 attributeOid.equals("nameformdescription-oid") || 1062 attributeOid.equals("ditcontentrules-oid") || 1063 attributeOid.equals("ditstructurerules-oid") || 1064 attributeOid.equals("ldapsyntaxes-oid"); 1065 } 1066} 1067