001 /*
002 * CDDL HEADER START
003 *
004 * The contents of this file are subject to the terms of the
005 * Common Development and Distribution License, Version 1.0 only
006 * (the "License"). You may not use this file except in compliance
007 * with the License.
008 *
009 * You can obtain a copy of the license at
010 * trunk/opends/resource/legal-notices/OpenDS.LICENSE
011 * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
012 * See the License for the specific language governing permissions
013 * and limitations under the License.
014 *
015 * When distributing Covered Code, include this CDDL HEADER in each
016 * file and include the License file at
017 * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
018 * add the following below this CDDL HEADER, with the fields enclosed
019 * by brackets "[]" replaced with your own identifying information:
020 * Portions Copyright [yyyy] [name of copyright owner]
021 *
022 * CDDL HEADER END
023 *
024 *
025 * Copyright 2006-2008 Sun Microsystems, Inc.
026 */
027 package org.opends.server.core;
028 import org.opends.messages.Message;
029
030
031
032 import java.io.File;
033 import java.util.ArrayList;
034 import java.util.Arrays;
035 import java.util.LinkedList;
036 import java.util.List;
037
038 import org.opends.server.api.ConfigHandler;
039 import org.opends.server.config.ConfigException;
040 import org.opends.server.schema.AttributeTypeSyntax;
041 import org.opends.server.schema.DITContentRuleSyntax;
042 import org.opends.server.schema.DITStructureRuleSyntax;
043 import org.opends.server.schema.MatchingRuleUseSyntax;
044 import org.opends.server.schema.NameFormSyntax;
045 import org.opends.server.schema.ObjectClassSyntax;
046 import org.opends.server.types.Attribute;
047 import org.opends.server.types.AttributeType;
048 import org.opends.server.types.AttributeValue;
049 import org.opends.server.types.DirectoryException;
050 import org.opends.server.types.DITContentRule;
051 import org.opends.server.types.DITStructureRule;
052 import org.opends.server.types.Entry;
053 import org.opends.server.types.InitializationException;
054 import org.opends.server.types.LDIFImportConfig;
055 import org.opends.server.types.MatchingRuleUse;
056 import org.opends.server.types.Modification;
057 import org.opends.server.types.ModificationType;
058 import org.opends.server.types.NameForm;
059 import org.opends.server.types.ObjectClass;
060 import org.opends.server.types.Schema;
061 import org.opends.server.util.LDIFReader;
062
063 import static org.opends.server.config.ConfigConstants.*;
064 import org.opends.server.types.DebugLogLevel;
065 import static org.opends.server.loggers.debug.DebugLogger.*;
066 import static org.opends.server.loggers.ErrorLogger.*;
067 import org.opends.server.loggers.debug.DebugTracer;
068 import static org.opends.messages.ConfigMessages.*;
069 import static org.opends.server.schema.SchemaConstants.*;
070 import static org.opends.server.util.ServerConstants.*;
071 import static org.opends.server.util.StaticUtils.*;
072
073
074
075 /**
076 * This class defines a utility that will be used to manage the interaction with
077 * the Directory Server schema. It will be used to initially load all of the
078 * matching rules and attribute syntaxes that have been defined in the
079 * configuration, and will then read the actual schema definitions. At present,
080 * only attribute types and objectclasses are supported in the schema config
081 * files. Other components like DIT content rules, DIT structure rules, name
082 * forms, and matching rule use definitions will be ignored.
083 */
084 public class SchemaConfigManager
085 {
086 /**
087 * The tracer object for the debug logger.
088 */
089 private static final DebugTracer TRACER = getTracer();
090
091 // The schema that has been parsed from the server configuration.
092 private Schema schema;
093
094 // The configuration handler for the Directory Server.
095 private ConfigHandler configHandler;
096
097
098
099 /**
100 * Creates a new instance of this schema config manager.
101 */
102 public SchemaConfigManager()
103 {
104 configHandler = DirectoryServer.getConfigHandler();
105
106 schema = new Schema();
107 }
108
109
110
111 /**
112 * Retrieves the path to the directory containing the server schema files.
113 *
114 * @return The path to the directory containing the server schema files.
115 */
116 public static String getSchemaDirectoryPath()
117 {
118 File schemaDir =
119 DirectoryServer.getEnvironmentConfig().getSchemaDirectory();
120 if (schemaDir != null) {
121 return schemaDir.getAbsolutePath();
122 } else {
123 return null;
124 }
125 }
126
127
128
129 /**
130 * Retrieves a reference to the schema information that has been read from the
131 * server configuration. Note that this information will not be complete
132 * until the <CODE>initializeMatchingRules</CODE>,
133 * <CODE>initializeAttributeSyntaxes</CODE>, and
134 * <CODE>initializeAttributeTypesAndObjectClasses</CODE> methods have been
135 * called.
136 *
137 * @return A reference to the schema information that has been read from the
138 * server configuration.
139 */
140 public Schema getSchema()
141 {
142 return schema;
143 }
144
145
146
147 /**
148 * Initializes all the matching rules defined in the Directory Server
149 * configuration. This should only be called at Directory Server startup.
150 *
151 * @throws ConfigException If a configuration problem causes the matching
152 * rule initialization process to fail.
153 *
154 * @throws InitializationException If a problem occurs while initializing
155 * the matching rules that is not related to
156 * the server configuration.
157 */
158 public void initializeMatchingRules()
159 throws ConfigException, InitializationException
160 {
161 MatchingRuleConfigManager matchingRuleConfigManager =
162 new MatchingRuleConfigManager();
163 matchingRuleConfigManager.initializeMatchingRules();
164 }
165
166
167
168 /**
169 * Initializes all the attribute syntaxes defined in the Directory Server
170 * configuration. This should only be called at Directory Server startup.
171 *
172 * @throws ConfigException If a configuration problem causes the syntax
173 * initialization process to fail.
174 *
175 * @throws InitializationException If a problem occurs while initializing
176 * the syntaxes that is not related to the
177 * server configuration.
178 */
179 public void initializeAttributeSyntaxes()
180 throws ConfigException, InitializationException
181 {
182 AttributeSyntaxConfigManager syntaxConfigManager =
183 new AttributeSyntaxConfigManager();
184 syntaxConfigManager.initializeAttributeSyntaxes();
185 }
186
187
188
189 /**
190 * Initializes all the attribute type, object class, name form, DIT content
191 * rule, DIT structure rule, and matching rule use definitions by reading the
192 * server schema files. These files will be located in a single directory and
193 * will be processed in lexicographic order. However, to make the order
194 * easier to understand, they may be prefixed with a two digit number (with a
195 * leading zero if necessary) so that they will be read in numeric order.
196 * This should only be called at Directory Server startup.
197 *
198 * @throws ConfigException If a configuration problem causes the schema
199 * element initialization to fail.
200 *
201 * @throws InitializationException If a problem occurs while initializing
202 * the schema elements that is not related
203 * to the server configuration.
204 */
205 public void initializeSchemaFromFiles()
206 throws ConfigException, InitializationException
207 {
208 // Construct the path to the directory that should contain the schema files
209 // and make sure that it exists and is a directory. Get a list of the files
210 // in that directory sorted in alphabetic order.
211 String schemaDirPath = getSchemaDirectoryPath();
212 File schemaDir = new File(schemaDirPath);
213 long oldestModificationTime = -1L;
214 long youngestModificationTime = -1L;
215 String[] fileNames;
216
217 try
218 {
219 if (schemaDirPath == null || ! schemaDir.exists())
220 {
221 Message message = ERR_CONFIG_SCHEMA_NO_SCHEMA_DIR.get(schemaDirPath);
222 throw new InitializationException(message);
223 }
224 else if (! schemaDir.isDirectory())
225 {
226 Message message =
227 ERR_CONFIG_SCHEMA_DIR_NOT_DIRECTORY.get(schemaDirPath);
228 throw new InitializationException(message);
229 }
230
231 File[] schemaDirFiles = schemaDir.listFiles();
232 ArrayList<String> fileList = new ArrayList<String>(schemaDirFiles.length);
233 for (File f : schemaDirFiles)
234 {
235 if (f.isFile())
236 {
237 fileList.add(f.getName());
238 }
239
240 long modificationTime = f.lastModified();
241 if ((oldestModificationTime <= 0L) ||
242 (modificationTime < oldestModificationTime))
243 {
244 oldestModificationTime = modificationTime;
245 }
246
247 if ((youngestModificationTime <= 0) ||
248 (modificationTime > youngestModificationTime))
249 {
250 youngestModificationTime = modificationTime;
251 }
252 }
253
254 fileNames = new String[fileList.size()];
255 fileList.toArray(fileNames);
256 Arrays.sort(fileNames);
257 }
258 catch (InitializationException ie)
259 {
260 if (debugEnabled())
261 {
262 TRACER.debugCaught(DebugLogLevel.ERROR, ie);
263 }
264
265 throw ie;
266 }
267 catch (Exception e)
268 {
269 if (debugEnabled())
270 {
271 TRACER.debugCaught(DebugLogLevel.ERROR, e);
272 }
273
274 Message message = ERR_CONFIG_SCHEMA_CANNOT_LIST_FILES.get(
275 schemaDirPath, getExceptionMessage(e));
276 throw new InitializationException(message, e);
277 }
278
279
280 // If the oldest and youngest modification timestamps didn't get set for
281 // some reason, then set them to the current time.
282 if (oldestModificationTime <= 0)
283 {
284 oldestModificationTime = System.currentTimeMillis();
285 }
286
287 if (youngestModificationTime <= 0)
288 {
289 youngestModificationTime = oldestModificationTime;
290 }
291
292 schema.setOldestModificationTime(oldestModificationTime);
293 schema.setYoungestModificationTime(youngestModificationTime);
294
295
296 // Iterate through the schema files and read them as an LDIF file containing
297 // a single entry. Then get the attributeTypes and objectClasses attributes
298 // from that entry and parse them to initialize the server schema.
299 for (String schemaFile : fileNames)
300 {
301 loadSchemaFile(schema, schemaFile, false);
302 }
303 }
304
305
306
307 /**
308 * Loads the contents of the specified schema file into the provided schema.
309 *
310 * @param schema The schema in which the contents of the schema file are
311 * to be loaded.
312 * @param schemaFile The name of the schema file to be loaded into the
313 * provided schema.
314 *
315 * @return A list of the modifications that could be performed in order to
316 * obtain the contents of the file.
317 *
318 * @throws ConfigException If a configuration problem causes the schema
319 * element initialization to fail.
320 *
321 * @throws InitializationException If a problem occurs while initializing
322 * the schema elements that is not related
323 * to the server configuration.
324 */
325 public static List<Modification> loadSchemaFile(Schema schema,
326 String schemaFile)
327 throws ConfigException, InitializationException
328 {
329 return loadSchemaFile(schema, schemaFile, true);
330 }
331
332
333
334 /**
335 * Loads the contents of the specified schema file into the provided schema.
336 *
337 * @param schema The schema in which the contents of the schema file
338 * are to be loaded.
339 * @param schemaFile The name of the schema file to be loaded into the
340 * provided schema.
341 * @param failOnError If {@code true}, indicates that this method should
342 * throw an exception if certain kinds of errors occur.
343 * If {@code false}, indicates that this method should
344 * log an error message and return without an exception.
345 * This should only be {@code false} when called from
346 * {@code initializeSchemaFromFiles}.
347 *
348 * @return A list of the modifications that could be performed in order to
349 * obtain the contents of the file, or {@code null} if a problem
350 * occurred and {@code failOnError} is {@code false}.
351 *
352 * @throws ConfigException If a configuration problem causes the schema
353 * element initialization to fail.
354 *
355 * @throws InitializationException If a problem occurs while initializing
356 * the schema elements that is not related
357 * to the server configuration.
358 */
359 private static List<Modification> loadSchemaFile(Schema schema,
360 String schemaFile,
361 boolean failOnError)
362 throws ConfigException, InitializationException
363 {
364 // Create an LDIF reader to use when reading the files.
365 String schemaDirPath = getSchemaDirectoryPath();
366 LDIFReader reader;
367 try
368 {
369 File f = new File(schemaDirPath, schemaFile);
370 reader = new LDIFReader(new LDIFImportConfig(f.getAbsolutePath()));
371 }
372 catch (Exception e)
373 {
374 if (debugEnabled())
375 {
376 TRACER.debugCaught(DebugLogLevel.ERROR, e);
377 }
378
379 Message message = WARN_CONFIG_SCHEMA_CANNOT_OPEN_FILE.get(
380 schemaFile, schemaDirPath, getExceptionMessage(e));
381
382 if (failOnError)
383 {
384 throw new ConfigException(message);
385 }
386 else
387 {
388 logError(message);
389 return null;
390 }
391 }
392
393
394 // Read the LDIF entry from the file and close the file.
395 Entry entry;
396 try
397 {
398 entry = reader.readEntry(false);
399
400 if (entry == null)
401 {
402 // The file was empty -- skip it.
403 reader.close();
404 return new LinkedList<Modification>();
405 }
406 }
407 catch (Exception e)
408 {
409 if (debugEnabled())
410 {
411 TRACER.debugCaught(DebugLogLevel.ERROR, e);
412 }
413
414 Message message = WARN_CONFIG_SCHEMA_CANNOT_READ_LDIF_ENTRY.get(
415 schemaFile, schemaDirPath, getExceptionMessage(e));
416
417 if (failOnError)
418 {
419 throw new InitializationException(message, e);
420 }
421 else
422 {
423 logError(message);
424 return null;
425 }
426 }
427
428 // If there are any more entries in the file, then print a warning message.
429 try
430 {
431 Entry e = reader.readEntry(false);
432 if (e != null)
433 {
434 Message message = WARN_CONFIG_SCHEMA_MULTIPLE_ENTRIES_IN_FILE.get(
435 schemaFile, schemaDirPath);
436 logError(message);
437 }
438 }
439 catch (Exception e)
440 {
441 if (debugEnabled())
442 {
443 TRACER.debugCaught(DebugLogLevel.ERROR, e);
444 }
445
446 Message message = WARN_CONFIG_SCHEMA_UNPARSEABLE_EXTRA_DATA_IN_FILE.get(
447 schemaFile, schemaDirPath, getExceptionMessage(e));
448 logError(message);
449 }
450
451 try
452 {
453 reader.close();
454 }
455 catch (Exception e)
456 {
457 if (debugEnabled())
458 {
459 TRACER.debugCaught(DebugLogLevel.ERROR, e);
460 }
461 }
462
463
464 // Get the attributeTypes attribute from the entry.
465 LinkedList<Modification> mods = new LinkedList<Modification>();
466 AttributeTypeSyntax attrTypeSyntax;
467 try
468 {
469 attrTypeSyntax = (AttributeTypeSyntax)
470 schema.getSyntax(SYNTAX_ATTRIBUTE_TYPE_OID);
471 if (attrTypeSyntax == null)
472 {
473 attrTypeSyntax = new AttributeTypeSyntax();
474 attrTypeSyntax.initializeSyntax(null);
475 }
476 }
477 catch (Exception e)
478 {
479 if (debugEnabled())
480 {
481 TRACER.debugCaught(DebugLogLevel.ERROR, e);
482 }
483
484 attrTypeSyntax = new AttributeTypeSyntax();
485 attrTypeSyntax.initializeSyntax(null);
486 }
487
488 AttributeType attributeAttrType =
489 schema.getAttributeType(ATTR_ATTRIBUTE_TYPES_LC);
490 if (attributeAttrType == null)
491 {
492 attributeAttrType =
493 DirectoryServer.getDefaultAttributeType(ATTR_ATTRIBUTE_TYPES,
494 attrTypeSyntax);
495 }
496
497 List<Attribute> attrList = entry.getAttribute(attributeAttrType);
498 if ((attrList != null) && (! attrList.isEmpty()))
499 {
500 for (Attribute a : attrList)
501 {
502 mods.add(new Modification(ModificationType.ADD, a.duplicate()));
503 }
504 }
505
506
507 // Get the objectClasses attribute from the entry.
508 ObjectClassSyntax ocSyntax;
509 try
510 {
511 ocSyntax = (ObjectClassSyntax) schema.getSyntax(SYNTAX_OBJECTCLASS_OID);
512 if (ocSyntax == null)
513 {
514 ocSyntax = new ObjectClassSyntax();
515 ocSyntax.initializeSyntax(null);
516 }
517 }
518 catch (Exception e)
519 {
520 if (debugEnabled())
521 {
522 TRACER.debugCaught(DebugLogLevel.ERROR, e);
523 }
524
525 ocSyntax = new ObjectClassSyntax();
526 ocSyntax.initializeSyntax(null);
527 }
528
529 AttributeType objectclassAttrType =
530 schema.getAttributeType(ATTR_OBJECTCLASSES_LC);
531 if (objectclassAttrType == null)
532 {
533 objectclassAttrType =
534 DirectoryServer.getDefaultAttributeType(ATTR_OBJECTCLASSES,
535 ocSyntax);
536 }
537
538 List<Attribute> ocList = entry.getAttribute(objectclassAttrType);
539 if ((ocList != null) && (! ocList.isEmpty()))
540 {
541 for (Attribute a : ocList)
542 {
543 mods.add(new Modification(ModificationType.ADD, a.duplicate()));
544 }
545 }
546
547
548 // Get the name forms attribute from the entry.
549 NameFormSyntax nfSyntax;
550 try
551 {
552 nfSyntax = (NameFormSyntax) schema.getSyntax(SYNTAX_NAME_FORM_OID);
553 if (nfSyntax == null)
554 {
555 nfSyntax = new NameFormSyntax();
556 nfSyntax.initializeSyntax(null);
557 }
558 }
559 catch (Exception e)
560 {
561 if (debugEnabled())
562 {
563 TRACER.debugCaught(DebugLogLevel.ERROR, e);
564 }
565
566 nfSyntax = new NameFormSyntax();
567 nfSyntax.initializeSyntax(null);
568 }
569
570 AttributeType nameFormAttrType =
571 schema.getAttributeType(ATTR_NAME_FORMS_LC);
572 if (nameFormAttrType == null)
573 {
574 nameFormAttrType =
575 DirectoryServer.getDefaultAttributeType(ATTR_NAME_FORMS, nfSyntax);
576 }
577
578 List<Attribute> nfList = entry.getAttribute(nameFormAttrType);
579 if ((nfList != null) && (! nfList.isEmpty()))
580 {
581 for (Attribute a : nfList)
582 {
583 mods.add(new Modification(ModificationType.ADD, a.duplicate()));
584 }
585 }
586
587
588 // Get the DIT content rules attribute from the entry.
589 DITContentRuleSyntax dcrSyntax;
590 try
591 {
592 dcrSyntax = (DITContentRuleSyntax)
593 schema.getSyntax(SYNTAX_DIT_CONTENT_RULE_OID);
594 if (dcrSyntax == null)
595 {
596 dcrSyntax = new DITContentRuleSyntax();
597 dcrSyntax.initializeSyntax(null);
598 }
599 }
600 catch (Exception e)
601 {
602 if (debugEnabled())
603 {
604 TRACER.debugCaught(DebugLogLevel.ERROR, e);
605 }
606
607 dcrSyntax = new DITContentRuleSyntax();
608 dcrSyntax.initializeSyntax(null);
609 }
610
611 AttributeType dcrAttrType =
612 schema.getAttributeType(ATTR_DIT_CONTENT_RULES_LC);
613 if (dcrAttrType == null)
614 {
615 dcrAttrType =
616 DirectoryServer.getDefaultAttributeType(ATTR_DIT_CONTENT_RULES,
617 dcrSyntax);
618 }
619
620 List<Attribute> dcrList = entry.getAttribute(dcrAttrType);
621 if ((dcrList != null) && (! dcrList.isEmpty()))
622 {
623 for (Attribute a : dcrList)
624 {
625 mods.add(new Modification(ModificationType.ADD, a.duplicate()));
626 }
627 }
628
629
630 // Get the DIT structure rules attribute from the entry.
631 DITStructureRuleSyntax dsrSyntax;
632 try
633 {
634 dsrSyntax = (DITStructureRuleSyntax)
635 schema.getSyntax(SYNTAX_DIT_STRUCTURE_RULE_OID);
636 if (dsrSyntax == null)
637 {
638 dsrSyntax = new DITStructureRuleSyntax();
639 dsrSyntax.initializeSyntax(null);
640 }
641 }
642 catch (Exception e)
643 {
644 if (debugEnabled())
645 {
646 TRACER.debugCaught(DebugLogLevel.ERROR, e);
647 }
648
649 dsrSyntax = new DITStructureRuleSyntax();
650 dsrSyntax.initializeSyntax(null);
651 }
652
653 AttributeType dsrAttrType =
654 schema.getAttributeType(ATTR_DIT_STRUCTURE_RULES_LC);
655 if (dsrAttrType == null)
656 {
657 dsrAttrType =
658 DirectoryServer.getDefaultAttributeType(ATTR_DIT_STRUCTURE_RULES,
659 dsrSyntax);
660 }
661
662 List<Attribute> dsrList = entry.getAttribute(dsrAttrType);
663 if ((dsrList != null) && (! dsrList.isEmpty()))
664 {
665 for (Attribute a : dsrList)
666 {
667 mods.add(new Modification(ModificationType.ADD, a.duplicate()));
668 }
669 }
670
671
672 // Get the matching rule uses attribute from the entry.
673 MatchingRuleUseSyntax mruSyntax;
674 try
675 {
676 mruSyntax = (MatchingRuleUseSyntax)
677 schema.getSyntax(SYNTAX_MATCHING_RULE_USE_OID);
678 if (mruSyntax == null)
679 {
680 mruSyntax = new MatchingRuleUseSyntax();
681 mruSyntax.initializeSyntax(null);
682 }
683 }
684 catch (Exception e)
685 {
686 if (debugEnabled())
687 {
688 TRACER.debugCaught(DebugLogLevel.ERROR, e);
689 }
690
691 mruSyntax = new MatchingRuleUseSyntax();
692 mruSyntax.initializeSyntax(null);
693 }
694
695 AttributeType mruAttrType =
696 schema.getAttributeType(ATTR_MATCHING_RULE_USE_LC);
697 if (mruAttrType == null)
698 {
699 mruAttrType =
700 DirectoryServer.getDefaultAttributeType(ATTR_MATCHING_RULE_USE,
701 mruSyntax);
702 }
703
704 List<Attribute> mruList = entry.getAttribute(mruAttrType);
705 if ((mruList != null) && (! mruList.isEmpty()))
706 {
707 for (Attribute a : mruList)
708 {
709 mods.add(new Modification(ModificationType.ADD, a.duplicate()));
710 }
711 }
712
713 // Loop on all the attribute of the schema entry to
714 // find the extra attribute that shoule be loaded in the Schema.
715 for (Attribute attribute : entry.getAttributes())
716 {
717 if (!isSchemaAttribute(attribute))
718 {
719 schema.addExtraAttribute(attribute.getName(), attribute);
720 }
721 }
722
723 // Parse the attribute type definitions if there are any.
724 if (attrList != null)
725 {
726 for (Attribute a : attrList)
727 {
728 for (AttributeValue v : a.getValues())
729 {
730 // Parse the attribute type.
731 AttributeType attrType;
732 try
733 {
734 attrType = AttributeTypeSyntax.decodeAttributeType(v.getValue(),
735 schema, false);
736 attrType.setExtraProperty(SCHEMA_PROPERTY_FILENAME, (String) null);
737 attrType.setSchemaFile(schemaFile);
738 }
739 catch (DirectoryException de)
740 {
741 if (debugEnabled())
742 {
743 TRACER.debugCaught(DebugLogLevel.ERROR, de);
744 }
745
746 Message message = WARN_CONFIG_SCHEMA_CANNOT_PARSE_ATTR_TYPE.get(
747 schemaFile, de.getMessageObject());
748
749 if (failOnError)
750 {
751 throw new ConfigException(message, de);
752 }
753 else
754 {
755 logError(message);
756 continue;
757 }
758 }
759 catch (Exception e)
760 {
761 if (debugEnabled())
762 {
763 TRACER.debugCaught(DebugLogLevel.ERROR, e);
764 }
765
766 Message message = WARN_CONFIG_SCHEMA_CANNOT_PARSE_ATTR_TYPE.get(
767 schemaFile, v.getStringValue() + ": " +
768 getExceptionMessage(e));
769 if (failOnError)
770 {
771 throw new ConfigException(message, e);
772 }
773 else
774 {
775 logError(message);
776 continue;
777 }
778 }
779
780 // Register it with the schema. We will allow duplicates, with the
781 // later definition overriding any earlier definition, but we want
782 // to trap them and log a warning.
783 try
784 {
785 schema.registerAttributeType(attrType, failOnError);
786 }
787 catch (DirectoryException de)
788 {
789 if (debugEnabled())
790 {
791 TRACER.debugCaught(DebugLogLevel.ERROR, de);
792 }
793
794 Message message = WARN_CONFIG_SCHEMA_CONFLICTING_ATTR_TYPE.get(
795 schemaFile, de.getMessageObject());
796 logError(message);
797
798 try
799 {
800 schema.registerAttributeType(attrType, true);
801 }
802 catch (Exception e)
803 {
804 // This should never happen.
805 if (debugEnabled())
806 {
807 TRACER.debugCaught(DebugLogLevel.ERROR, e);
808 }
809 }
810 }
811 }
812 }
813 }
814
815
816 // Parse the objectclass definitions if there are any.
817 if (ocList != null)
818 {
819 for (Attribute a : ocList)
820 {
821 for (AttributeValue v : a.getValues())
822 {
823 // Parse the objectclass.
824 ObjectClass oc;
825 try
826 {
827 oc =
828 ObjectClassSyntax.decodeObjectClass(v.getValue(), schema, false);
829 oc.setExtraProperty(SCHEMA_PROPERTY_FILENAME, (String) null);
830 oc.setSchemaFile(schemaFile);
831 }
832 catch (DirectoryException de)
833 {
834 if (debugEnabled())
835 {
836 TRACER.debugCaught(DebugLogLevel.ERROR, de);
837 }
838
839 Message message = WARN_CONFIG_SCHEMA_CANNOT_PARSE_OC.get(
840 schemaFile,
841 de.getMessageObject());
842
843 if (failOnError)
844 {
845 throw new ConfigException(message, de);
846 }
847 else
848 {
849 logError(message);
850 continue;
851 }
852 }
853 catch (Exception e)
854 {
855 if (debugEnabled())
856 {
857 TRACER.debugCaught(DebugLogLevel.ERROR, e);
858 }
859
860 Message message = WARN_CONFIG_SCHEMA_CANNOT_PARSE_OC.get(
861 schemaFile,
862 v.getStringValue() + ": " + getExceptionMessage(e));
863
864 if (failOnError)
865 {
866 throw new ConfigException(message, e);
867 }
868 else
869 {
870 logError(message);
871 continue;
872 }
873 }
874
875 // Register it with the schema. We will allow duplicates, with the
876 // later definition overriding any earlier definition, but we want
877 // to trap them and log a warning.
878 try
879 {
880 schema.registerObjectClass(oc, failOnError);
881 }
882 catch (DirectoryException de)
883 {
884 if (debugEnabled())
885 {
886 TRACER.debugCaught(DebugLogLevel.ERROR, de);
887 }
888
889 Message message = WARN_CONFIG_SCHEMA_CONFLICTING_OC.get(
890 schemaFile, de.getMessageObject());
891 logError(message);
892
893 try
894 {
895 schema.registerObjectClass(oc, true);
896 }
897 catch (Exception e)
898 {
899 // This should never happen.
900 if (debugEnabled())
901 {
902 TRACER.debugCaught(DebugLogLevel.ERROR, e);
903 }
904 }
905 }
906 }
907 }
908 }
909
910
911 // Parse the name form definitions if there are any.
912 if (nfList != null)
913 {
914 for (Attribute a : nfList)
915 {
916 for (AttributeValue v : a.getValues())
917 {
918 // Parse the name form.
919 NameForm nf;
920 try
921 {
922 nf = NameFormSyntax.decodeNameForm(v.getValue(), schema, false);
923 nf.getExtraProperties().remove(SCHEMA_PROPERTY_FILENAME);
924 nf.setSchemaFile(schemaFile);
925 }
926 catch (DirectoryException de)
927 {
928 if (debugEnabled())
929 {
930 TRACER.debugCaught(DebugLogLevel.ERROR, de);
931 }
932
933 Message message = WARN_CONFIG_SCHEMA_CANNOT_PARSE_NAME_FORM.get(
934 schemaFile, de.getMessageObject());
935 if (failOnError)
936 {
937 throw new ConfigException(message, de);
938 }
939 else
940 {
941 logError(message);
942 continue;
943 }
944 }
945 catch (Exception e)
946 {
947 if (debugEnabled())
948 {
949 TRACER.debugCaught(DebugLogLevel.ERROR, e);
950 }
951
952 Message message = WARN_CONFIG_SCHEMA_CANNOT_PARSE_NAME_FORM.get(
953 schemaFile, v.getStringValue() + ": " +
954 getExceptionMessage(e));
955
956 if (failOnError)
957 {
958 throw new ConfigException(message, e);
959 }
960 else
961 {
962 logError(message);
963 continue;
964 }
965 }
966
967 // Register it with the schema. We will allow duplicates, with the
968 // later definition overriding any earlier definition, but we want
969 // to trap them and log a warning.
970 try
971 {
972 schema.registerNameForm(nf, failOnError);
973 }
974 catch (DirectoryException de)
975 {
976 if (debugEnabled())
977 {
978 TRACER.debugCaught(DebugLogLevel.ERROR, de);
979 }
980
981 Message message = WARN_CONFIG_SCHEMA_CONFLICTING_NAME_FORM.get(
982 schemaFile, de.getMessageObject());
983 logError(message);
984
985 try
986 {
987 schema.registerNameForm(nf, true);
988 }
989 catch (Exception e)
990 {
991 // This should never happen.
992 if (debugEnabled())
993 {
994 TRACER.debugCaught(DebugLogLevel.ERROR, e);
995 }
996 }
997 }
998 }
999 }
1000 }
1001
1002
1003 // Parse the DIT content rule definitions if there are any.
1004 if (dcrList != null)
1005 {
1006 for (Attribute a : dcrList)
1007 {
1008 for (AttributeValue v : a.getValues())
1009 {
1010 // Parse the DIT content rule.
1011 DITContentRule dcr;
1012 try
1013 {
1014 dcr = DITContentRuleSyntax.decodeDITContentRule(
1015 v.getValue(), schema, false);
1016 dcr.getExtraProperties().remove(SCHEMA_PROPERTY_FILENAME);
1017 dcr.setSchemaFile(schemaFile);
1018 }
1019 catch (DirectoryException de)
1020 {
1021 if (debugEnabled())
1022 {
1023 TRACER.debugCaught(DebugLogLevel.ERROR, de);
1024 }
1025
1026 Message message = WARN_CONFIG_SCHEMA_CANNOT_PARSE_DCR.get(
1027 schemaFile, de.getMessageObject());
1028
1029 if (failOnError)
1030 {
1031 throw new ConfigException(message, de);
1032 }
1033 else
1034 {
1035 logError(message);
1036 continue;
1037 }
1038 }
1039 catch (Exception e)
1040 {
1041 if (debugEnabled())
1042 {
1043 TRACER.debugCaught(DebugLogLevel.ERROR, e);
1044 }
1045
1046 Message message = WARN_CONFIG_SCHEMA_CANNOT_PARSE_DCR.get(
1047 schemaFile,v.getStringValue() + ": " +
1048 getExceptionMessage(e));
1049
1050 if (failOnError)
1051 {
1052 throw new ConfigException(message, e);
1053 }
1054 else
1055 {
1056 logError(message);
1057 continue;
1058 }
1059 }
1060
1061 // Register it with the schema. We will allow duplicates, with the
1062 // later definition overriding any earlier definition, but we want
1063 // to trap them and log a warning.
1064 try
1065 {
1066 schema.registerDITContentRule(dcr, failOnError);
1067 }
1068 catch (DirectoryException de)
1069 {
1070 if (debugEnabled())
1071 {
1072 TRACER.debugCaught(DebugLogLevel.ERROR, de);
1073 }
1074
1075 Message message = WARN_CONFIG_SCHEMA_CONFLICTING_DCR.get(
1076 schemaFile, de.getMessageObject());
1077 logError(message);
1078
1079 try
1080 {
1081 schema.registerDITContentRule(dcr, true);
1082 }
1083 catch (Exception e)
1084 {
1085 // This should never happen.
1086 if (debugEnabled())
1087 {
1088 TRACER.debugCaught(DebugLogLevel.ERROR, e);
1089 }
1090 }
1091 }
1092 }
1093 }
1094 }
1095
1096
1097 // Parse the DIT structure rule definitions if there are any.
1098 if (dsrList != null)
1099 {
1100 for (Attribute a : dsrList)
1101 {
1102 for (AttributeValue v : a.getValues())
1103 {
1104 // Parse the DIT content rule.
1105 DITStructureRule dsr;
1106 try
1107 {
1108 dsr = DITStructureRuleSyntax.decodeDITStructureRule(
1109 v.getValue(), schema, false);
1110 dsr.getExtraProperties().remove(SCHEMA_PROPERTY_FILENAME);
1111 dsr.setSchemaFile(schemaFile);
1112 }
1113 catch (DirectoryException de)
1114 {
1115 if (debugEnabled())
1116 {
1117 TRACER.debugCaught(DebugLogLevel.ERROR, de);
1118 }
1119
1120 Message message = WARN_CONFIG_SCHEMA_CANNOT_PARSE_DSR.get(
1121 schemaFile, de.getMessageObject());
1122
1123 if (failOnError)
1124 {
1125 throw new ConfigException(message, de);
1126 }
1127 else
1128 {
1129 logError(message);
1130 continue;
1131 }
1132 }
1133 catch (Exception e)
1134 {
1135 if (debugEnabled())
1136 {
1137 TRACER.debugCaught(DebugLogLevel.ERROR, e);
1138 }
1139
1140 Message message = WARN_CONFIG_SCHEMA_CANNOT_PARSE_DSR.get(
1141 schemaFile, v.getStringValue() + ": " +
1142 getExceptionMessage(e));
1143
1144 if (failOnError)
1145 {
1146 throw new ConfigException(message, e);
1147 }
1148 else
1149 {
1150 logError(message);
1151 continue;
1152 }
1153 }
1154
1155 // Register it with the schema. We will allow duplicates, with the
1156 // later definition overriding any earlier definition, but we want
1157 // to trap them and log a warning.
1158 try
1159 {
1160 schema.registerDITStructureRule(dsr, failOnError);
1161 }
1162 catch (DirectoryException de)
1163 {
1164 if (debugEnabled())
1165 {
1166 TRACER.debugCaught(DebugLogLevel.ERROR, de);
1167 }
1168
1169 Message message = WARN_CONFIG_SCHEMA_CONFLICTING_DSR.get(
1170 schemaFile, de.getMessageObject());
1171 logError(message);
1172
1173 try
1174 {
1175 schema.registerDITStructureRule(dsr, true);
1176 }
1177 catch (Exception e)
1178 {
1179 // This should never happen.
1180 if (debugEnabled())
1181 {
1182 TRACER.debugCaught(DebugLogLevel.ERROR, e);
1183 }
1184 }
1185 }
1186 }
1187 }
1188 }
1189
1190
1191 // Parse the matching rule use definitions if there are any.
1192 if (mruList != null)
1193 {
1194 for (Attribute a : mruList)
1195 {
1196 for (AttributeValue v : a.getValues())
1197 {
1198 // Parse the matching rule use definition.
1199 MatchingRuleUse mru;
1200 try
1201 {
1202 mru = MatchingRuleUseSyntax.decodeMatchingRuleUse(
1203 v.getValue(), schema, false);
1204 mru.getExtraProperties().remove(SCHEMA_PROPERTY_FILENAME);
1205 mru.setSchemaFile(schemaFile);
1206 }
1207 catch (DirectoryException de)
1208 {
1209 if (debugEnabled())
1210 {
1211 TRACER.debugCaught(DebugLogLevel.ERROR, de);
1212 }
1213
1214 Message message = WARN_CONFIG_SCHEMA_CANNOT_PARSE_MRU.get(
1215 schemaFile, de.getMessageObject());
1216
1217 if (failOnError)
1218 {
1219 throw new ConfigException(message, de);
1220 }
1221 else
1222 {
1223 logError(message);
1224 continue;
1225 }
1226 }
1227 catch (Exception e)
1228 {
1229 if (debugEnabled())
1230 {
1231 TRACER.debugCaught(DebugLogLevel.ERROR, e);
1232 }
1233
1234 Message message = WARN_CONFIG_SCHEMA_CANNOT_PARSE_MRU.get(
1235 schemaFile,
1236 v.getStringValue() + ": " +
1237 getExceptionMessage(e));
1238
1239 if (failOnError)
1240 {
1241 throw new ConfigException(message, e);
1242 }
1243 else
1244 {
1245 logError(message);
1246 continue;
1247 }
1248 }
1249
1250 // Register it with the schema. We will allow duplicates, with the
1251 // later definition overriding any earlier definition, but we want
1252 // to trap them and log a warning.
1253 try
1254 {
1255 schema.registerMatchingRuleUse(mru, failOnError);
1256 }
1257 catch (DirectoryException de)
1258 {
1259 if (debugEnabled())
1260 {
1261 TRACER.debugCaught(DebugLogLevel.ERROR, de);
1262 }
1263
1264 Message message = WARN_CONFIG_SCHEMA_CONFLICTING_MRU.get(
1265 schemaFile, de.getMessageObject());
1266 logError(message);
1267
1268 try
1269 {
1270 schema.registerMatchingRuleUse(mru, true);
1271 }
1272 catch (Exception e)
1273 {
1274 // This should never happen.
1275 if (debugEnabled())
1276 {
1277 TRACER.debugCaught(DebugLogLevel.ERROR, e);
1278 }
1279 }
1280 }
1281 }
1282 }
1283 }
1284
1285
1286 return mods;
1287 }
1288
1289
1290
1291 /**
1292 * This method checks if a given attribute is an attribute that
1293 * is used by the definition of the schema.
1294 *
1295 * @param attribute The attribute to be checked.
1296 * @return true if the attribute is part of the schema definition,
1297 * false if the attribute is not part of the schema
1298 * definition.
1299 */
1300 private static boolean isSchemaAttribute(Attribute attribute)
1301 {
1302 String attributeOid = attribute.getAttributeType().getOID();
1303 if (attributeOid.equals("2.5.21.1") ||
1304 attributeOid.equals("2.5.21.2") ||
1305 attributeOid.equals("2.5.21.4") ||
1306 attributeOid.equals("2.5.21.5") ||
1307 attributeOid.equals("2.5.21.6") ||
1308 attributeOid.equals("2.5.21.7") ||
1309 attributeOid.equals("2.5.21.8") ||
1310 attributeOid.equals("2.5.4.3") ||
1311 attributeOid.equals("attributetypes-oid") ||
1312 attributeOid.equals("objectclasses-oid") ||
1313 attributeOid.equals("matchingRules-oid") ||
1314 attributeOid.equals("matchingRuleUse-oid") ||
1315 attributeOid.equals("NameFormDescription-oid") ||
1316 attributeOid.equals("dITContentRules-oid") ||
1317 attributeOid.equals("dITStructureRules")
1318 )
1319 {
1320 return true;
1321 }
1322 else
1323 {
1324 return false;
1325 }
1326 }
1327 }
1328