From 62d649388ccf89adda304e65e2b49a81d5ce890c Mon Sep 17 00:00:00 2001
From: Nicolas Capponi <nicolas.capponi@forgerock.com>
Date: Wed, 01 Jun 2016 09:06:50 +0000
Subject: [PATCH] OPENDJ-3005 Migrate DITContentRule to SDK
---
/dev/null | 459 -------------
opendj-server-legacy/src/main/java/org/opends/server/schema/DITContentRuleSyntax.java | 1092 ---------------------------------
opendj-server-legacy/src/main/java/org/opends/server/core/DirectoryServer.java | 13
opendj-server-legacy/src/main/java/org/opends/server/backends/SchemaBackend.java | 126 ---
opendj-server-legacy/src/main/java/org/opends/server/types/Entry.java | 1
opendj-server-legacy/src/main/java/org/opends/server/types/DirectoryConfig.java | 1
opendj-server-legacy/src/main/java/org/opends/server/types/Schema.java | 195 +++--
opendj-server-legacy/src/main/java/org/opends/server/core/SchemaConfigManager.java | 37 -
opendj-server-legacy/src/test/java/org/opends/server/backends/SchemaBackendTestCase.java | 30
opendj-server-legacy/src/messages/org/opends/messages/schema.properties | 4
10 files changed, 163 insertions(+), 1,795 deletions(-)
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/backends/SchemaBackend.java b/opendj-server-legacy/src/main/java/org/opends/server/backends/SchemaBackend.java
index 9b73274..09a44bd 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/backends/SchemaBackend.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/backends/SchemaBackend.java
@@ -62,11 +62,11 @@
import org.forgerock.opendj.ldap.SearchScope;
import org.forgerock.opendj.ldap.schema.AttributeType;
import org.forgerock.opendj.ldap.schema.CoreSchema;
+import org.forgerock.opendj.ldap.schema.DITContentRule;
import org.forgerock.opendj.ldap.schema.MatchingRule;
import org.forgerock.opendj.ldap.schema.MatchingRuleUse;
import org.forgerock.opendj.ldap.schema.NameForm;
import org.forgerock.opendj.ldap.schema.ObjectClass;
-import org.forgerock.opendj.ldap.schema.ObjectClassType;
import org.forgerock.opendj.ldap.schema.SchemaElement;
import org.forgerock.opendj.server.config.server.SchemaBackendCfg;
import org.opends.server.api.AlertGenerator;
@@ -82,7 +82,6 @@
import org.opends.server.core.SearchOperation;
import org.opends.server.core.ServerContext;
import org.opends.server.schema.AttributeTypeSyntax;
-import org.opends.server.schema.DITContentRuleSyntax;
import org.opends.server.schema.DITStructureRuleSyntax;
import org.opends.server.schema.GeneralizedTimeSyntax;
import org.opends.server.schema.ServerSchemaElement;
@@ -92,7 +91,6 @@
import org.opends.server.types.Attributes;
import org.opends.server.types.BackupConfig;
import org.opends.server.types.BackupDirectory;
-import org.opends.server.types.DITContentRule;
import org.opends.server.types.DITStructureRule;
import org.opends.server.types.DirectoryException;
import org.opends.server.types.Entry;
@@ -581,7 +579,7 @@
operationalAttrs, ldapSyntaxesType, includeSchemaFile, false, true);
buildSchemaAttribute(schema.getNameForms(), userAttrs,
operationalAttrs, nameFormsType, includeSchemaFile, false, true);
- buildSchemaAttribute(schema.getDITContentRules().values(), userAttrs,
+ buildSchemaAttribute(schema.getDITContentRules(), userAttrs,
operationalAttrs, ditContentRulesType, includeSchemaFile, false, true);
buildSchemaAttribute(schema.getDITStructureRulesByID().values(), userAttrs,
operationalAttrs, ditStructureRulesType, includeSchemaFile, false, true);
@@ -776,21 +774,7 @@
{
for (ByteString v : a)
{
- DITContentRule dcr;
- try
- {
- dcr = DITContentRuleSyntax.decodeDITContentRule(v, newSchema, false);
- }
- catch (DirectoryException de)
- {
- logger.traceException(de);
-
- LocalizableMessage message = ERR_SCHEMA_MODIFY_CANNOT_DECODE_DCR.get(
- v, de.getMessageObject());
- throw new DirectoryException(
- ResultCode.INVALID_ATTRIBUTE_SYNTAX, message, de);
- }
-
+ DITContentRule dcr = newSchema.parseDITContentRule(v.toString());
addDITContentRule(dcr, newSchema, modifiedSchemaFiles);
}
}
@@ -886,21 +870,7 @@
{
for (ByteString v : a)
{
- DITContentRule dcr;
- try
- {
- dcr = DITContentRuleSyntax.decodeDITContentRule(v, newSchema, false);
- }
- catch (DirectoryException de)
- {
- logger.traceException(de);
-
- LocalizableMessage message = ERR_SCHEMA_MODIFY_CANNOT_DECODE_DCR.get(
- v, de.getMessageObject());
- throw new DirectoryException(
- ResultCode.INVALID_ATTRIBUTE_SYNTAX, message, de);
- }
-
+ DITContentRule dcr = newSchema.parseDITContentRule(v.toString());
removeDITContentRule(dcr, newSchema, modifiedSchemaFiles);
}
}
@@ -1280,7 +1250,7 @@
// Make sure that the attribute type isn't used as a required, optional, or
// prohibited attribute type in any DIT content rule.
- for (DITContentRule dcr : schema.getDITContentRules().values())
+ for (DITContentRule dcr : schema.getDITContentRules())
{
if (dcr.getRequiredAttributes().contains(removeType) ||
dcr.getOptionalAttributes().contains(removeType) ||
@@ -1540,7 +1510,7 @@
// Make sure that the objectclass isn't used as a structural or auxiliary
// class for any DIT content rule.
- for (DITContentRule dcr : schema.getDITContentRules().values())
+ for (DITContentRule dcr : schema.getDITContentRules())
{
if (dcr.getStructuralClass().equals(removeClass) ||
dcr.getAuxiliaryClasses().contains(removeClass))
@@ -1751,9 +1721,9 @@
// all of the names, which means that it's possible there could be more than
// one match (although if there is, then we'll refuse the operation).
DITContentRule existingDCR = null;
- for (DITContentRule dcr : schema.getDITContentRules().values())
+ for (DITContentRule dcr : schema.getDITContentRules())
{
- for (String name : ditContentRule.getNames().keySet())
+ for (String name : ditContentRule.getNames())
{
if (dcr.hasName(name))
{
@@ -1774,38 +1744,10 @@
}
}
- // Get the structural class for the new DIT content rule and see if there's
- // already an existing rule that is associated with that class. If there
- // is, then it will only be acceptable if it's the DIT content rule that we
- // are replacing (in which case we really do want to use the "!=" operator).
ObjectClass structuralClass = ditContentRule.getStructuralClass();
- DITContentRule existingRuleForClass =
- schema.getDITContentRule(structuralClass);
- if (existingRuleForClass != null && existingRuleForClass != existingDCR)
- {
- LocalizableMessage message = ERR_SCHEMA_MODIFY_STRUCTURAL_OC_CONFLICT_FOR_ADD_DCR.
- get(ditContentRule.getNameOrOID(), structuralClass.getNameOrOID(),
- existingRuleForClass.getNameOrOID());
- throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
- }
- // Make sure that the new DIT content rule doesn't reference an undefined
- // structural or auxiliary class, or an undefined required, optional, or
- // prohibited attribute type.
- if (! schema.hasObjectClass(structuralClass.getOID()))
- {
- LocalizableMessage message = ERR_SCHEMA_MODIFY_DCR_UNDEFINED_STRUCTURAL_OC.get(
- ditContentRule.getNameOrOID(), structuralClass.getNameOrOID());
- throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
- }
-
- if (structuralClass.getObjectClassType() != ObjectClassType.STRUCTURAL)
- {
- LocalizableMessage message = ERR_SCHEMA_MODIFY_DCR_OC_NOT_STRUCTURAL.get(
- ditContentRule.getNameOrOID(), structuralClass.getNameOrOID());
- throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
- }
-
+ // Make sure that the new DIT content rule doesn't reference an obsolete
+ // object class or attribute
if (structuralClass.isObsolete())
{
LocalizableMessage message = ERR_SCHEMA_MODIFY_DCR_STRUCTURAL_OC_OBSOLETE.get(
@@ -1815,18 +1757,6 @@
for (ObjectClass oc : ditContentRule.getAuxiliaryClasses())
{
- if (! schema.hasObjectClass(oc.getOID()))
- {
- LocalizableMessage message = ERR_SCHEMA_MODIFY_DCR_UNDEFINED_AUXILIARY_OC.get(
- ditContentRule.getNameOrOID(), oc.getNameOrOID());
- throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
- }
- if (oc.getObjectClassType() != ObjectClassType.AUXILIARY)
- {
- LocalizableMessage message = ERR_SCHEMA_MODIFY_DCR_OC_NOT_AUXILIARY.get(
- ditContentRule.getNameOrOID(), oc.getNameOrOID());
- throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
- }
if (oc.isObsolete())
{
LocalizableMessage message = ERR_SCHEMA_MODIFY_DCR_OBSOLETE_AUXILIARY_OC.get(
@@ -1837,13 +1767,7 @@
for (AttributeType at : ditContentRule.getRequiredAttributes())
{
- if (! schema.hasAttributeType(at.getOID()))
- {
- LocalizableMessage message = ERR_SCHEMA_MODIFY_DCR_UNDEFINED_REQUIRED_ATTR.get(
- ditContentRule.getNameOrOID(), at.getNameOrOID());
- throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
- }
- else if (at.isObsolete())
+ if (at.isObsolete())
{
LocalizableMessage message = ERR_SCHEMA_MODIFY_DCR_OBSOLETE_REQUIRED_ATTR.get(
ditContentRule.getNameOrOID(), at.getNameOrOID());
@@ -1853,13 +1777,7 @@
for (AttributeType at : ditContentRule.getOptionalAttributes())
{
- if (! schema.hasAttributeType(at.getOID()))
- {
- LocalizableMessage message = ERR_SCHEMA_MODIFY_DCR_UNDEFINED_OPTIONAL_ATTR.get(
- ditContentRule.getNameOrOID(), at.getNameOrOID());
- throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
- }
- else if (at.isObsolete())
+ if (at.isObsolete())
{
LocalizableMessage message = ERR_SCHEMA_MODIFY_DCR_OBSOLETE_OPTIONAL_ATTR.get(
ditContentRule.getNameOrOID(), at.getNameOrOID());
@@ -1869,13 +1787,7 @@
for (AttributeType at : ditContentRule.getProhibitedAttributes())
{
- if (! schema.hasAttributeType(at.getOID()))
- {
- LocalizableMessage message = ERR_SCHEMA_MODIFY_DCR_UNDEFINED_PROHIBITED_ATTR.get(
- ditContentRule.getNameOrOID(), at.getNameOrOID());
- throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
- }
- else if (at.isObsolete())
+ if (at.isObsolete())
{
LocalizableMessage message = ERR_SCHEMA_MODIFY_DCR_OBSOLETE_PROHIBITED_ATTR.get(
ditContentRule.getNameOrOID(), at.getNameOrOID());
@@ -1887,16 +1799,16 @@
// Otherwise, we're replacing an existing one.
if (existingDCR == null)
{
- schema.registerDITContentRule(ditContentRule, false);
- addNewSchemaElement(modifiedSchemaFiles, ditContentRule);
+ String schemaFile = addNewSchemaElement(modifiedSchemaFiles, new ServerSchemaElement(ditContentRule));
+ schema.registerDITContentRule(ditContentRule, schemaFile, false);
}
else
{
schema.deregisterDITContentRule(existingDCR);
- schema.registerDITContentRule(ditContentRule, false);
+ String schemaFile = replaceExistingSchemaElement(modifiedSchemaFiles, new ServerSchemaElement(ditContentRule),
+ new ServerSchemaElement(existingDCR));
+ schema.registerDITContentRule(ditContentRule, schemaFile, false);
schema.rebuildDependentElements(existingDCR);
- replaceExistingSchemaElement(modifiedSchemaFiles, ditContentRule,
- existingDCR);
}
}
@@ -2540,7 +2452,7 @@
// there is no hierarchical relationship between DIT content rules, we don't
// need to worry about ordering.
values = new LinkedHashSet<>();
- for (DITContentRule dcr : schema.getDITContentRules().values())
+ for (DITContentRule dcr : schema.getDITContentRules())
{
if (schemaFile.equals(getSchemaFile(dcr)))
{
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/core/DirectoryServer.java b/opendj-server-legacy/src/main/java/org/opends/server/core/DirectoryServer.java
index c0afe5f..e4d2023 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/core/DirectoryServer.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/core/DirectoryServer.java
@@ -17,7 +17,6 @@
package org.opends.server.core;
import static com.forgerock.opendj.cli.CommonArguments.*;
-
import static org.forgerock.util.Reject.*;
import static org.opends.messages.CoreMessages.*;
import static org.opends.messages.ToolMessages.*;
@@ -72,6 +71,7 @@
import org.forgerock.opendj.ldap.ResultCode;
import org.forgerock.opendj.ldap.schema.AttributeType;
import org.forgerock.opendj.ldap.schema.CoreSchema;
+import org.forgerock.opendj.ldap.schema.DITContentRule;
import org.forgerock.opendj.ldap.schema.MatchingRule;
import org.forgerock.opendj.ldap.schema.MatchingRuleUse;
import org.forgerock.opendj.ldap.schema.NameForm;
@@ -150,7 +150,6 @@
import org.opends.server.types.BackupConfig;
import org.opends.server.types.Control;
import org.opends.server.types.CryptoManager;
-import org.opends.server.types.DITContentRule;
import org.opends.server.types.DITStructureRule;
import org.opends.server.types.DirectoryEnvironmentConfig;
import org.opends.server.types.DirectoryException;
@@ -2618,16 +2617,6 @@
}
/**
- * Deregisters the provided DIT content rule with the Directory Server.
- *
- * @param ditContentRule The DIT content rule to deregister with the server.
- */
- public static void deregisterDITContentRule(DITContentRule ditContentRule)
- {
- directoryServer.schema.deregisterDITContentRule(ditContentRule);
- }
-
- /**
* Retrieves the DIT structure rule associated with the provided rule ID.
*
* @param ruleID The rule ID for which to retrieve the associated DIT
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/core/SchemaConfigManager.java b/opendj-server-legacy/src/main/java/org/opends/server/core/SchemaConfigManager.java
index f82b5a1..2aa47ba 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/core/SchemaConfigManager.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/core/SchemaConfigManager.java
@@ -32,10 +32,8 @@
import org.forgerock.opendj.ldap.schema.AttributeType;
import org.forgerock.opendj.ldap.schema.CoreSchema;
import org.forgerock.opendj.ldap.schema.Syntax;
-import org.opends.server.schema.DITContentRuleSyntax;
import org.opends.server.schema.DITStructureRuleSyntax;
import org.opends.server.types.Attribute;
-import org.opends.server.types.DITContentRule;
import org.opends.server.types.DITStructureRule;
import org.opends.server.types.DirectoryException;
import org.opends.server.types.Entry;
@@ -758,39 +756,10 @@
{
for (ByteString v : a)
{
- // Parse the DIT content rule.
- DITContentRule dcr;
+ final String definition = v.toString();
try
{
- dcr = DITContentRuleSyntax.decodeDITContentRule(v, schema, false);
- dcr.getExtraProperties().remove(SCHEMA_PROPERTY_FILENAME);
- setSchemaFile(dcr, schemaFile);
- }
- catch (DirectoryException de)
- {
- logger.traceException(de);
-
- LocalizableMessage message = WARN_CONFIG_SCHEMA_CANNOT_PARSE_DCR.get(
- schemaFile, de.getMessageObject());
- reportError(failOnError, de, message);
- continue;
- }
- catch (Exception e)
- {
- logger.traceException(e);
-
- LocalizableMessage message = WARN_CONFIG_SCHEMA_CANNOT_PARSE_DCR.get(
- schemaFile, v + ": " + getExceptionMessage(e));
- reportError(failOnError, e, message);
- continue;
- }
-
- // Register it with the schema. We will allow duplicates, with the
- // later definition overriding any earlier definition, but we want
- // to trap them and log a warning.
- try
- {
- schema.registerDITContentRule(dcr, failOnError);
+ schema.registerDITContentRule(definition, schemaFile, failOnError);
}
catch (DirectoryException de)
{
@@ -800,7 +769,7 @@
try
{
- schema.registerDITContentRule(dcr, true);
+ schema.registerDITContentRule(definition, schemaFile, true);
}
catch (Exception e)
{
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/schema/DITContentRuleSyntax.java b/opendj-server-legacy/src/main/java/org/opends/server/schema/DITContentRuleSyntax.java
index 0901afe..a26c35a 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/schema/DITContentRuleSyntax.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/schema/DITContentRuleSyntax.java
@@ -16,29 +16,11 @@
*/
package org.opends.server.schema;
-import static org.opends.messages.SchemaMessages.*;
import static org.opends.server.schema.SchemaConstants.*;
-import static org.opends.server.util.StaticUtils.*;
-import java.util.LinkedHashMap;
-import java.util.LinkedHashSet;
-import java.util.LinkedList;
-import java.util.List;
-
-import org.forgerock.i18n.LocalizableMessage;
-import org.forgerock.i18n.LocalizableMessageDescriptor.Arg2;
-import org.forgerock.opendj.ldap.ByteSequence;
-import org.forgerock.opendj.ldap.ResultCode;
-import org.forgerock.opendj.ldap.schema.AttributeType;
-import org.forgerock.opendj.ldap.schema.ObjectClass;
-import org.forgerock.opendj.ldap.schema.ObjectClassType;
import org.forgerock.opendj.ldap.schema.Syntax;
import org.forgerock.opendj.server.config.server.AttributeSyntaxCfg;
import org.opends.server.api.AttributeSyntax;
-import org.opends.server.core.DirectoryServer;
-import org.opends.server.types.DITContentRule;
-import org.opends.server.types.DirectoryException;
-import org.opends.server.types.Schema;
/**
* This class implements the DIT content rule description syntax, which is used
@@ -59,1102 +41,28 @@
super();
}
- /** {@inheritDoc} */
@Override
public Syntax getSDKSyntax(org.forgerock.opendj.ldap.schema.Schema schema)
{
return schema.getSyntax(SchemaConstants.SYNTAX_DIT_CONTENT_RULE_OID);
}
- /** {@inheritDoc} */
@Override
public String getName()
{
return SYNTAX_DIT_CONTENT_RULE_NAME;
}
- /** {@inheritDoc} */
@Override
public String getOID()
{
return SYNTAX_DIT_CONTENT_RULE_OID;
}
- /** {@inheritDoc} */
@Override
public String getDescription()
{
return SYNTAX_DIT_CONTENT_RULE_DESCRIPTION;
}
-
- /**
- * Decodes the contents of the provided ASN.1 octet string as a DIT content
- * rule definition according to the rules of this syntax. Note that the
- * provided octet string value does not need to be normalized (and in fact, it
- * should not be in order to allow the desired capitalization to be
- * preserved).
- *
- * @param value The ASN.1 octet string containing the value
- * to decode (it does not need to be
- * normalized).
- * @param schema The schema to use to resolve references to
- * other schema elements.
- * @param allowUnknownElements Indicates whether to allow values that
- * reference a name form and/or superior rules
- * which are not defined in the server schema.
- * This should only be true when called by
- * {@code valueIsAcceptable}.
- *
- * @return The decoded DIT content rule definition.
- *
- * @throws DirectoryException If the provided value cannot be decoded as an
- * DIT content rule definition.
- */
- public static DITContentRule decodeDITContentRule(ByteSequence value,
- Schema schema, boolean allowUnknownElements)
- throws DirectoryException
- {
- // Get string representations of the provided value using the provided form
- // and with all lowercase characters.
- String valueStr = value.toString();
- String lowerStr = toLowerCase(valueStr);
-
-
- // We'll do this a character at a time. First, skip over any leading
- // whitespace.
- int pos = 0;
- int length = valueStr.length();
- while (pos < length && valueStr.charAt(pos) == ' ')
- {
- pos++;
- }
-
- if (pos >= length)
- {
- // This means that the value was empty or contained only whitespace. That
- // is illegal.
- LocalizableMessage message = ERR_ATTR_SYNTAX_DCR_EMPTY_VALUE.get();
- throw new DirectoryException(
- ResultCode.INVALID_ATTRIBUTE_SYNTAX, message);
- }
-
-
- // The next character must be an open parenthesis. If it is not, then that
- // is an error.
- char c = valueStr.charAt(pos++);
- if (c != '(')
- {
- LocalizableMessage message = ERR_ATTR_SYNTAX_DCR_EXPECTED_OPEN_PARENTHESIS.get(valueStr, pos-1, c);
- throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX, message);
- }
-
-
- // Skip over any spaces immediately following the opening parenthesis.
- while (pos < length && ((c = valueStr.charAt(pos)) == ' '))
- {
- pos++;
- }
-
- if (pos >= length)
- {
- // This means that the end of the value was reached before we could find
- // the OID. Ths is illegal.
- LocalizableMessage message = ERR_ATTR_SYNTAX_DCR_TRUNCATED_VALUE.get(valueStr);
- throw new DirectoryException(
- ResultCode.INVALID_ATTRIBUTE_SYNTAX, message);
- }
-
-
- // The next set of characters must be the OID. Strictly speaking, this
- // should only be a numeric OID, but we'll also allow for the
- // "ocname-oid" case as well. Look at the first character to figure out
- // which we will be using.
- int oidStartPos = pos;
- if (isDigit(c))
- {
- // This must be a numeric OID. In that case, we will accept only digits
- // and periods, but not consecutive periods.
- boolean lastWasPeriod = false;
- while (pos < length && ((c = valueStr.charAt(pos++)) != ' '))
- {
- if (c == '.')
- {
- if (lastWasPeriod)
- {
- LocalizableMessage message = ERR_ATTR_SYNTAX_DCR_DOUBLE_PERIOD_IN_NUMERIC_OID.
- get(valueStr, pos-1);
- throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX,
- message);
- }
- lastWasPeriod = true;
- }
- else if (! isDigit(c))
- {
- // This must have been an illegal character.
- LocalizableMessage message = ERR_ATTR_SYNTAX_DCR_ILLEGAL_CHAR_IN_NUMERIC_OID.get(valueStr, c, pos-1);
- throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX, message);
- }
- else
- {
- lastWasPeriod = false;
- }
- }
- }
- else
- {
- // This must be a "fake" OID. In this case, we will only accept
- // alphabetic characters, numeric digits, and the hyphen.
- while (pos < length && ((c = valueStr.charAt(pos++)) != ' '))
- {
- if (isAlpha(c) || isDigit(c) || c == '-' ||
- (c == '_' && DirectoryServer.allowAttributeNameExceptions()))
- {
- // This is fine. It is an acceptable character.
- }
- else
- {
- // This must have been an illegal character.
- LocalizableMessage message = ERR_ATTR_SYNTAX_DCR_ILLEGAL_CHAR_IN_STRING_OID.get(valueStr, c, pos-1);
- throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX, message);
- }
- }
- }
-
-
- // If we're at the end of the value, then it isn't a valid DIT content rule
- // description. Otherwise, parse out the OID.
- if (pos >= length)
- {
- LocalizableMessage message = ERR_ATTR_SYNTAX_DCR_TRUNCATED_VALUE.get(valueStr);
- throw new DirectoryException(
- ResultCode.INVALID_ATTRIBUTE_SYNTAX, message);
- }
-
- String oid = lowerStr.substring(oidStartPos, pos-1);
-
- // Get the objectclass with the specified OID. If it does not exist or is
- // not structural, then fail.
- ObjectClass structuralClass = schema.getObjectClass(oid);
- if (structuralClass.isPlaceHolder())
- {
- if (!allowUnknownElements)
- {
- LocalizableMessage message =
- ERR_ATTR_SYNTAX_DCR_UNKNOWN_STRUCTURAL_CLASS.get(valueStr, oid);
- throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION, message);
- }
- }
- else if (structuralClass.getObjectClassType() != ObjectClassType.STRUCTURAL)
- {
- LocalizableMessage message = ERR_ATTR_SYNTAX_DCR_STRUCTURAL_CLASS_NOT_STRUCTURAL.
- get(valueStr, oid, structuralClass.getNameOrOID(),
- structuralClass.getObjectClassType());
- throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION, message);
- }
-
-
- // Skip over the space(s) after the OID.
- while (pos < length && ((c = valueStr.charAt(pos)) == ' '))
- {
- pos++;
- }
-
- if (pos >= length)
- {
- // This means that the end of the value was reached before we could find
- // the OID. Ths is illegal.
- LocalizableMessage message = ERR_ATTR_SYNTAX_DCR_TRUNCATED_VALUE.get(valueStr);
- throw new DirectoryException(
- ResultCode.INVALID_ATTRIBUTE_SYNTAX, message);
- }
-
-
- // At this point, we should have a pretty specific syntax that describes
- // what may come next, but some of the components are optional and it would
- // be pretty easy to put something in the wrong order, so we will be very
- // flexible about what we can accept. Just look at the next token, figure
- // out what it is and how to treat what comes after it, then repeat until
- // we get to the end of the value. But before we start, set default values
- // for everything else we might need to know.
- LinkedHashMap<String,String> names = new LinkedHashMap<>();
- String description = null;
- boolean isObsolete = false;
- LinkedHashSet<ObjectClass> auxiliaryClasses = new LinkedHashSet<>();
- LinkedHashSet<AttributeType> requiredAttributes = new LinkedHashSet<>();
- LinkedHashSet<AttributeType> optionalAttributes = new LinkedHashSet<>();
- LinkedHashSet<AttributeType> prohibitedAttributes = new LinkedHashSet<>();
- LinkedHashMap<String,List<String>> extraProperties = new LinkedHashMap<>();
-
-
- while (true)
- {
- StringBuilder tokenNameBuffer = new StringBuilder();
- pos = readTokenName(valueStr, tokenNameBuffer, pos);
- String tokenName = tokenNameBuffer.toString();
- String lowerTokenName = toLowerCase(tokenName);
- if (tokenName.equals(")"))
- {
- // We must be at the end of the value. If not, then that's a problem.
- if (pos < length)
- {
- LocalizableMessage message = ERR_ATTR_SYNTAX_DCR_UNEXPECTED_CLOSE_PARENTHESIS.
- get(valueStr, pos-1);
- throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX,
- message);
- }
-
- break;
- }
- else if (lowerTokenName.equals("name"))
- {
- // This specifies the set of names for the DIT content rule. It may be
- // a single name in single quotes, or it may be an open parenthesis
- // followed by one or more names in single quotes separated by spaces.
- c = valueStr.charAt(pos++);
- if (c == '\'')
- {
- StringBuilder userBuffer = new StringBuilder();
- StringBuilder lowerBuffer = new StringBuilder();
- pos = readQuotedString(valueStr, lowerStr, userBuffer, lowerBuffer, pos-1);
- names.put(lowerBuffer.toString(), userBuffer.toString());
- }
- else if (c == '(')
- {
- StringBuilder userBuffer = new StringBuilder();
- StringBuilder lowerBuffer = new StringBuilder();
- pos = readQuotedString(valueStr, lowerStr, userBuffer, lowerBuffer,
- pos);
- names.put(lowerBuffer.toString(), userBuffer.toString());
-
-
- while (true)
- {
- if (valueStr.charAt(pos) == ')')
- {
- // Skip over any spaces after the parenthesis.
- pos++;
- while (pos < length && ((c = valueStr.charAt(pos)) == ' '))
- {
- pos++;
- }
-
- break;
- }
- else
- {
- userBuffer = new StringBuilder();
- lowerBuffer = new StringBuilder();
-
- pos = readQuotedString(valueStr, lowerStr, userBuffer,
- lowerBuffer, pos);
- names.put(lowerBuffer.toString(), userBuffer.toString());
- }
- }
- }
- else
- {
- // This is an illegal character.
- LocalizableMessage message = ERR_ATTR_SYNTAX_DCR_ILLEGAL_CHAR.get(valueStr, c, pos-1);
- throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX, message);
- }
- }
- else if (lowerTokenName.equals("desc"))
- {
- // This specifies the description for the DIT content rule. It is an
- // arbitrary string of characters enclosed in single quotes.
- StringBuilder descriptionBuffer = new StringBuilder();
- pos = readQuotedString(valueStr, descriptionBuffer, pos);
- description = descriptionBuffer.toString();
- }
- else if (lowerTokenName.equals("obsolete"))
- {
- // This indicates whether the DIT content rule should be considered
- // obsolete. We do not need to do any more parsing for this token.
- isObsolete = true;
- }
- else if (lowerTokenName.equals("aux"))
- {
- LinkedList<ObjectClass> ocs = new LinkedList<>();
-
- // This specifies the set of required auxiliary objectclasses for this
- // DIT content rule. It may be a single name or OID (not in quotes), or
- // it may be an open parenthesis followed by one or more names separated
- // by spaces and the dollar sign character, followed by a closing
- // parenthesis.
- c = valueStr.charAt(pos++);
- if (c == '(')
- {
- while (true)
- {
- StringBuilder woidBuffer = new StringBuilder();
- pos = readWOID(lowerStr, woidBuffer, pos);
-
- ObjectClass oc = schema.getObjectClass(woidBuffer.toString());
- if (oc.isPlaceHolder())
- {
- // This isn't good because it is an unknown auxiliary class.
- if (!allowUnknownElements)
- {
- throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION,
- ERR_ATTR_SYNTAX_DCR_UNKNOWN_AUXILIARY_CLASS.get(
- valueStr, woidBuffer));
- }
- }
- else if (oc.getObjectClassType() != ObjectClassType.AUXILIARY)
- {
- // This isn't good because it isn't an auxiliary class.
- LocalizableMessage message =
- ERR_ATTR_SYNTAX_DCR_AUXILIARY_CLASS_NOT_AUXILIARY.
- get(valueStr, woidBuffer, oc.getObjectClassType());
- throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION,
- message);
- }
-
- ocs.add(oc);
-
-
- // The next character must be either a dollar sign or a closing
- // parenthesis.
- c = valueStr.charAt(pos++);
- if (c == ')')
- {
- // This denotes the end of the list.
- break;
- }
- else if (c != '$')
- {
- LocalizableMessage message =
- ERR_ATTR_SYNTAX_DCR_ILLEGAL_CHAR.get(valueStr, c, pos-1);
- throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX, message);
- }
- }
- }
- else
- {
- StringBuilder woidBuffer = new StringBuilder();
- pos = readWOID(lowerStr, woidBuffer, pos-1);
-
- ObjectClass oc = schema.getObjectClass(woidBuffer.toString());
- if (oc.isPlaceHolder())
- {
- // This isn't good because it is an unknown auxiliary class.
- if (!allowUnknownElements)
- {
- throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION,
- ERR_ATTR_SYNTAX_DCR_UNKNOWN_AUXILIARY_CLASS.get(valueStr, woidBuffer));
- }
- }
- else if (oc.getObjectClassType() != ObjectClassType.AUXILIARY)
- {
- // This isn't good because it isn't an auxiliary class.
- LocalizableMessage message = ERR_ATTR_SYNTAX_DCR_AUXILIARY_CLASS_NOT_AUXILIARY.
- get(valueStr, woidBuffer, oc.getObjectClassType());
- throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION,
- message);
- }
-
- ocs.add(oc);
- }
-
- auxiliaryClasses.addAll(ocs);
- }
- else if (lowerTokenName.equals("must"))
- {
- LinkedList<AttributeType> attrs = new LinkedList<>();
-
- // This specifies the set of required attributes for the DIT content
- // rule. It may be a single name or OID (not in quotes), or it may be
- // an open parenthesis followed by one or more names separated by spaces
- // and the dollar sign character, followed by a closing parenthesis.
- c = valueStr.charAt(pos++);
- if (c == '(')
- {
- while (true)
- {
- StringBuilder woidBuffer = new StringBuilder();
- pos = readWOID(lowerStr, woidBuffer, pos);
- attrs.add(getAttribute(schema, allowUnknownElements, valueStr, woidBuffer,
- ERR_ATTR_SYNTAX_DCR_UNKNOWN_REQUIRED_ATTR));
-
- // The next character must be either a dollar sign or a closing parenthesis.
- c = valueStr.charAt(pos++);
- if (c == ')')
- {
- // This denotes the end of the list.
- break;
- }
- else if (c != '$')
- {
- LocalizableMessage message =
- ERR_ATTR_SYNTAX_DCR_ILLEGAL_CHAR.get(valueStr, c, pos-1);
- throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX, message);
- }
- }
- }
- else
- {
- StringBuilder woidBuffer = new StringBuilder();
- pos = readWOID(lowerStr, woidBuffer, pos-1);
- attrs.add(getAttribute(schema, allowUnknownElements, valueStr, woidBuffer,
- ERR_ATTR_SYNTAX_DCR_UNKNOWN_REQUIRED_ATTR));
- }
-
- requiredAttributes.addAll(attrs);
- }
- else if (lowerTokenName.equals("may"))
- {
- LinkedList<AttributeType> attrs = new LinkedList<>();
-
- // This specifies the set of optional attributes for the DIT content
- // rule. It may be a single name or OID (not in quotes), or it may be
- // an open parenthesis followed by one or more names separated by spaces
- // and the dollar sign character, followed by a closing parenthesis.
- c = valueStr.charAt(pos++);
- if (c == '(')
- {
- while (true)
- {
- StringBuilder woidBuffer = new StringBuilder();
- pos = readWOID(lowerStr, woidBuffer, pos);
- attrs.add(getAttribute(schema, allowUnknownElements, valueStr, woidBuffer,
- ERR_ATTR_SYNTAX_DCR_UNKNOWN_OPTIONAL_ATTR));
-
- // The next character must be either a dollar sign or a closing parenthesis.
- c = valueStr.charAt(pos++);
- if (c == ')')
- {
- // This denotes the end of the list.
- break;
- }
- else if (c != '$')
- {
- LocalizableMessage message =
- ERR_ATTR_SYNTAX_DCR_ILLEGAL_CHAR.get(valueStr, c, pos-1);
- throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX, message);
- }
- }
- }
- else
- {
- StringBuilder woidBuffer = new StringBuilder();
- pos = readWOID(lowerStr, woidBuffer, pos-1);
- attrs.add(getAttribute(schema, allowUnknownElements, valueStr, woidBuffer,
- ERR_ATTR_SYNTAX_DCR_UNKNOWN_OPTIONAL_ATTR));
- }
-
- optionalAttributes.addAll(attrs);
- }
- else if (lowerTokenName.equals("not"))
- {
- LinkedList<AttributeType> attrs = new LinkedList<>();
-
- // This specifies the set of prohibited attributes for the DIT content
- // rule. It may be a single name or OID (not in quotes), or it may be
- // an open parenthesis followed by one or more names separated by spaces
- // and the dollar sign character, followed by a closing parenthesis.
- c = valueStr.charAt(pos++);
- if (c == '(')
- {
- while (true)
- {
- StringBuilder woidBuffer = new StringBuilder();
- pos = readWOID(lowerStr, woidBuffer, pos);
- attrs.add(getAttribute(schema, allowUnknownElements, valueStr, woidBuffer,
- ERR_ATTR_SYNTAX_DCR_UNKNOWN_PROHIBITED_ATTR));
-
- // The next character must be either a dollar sign or a closing parenthesis.
- c = valueStr.charAt(pos++);
- if (c == ')')
- {
- // This denotes the end of the list.
- break;
- }
- else if (c != '$')
- {
- LocalizableMessage message =
- ERR_ATTR_SYNTAX_DCR_ILLEGAL_CHAR.get(valueStr, c, pos-1);
- throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX, message);
- }
- }
- }
- else
- {
- StringBuilder woidBuffer = new StringBuilder();
- pos = readWOID(lowerStr, woidBuffer, pos-1);
- attrs.add(getAttribute(schema, allowUnknownElements, valueStr, woidBuffer,
- ERR_ATTR_SYNTAX_DCR_UNKNOWN_PROHIBITED_ATTR));
- }
-
- prohibitedAttributes.addAll(attrs);
- }
- else
- {
- // This must be a non-standard property and it must be followed by
- // either a single value in single quotes or an open parenthesis
- // followed by one or more values in single quotes separated by spaces
- // followed by a close parenthesis.
- LinkedList<String> valueList = new LinkedList<>();
- pos = readExtraParameterValues(valueStr, valueList, pos);
- extraProperties.put(tokenName, valueList);
- }
- }
-
-
- // Make sure that none of the prohibited attributes is required by the
- // structural or any of the auxiliary classes.
- for (AttributeType t : prohibitedAttributes)
- {
- if (structuralClass.isRequired(t))
- {
- LocalizableMessage message = ERR_ATTR_SYNTAX_DCR_PROHIBITED_REQUIRED_BY_STRUCTURAL.
- get(valueStr, t.getNameOrOID(), structuralClass.getNameOrOID());
- throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION, message);
- }
-
- for (ObjectClass oc : auxiliaryClasses)
- {
- if (oc.isRequired(t))
- {
- LocalizableMessage message =
- ERR_ATTR_SYNTAX_DCR_PROHIBITED_REQUIRED_BY_AUXILIARY.
- get(valueStr, t.getNameOrOID(), oc.getNameOrOID());
- throw new DirectoryException(
- ResultCode.CONSTRAINT_VIOLATION, message);
- }
- }
- }
-
-
- return new DITContentRule(value.toString(), structuralClass, names,
- description, auxiliaryClasses, requiredAttributes,
- optionalAttributes, prohibitedAttributes,
- isObsolete, extraProperties);
- }
-
- private static AttributeType getAttribute(Schema schema, boolean allowUnknownElements, String valueStr,
- StringBuilder woidBuffer, Arg2<Object, Object> msg) throws DirectoryException
- {
- String woidString = woidBuffer.toString();
- AttributeType attr = schema.getAttributeType(woidString);
- if (attr.isPlaceHolder() && !allowUnknownElements)
- {
- throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION, msg.get(valueStr, woidString));
- }
- return attr;
- }
-
- /**
- * Reads the next token name from the DIT content rule definition, skipping
- * over any leading or trailing spaces, and appends it to the provided buffer.
- *
- * @param valueStr The string representation of the DIT content rule
- * definition.
- * @param tokenName The buffer into which the token name will be written.
- * @param startPos The position in the provided string at which to start
- * reading the token name.
- *
- * @return The position of the first character that is not part of the token
- * name or one of the trailing spaces after it.
- *
- * @throws DirectoryException If a problem is encountered while reading the
- * token name.
- */
- private static int readTokenName(String valueStr, StringBuilder tokenName,
- int startPos)
- throws DirectoryException
- {
- // Skip over any spaces at the beginning of the value.
- char c = '\u0000';
- int length = valueStr.length();
- while (startPos < length && ((c = valueStr.charAt(startPos)) == ' '))
- {
- startPos++;
- }
-
- if (startPos >= length)
- {
- LocalizableMessage message = ERR_ATTR_SYNTAX_DCR_TRUNCATED_VALUE.get(valueStr);
- throw new DirectoryException(
- ResultCode.INVALID_ATTRIBUTE_SYNTAX, message);
- }
-
-
- // Read until we find the next space.
- while (startPos < length && ((c = valueStr.charAt(startPos++)) != ' '))
- {
- tokenName.append(c);
- }
-
-
- // Skip over any trailing spaces after the value.
- while (startPos < length && ((c = valueStr.charAt(startPos)) == ' '))
- {
- startPos++;
- }
-
-
- // Return the position of the first non-space character after the token.
- return startPos;
- }
-
- /**
- * Reads the value of a string enclosed in single quotes, skipping over the
- * quotes and any leading or trailing spaces, and appending the string to the
- * provided buffer.
- *
- * @param valueStr The user-provided representation of the DIT content
- * rule definition.
- * @param valueBuffer The buffer into which the user-provided representation
- * of the value will be placed.
- * @param startPos The position in the provided string at which to start
- * reading the quoted string.
- *
- * @return The position of the first character that is not part of the quoted
- * string or one of the trailing spaces after it.
- *
- * @throws DirectoryException If a problem is encountered while reading the
- * quoted string.
- */
- private static int readQuotedString(String valueStr,
- StringBuilder valueBuffer, int startPos)
- throws DirectoryException
- {
- // Skip over any spaces at the beginning of the value.
- char c = '\u0000';
- int length = valueStr.length();
- while (startPos < length && ((c = valueStr.charAt(startPos)) == ' '))
- {
- startPos++;
- }
-
- if (startPos >= length)
- {
- LocalizableMessage message = ERR_ATTR_SYNTAX_DCR_TRUNCATED_VALUE.get(valueStr);
- throw new DirectoryException(
- ResultCode.INVALID_ATTRIBUTE_SYNTAX, message);
- }
-
-
- // The next character must be a single quote.
- if (c != '\'')
- {
- LocalizableMessage message =
- ERR_ATTR_SYNTAX_DCR_EXPECTED_QUOTE_AT_POS.get(valueStr, startPos, c);
- throw new DirectoryException(
- ResultCode.INVALID_ATTRIBUTE_SYNTAX, message);
- }
-
-
- // Read until we find the closing quote.
- startPos++;
- while (startPos < length && ((c = valueStr.charAt(startPos)) != '\''))
- {
- valueBuffer.append(c);
- startPos++;
- }
-
-
- // Skip over any trailing spaces after the value.
- startPos++;
- while (startPos < length && ((c = valueStr.charAt(startPos)) == ' '))
- {
- startPos++;
- }
-
-
- // If we're at the end of the value, then that's illegal.
- if (startPos >= length)
- {
- LocalizableMessage message = ERR_ATTR_SYNTAX_DCR_TRUNCATED_VALUE.get(valueStr);
- throw new DirectoryException(
- ResultCode.INVALID_ATTRIBUTE_SYNTAX, message);
- }
-
-
- // Return the position of the first non-space character after the token.
- return startPos;
- }
-
- /**
- * Reads the value of a string enclosed in single quotes, skipping over the
- * quotes and any leading or trailing spaces, and appending the string to the
- * provided buffer.
- *
- * @param valueStr The user-provided representation of the DIT content
- * rule definition.
- * @param lowerStr The all-lowercase representation of the DIT content
- * rule definition.
- * @param userBuffer The buffer into which the user-provided representation
- * of the value will be placed.
- * @param lowerBuffer The buffer into which the all-lowercase representation
- * of the value will be placed.
- * @param startPos The position in the provided string at which to start
- * reading the quoted string.
- *
- * @return The position of the first character that is not part of the quoted
- * string or one of the trailing spaces after it.
- *
- * @throws DirectoryException If a problem is encountered while reading the
- * quoted string.
- */
- private static int readQuotedString(String valueStr, String lowerStr,
- StringBuilder userBuffer,
- StringBuilder lowerBuffer, int startPos)
- throws DirectoryException
- {
- // Skip over any spaces at the beginning of the value.
- char c = '\u0000';
- int length = lowerStr.length();
- while (startPos < length && ((c = lowerStr.charAt(startPos)) == ' '))
- {
- startPos++;
- }
-
- if (startPos >= length)
- {
- LocalizableMessage message = ERR_ATTR_SYNTAX_DCR_TRUNCATED_VALUE.get(lowerStr);
- throw new DirectoryException(
- ResultCode.INVALID_ATTRIBUTE_SYNTAX, message);
- }
-
-
- // The next character must be a single quote.
- if (c != '\'')
- {
- LocalizableMessage message =
- ERR_ATTR_SYNTAX_DCR_EXPECTED_QUOTE_AT_POS.get(valueStr, startPos, c);
- throw new DirectoryException(
- ResultCode.INVALID_ATTRIBUTE_SYNTAX, message);
- }
-
-
- // Read until we find the closing quote.
- startPos++;
- while (startPos < length && ((c = lowerStr.charAt(startPos)) != '\''))
- {
- lowerBuffer.append(c);
- userBuffer.append(valueStr.charAt(startPos));
- startPos++;
- }
-
-
- // Skip over any trailing spaces after the value.
- startPos++;
- while (startPos < length && ((c = lowerStr.charAt(startPos)) == ' '))
- {
- startPos++;
- }
-
-
- // If we're at the end of the value, then that's illegal.
- if (startPos >= length)
- {
- LocalizableMessage message = ERR_ATTR_SYNTAX_DCR_TRUNCATED_VALUE.get(lowerStr);
- throw new DirectoryException(
- ResultCode.INVALID_ATTRIBUTE_SYNTAX, message);
- }
-
-
- // Return the position of the first non-space character after the token.
- return startPos;
- }
-
- /**
- * Reads an attributeType/objectclass description or numeric OID from the
- * provided string, skipping over any leading or trailing spaces, and
- * appending the value to the provided buffer.
- *
- * @param lowerStr The string from which the name or OID is to be read.
- * @param woidBuffer The buffer into which the name or OID should be
- * appended.
- * @param startPos The position at which to start reading.
- *
- * @return The position of the first character after the name or OID that is
- * not a space.
- *
- * @throws DirectoryException If a problem is encountered while reading the
- * name or OID.
- */
- private static int readWOID(String lowerStr, StringBuilder woidBuffer,
- int startPos)
- throws DirectoryException
- {
- // Skip over any spaces at the beginning of the value.
- char c = '\u0000';
- int length = lowerStr.length();
- while (startPos < length && ((c = lowerStr.charAt(startPos)) == ' '))
- {
- startPos++;
- }
-
- if (startPos >= length)
- {
- LocalizableMessage message = ERR_ATTR_SYNTAX_DCR_TRUNCATED_VALUE.get(lowerStr);
- throw new DirectoryException(
- ResultCode.INVALID_ATTRIBUTE_SYNTAX, message);
- }
-
-
- // The next character must be either numeric (for an OID) or alphabetic (for
- // an attribute type/objectclass description).
- if (isDigit(c))
- {
- // This must be a numeric OID. In that case, we will accept only digits
- // and periods, but not consecutive periods.
- boolean lastWasPeriod = false;
- while (startPos < length && ((c = lowerStr.charAt(startPos++)) != ' '))
- {
- if (c == '.')
- {
- if (lastWasPeriod)
- {
- LocalizableMessage message = ERR_ATTR_SYNTAX_DCR_DOUBLE_PERIOD_IN_NUMERIC_OID.
- get(lowerStr, startPos-1);
- throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX,
- message);
- }
- else
- {
- woidBuffer.append(c);
- lastWasPeriod = true;
- }
- }
- else if (! isDigit(c))
- {
- // Technically, this must be an illegal character. However, it is
- // possible that someone just got sloppy and did not include a space
- // between the name/OID and a closing parenthesis. In that case,
- // we'll assume it's the end of the value. What's more, we'll have
- // to prematurely return to nasty side effects from stripping off
- // additional characters.
- if (c == ')')
- {
- return startPos-1;
- }
-
- // This must have been an illegal character.
- LocalizableMessage message = ERR_ATTR_SYNTAX_DCR_ILLEGAL_CHAR_IN_NUMERIC_OID.get(
- lowerStr, c, startPos-1);
- throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX, message);
- }
- else
- {
- woidBuffer.append(c);
- lastWasPeriod = false;
- }
- }
- }
- else if (isAlpha(c))
- {
- // This must be an attribute type/objectclass description. In this case,
- // we will only accept alphabetic characters, numeric digits, and the hyphen.
- while (startPos < length && ((c = lowerStr.charAt(startPos++)) != ' '))
- {
- if (isAlpha(c) || isDigit(c) || c == '-' ||
- (c == '_' && DirectoryServer.allowAttributeNameExceptions()))
- {
- woidBuffer.append(c);
- }
- else
- {
- // Technically, this must be an illegal character. However, it is
- // possible that someone just got sloppy and did not include a space
- // between the name/OID and a closing parenthesis. In that case,
- // we'll assume it's the end of the value. What's more, we'll have
- // to prematurely return to nasty side effects from stripping off
- // additional characters.
- if (c == ')')
- {
- return startPos-1;
- }
-
- // This must have been an illegal character.
- LocalizableMessage message = ERR_ATTR_SYNTAX_DCR_ILLEGAL_CHAR_IN_STRING_OID.get(
- lowerStr, c, startPos-1);
- throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX, message);
- }
- }
- }
- else
- {
- LocalizableMessage message = ERR_ATTR_SYNTAX_DCR_ILLEGAL_CHAR.get(lowerStr, c, startPos);
- throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX, message);
- }
-
-
- // Skip over any trailing spaces after the value.
- while (startPos < length && ((c = lowerStr.charAt(startPos)) == ' '))
- {
- startPos++;
- }
-
-
- // If we're at the end of the value, then that's illegal.
- if (startPos >= length)
- {
- LocalizableMessage message = ERR_ATTR_SYNTAX_DCR_TRUNCATED_VALUE.get(lowerStr);
- throw new DirectoryException(
- ResultCode.INVALID_ATTRIBUTE_SYNTAX, message);
- }
-
-
- // Return the position of the first non-space character after the token.
- return startPos;
- }
-
- /**
- * Reads the value for an "extra" parameter. It will handle a single unquoted
- * word (which is technically illegal, but we'll allow it), a single quoted
- * string, or an open parenthesis followed by a space-delimited set of quoted
- * strings or unquoted words followed by a close parenthesis.
- *
- * @param valueStr The string containing the information to be read.
- * @param valueList The list of "extra" parameter values read so far.
- * @param startPos The position in the value string at which to start
- * reading.
- *
- * @return The "extra" parameter value that was read.
- *
- * @throws DirectoryException If a problem occurs while attempting to read
- * the value.
- */
- private static int readExtraParameterValues(String valueStr,
- List<String> valueList, int startPos)
- throws DirectoryException
- {
- // Skip over any leading spaces.
- int length = valueStr.length();
- char c = '\u0000';
- while (startPos < length && ((c = valueStr.charAt(startPos)) == ' '))
- {
- startPos++;
- }
-
- if (startPos >= length)
- {
- LocalizableMessage message =
- ERR_ATTR_SYNTAX_DCR_TRUNCATED_VALUE.get(valueStr);
- throw new DirectoryException(
- ResultCode.INVALID_ATTRIBUTE_SYNTAX, message);
- }
-
-
- // Look at the next character. If it is a quote, then parse until the next
- // quote and end. If it is an open parenthesis, then parse individual
- // values until the close parenthesis and end. Otherwise, parse until the
- // next space and end.
- if (c == '\'')
- {
- // Parse until the closing quote.
- StringBuilder valueBuffer = new StringBuilder();
- startPos++;
- while (startPos < length && ((c = valueStr.charAt(startPos)) != '\''))
- {
- valueBuffer.append(c);
- startPos++;
- }
- startPos++;
- valueList.add(valueBuffer.toString());
- }
- else if (c == '(')
- {
- startPos++;
- // We're expecting a list of values. Quoted, space separated.
- while (true)
- {
- // Skip over any leading spaces;
- while (startPos < length && ((c = valueStr.charAt(startPos)) == ' '))
- {
- startPos++;
- }
-
- if (startPos >= length)
- {
- LocalizableMessage message =
- ERR_ATTR_SYNTAX_DCR_TRUNCATED_VALUE.get(valueStr);
- throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX,
- message);
- }
-
- if (c == ')')
- {
- // This is the end of the list.
- startPos++;
- break;
- }
- else if (c == '(')
- {
- // This is an illegal character.
- LocalizableMessage message =
- ERR_ATTR_SYNTAX_DCR_ILLEGAL_CHAR.get(valueStr, c, startPos);
- throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX, message);
- }
- else if (c == '\'')
- {
- // We have a quoted string
- StringBuilder valueBuffer = new StringBuilder();
- startPos++;
- while (startPos < length &&
- ((c = valueStr.charAt(startPos)) != '\''))
- {
- valueBuffer.append(c);
- startPos++;
- }
-
- valueList.add(valueBuffer.toString());
- startPos++;
- }
- else
- {
- //Consider unquoted string
- StringBuilder valueBuffer = new StringBuilder();
- while (startPos < length &&
- ((c = valueStr.charAt(startPos)) != ' '))
- {
- valueBuffer.append(c);
- startPos++;
- }
-
- valueList.add(valueBuffer.toString());
- }
-
- if (startPos >= length)
- {
- LocalizableMessage message =
- ERR_ATTR_SYNTAX_DCR_TRUNCATED_VALUE.get(valueStr);
- throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX,
- message);
- }
- }
- }
- else
- {
- // Parse until the next space.
- StringBuilder valueBuffer = new StringBuilder();
- while (startPos < length && ((c = valueStr.charAt(startPos)) != ' '))
- {
- valueBuffer.append(c);
- startPos++;
- }
-
- valueList.add(valueBuffer.toString());
- }
-
- // Skip over any trailing spaces.
- while (startPos < length && valueStr.charAt(startPos) == ' ')
- {
- startPos++;
- }
-
- if (startPos >= length)
- {
- LocalizableMessage message =
- ERR_ATTR_SYNTAX_DCR_TRUNCATED_VALUE.get(valueStr);
- throw new DirectoryException(
- ResultCode.INVALID_ATTRIBUTE_SYNTAX, message);
- }
-
- return startPos;
- }
}
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/types/DITContentRule.java b/opendj-server-legacy/src/main/java/org/opends/server/types/DITContentRule.java
deleted file mode 100644
index afb0813..0000000
--- a/opendj-server-legacy/src/main/java/org/opends/server/types/DITContentRule.java
+++ /dev/null
@@ -1,459 +0,0 @@
-/*
- * The contents of this file are subject to the terms of the Common Development and
- * Distribution License (the License). You may not use this file except in compliance with the
- * License.
- *
- * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
- * specific language governing permission and limitations under the License.
- *
- * When distributing Covered Software, include this CDDL Header Notice in each file and include
- * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
- * Header, with the fields enclosed by brackets [] replaced by your own identifying
- * information: "Portions Copyright [year] [name of copyright owner]".
- *
- * Copyright 2006-2008 Sun Microsystems, Inc.
- * Portions Copyright 2013-2016 ForgeRock AS.
- */
-package org.opends.server.types;
-
-import org.forgerock.i18n.slf4j.LocalizedLogger;
-import org.forgerock.opendj.ldap.schema.AttributeType;
-import org.forgerock.opendj.ldap.schema.ObjectClass;
-import org.forgerock.opendj.ldap.schema.SchemaElement;
-
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import static org.forgerock.util.Reject.*;
-import static org.opends.server.util.ServerConstants.*;
-
-/**
- * This class defines a DIT content rule, which defines the set of
- * allowed, required, and prohibited attributes for entries with a
- * given structural objectclass, and also indicates which auxiliary
- * classes that may be included in the entry.
- */
-@org.opends.server.types.PublicAPI(
- stability=org.opends.server.types.StabilityLevel.UNCOMMITTED,
- mayInstantiate=false,
- mayExtend=false,
- mayInvoke=true)
-public final class DITContentRule implements SchemaElement
-{
- private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
-
- /** Indicates whether this content rule is declared "obsolete". */
- private final boolean isObsolete;
-
- /**
- * The set of additional name-value pairs associated with this
- * content rule definition.
- */
- private final Map<String,List<String>> extraProperties;
-
- /**
- * The set of names for this DIT content rule, in a mapping between
- * the all-lowercase form and the user-defined form.
- */
- private final Map<String,String> names;
-
- /** The structural objectclass for this DIT content rule. */
- private final ObjectClass structuralClass;
-
- /**
- * The set of auxiliary objectclasses that entries with this content
- * rule may contain, in a mapping between the objectclass and the
- * user-defined name for that class.
- */
- private final Set<ObjectClass> auxiliaryClasses;
- /** The set of optional attribute types for this DIT content rule. */
- private final Set<AttributeType> optionalAttributes;
- /** The set of prohibited attribute types for this DIT content rule. */
- private final Set<AttributeType> prohibitedAttributes;
- /** The set of required attribute types for this DIT content rule. */
- private final Set<AttributeType> requiredAttributes;
- /** The definition string used to create this DIT content rule. */
- private final String definition;
- /** The description for this DIT content rule. */
- private final String description;
-
- /**
- * Creates a new DIT content rule definition with the provided
- * information.
- *
- * @param definition The definition string used to
- * create this DIT content rule. It
- * must not be {@code null}.
- * @param structuralClass The structural objectclass for this
- * DIT content rule. It must not be
- * {@code null}.
- * @param names The set of names that may be used
- * to reference this DIT content rule.
- * @param description The description for this DIT
- * content rule.
- * @param auxiliaryClasses The set of auxiliary classes for
- * this DIT content rule
- * @param requiredAttributes The set of required attribute types
- * for this DIT content rule.
- * @param optionalAttributes The set of optional attribute types
- * for this DIT content rule.
- * @param prohibitedAttributes The set of prohibited attribute
- * types for this DIT content rule.
- * @param isObsolete Indicates whether this DIT content
- * rule is declared "obsolete".
- * @param extraProperties A set of extra properties for this
- * DIT content rule.
- */
- public DITContentRule(String definition,
- ObjectClass structuralClass,
- Map<String,String> names, String description,
- Set<ObjectClass> auxiliaryClasses,
- Set<AttributeType> requiredAttributes,
- Set<AttributeType> optionalAttributes,
- Set<AttributeType> prohibitedAttributes,
- boolean isObsolete,
- Map<String,List<String>> extraProperties)
- {
- ifNull(definition, structuralClass);
-
- this.structuralClass = structuralClass;
- this.description = description;
- this.isObsolete = isObsolete;
-
- int schemaFilePos = definition.indexOf(SCHEMA_PROPERTY_FILENAME);
- if (schemaFilePos > 0)
- {
- String defStr;
- try
- {
- int firstQuotePos = definition.indexOf('\'', schemaFilePos);
- int secondQuotePos = definition.indexOf('\'',
- firstQuotePos+1);
-
- defStr = definition.substring(0, schemaFilePos).trim() + " " +
- definition.substring(secondQuotePos+1).trim();
- }
- catch (Exception e)
- {
- logger.traceException(e);
-
- defStr = definition;
- }
-
- this.definition = defStr;
- }
- else
- {
- this.definition = definition;
- }
-
- if (names == null || names.isEmpty())
- {
- this.names = new LinkedHashMap<>(0);
- }
- else
- {
- this.names = new LinkedHashMap<>(names);
- }
-
- if (auxiliaryClasses == null || auxiliaryClasses.isEmpty())
- {
- this.auxiliaryClasses = new LinkedHashSet<>(0);
- }
- else
- {
- this.auxiliaryClasses = new LinkedHashSet<>(auxiliaryClasses);
- }
-
- if (requiredAttributes == null || requiredAttributes.isEmpty())
- {
- this.requiredAttributes = new LinkedHashSet<>(0);
- }
- else
- {
- this.requiredAttributes = new LinkedHashSet<>(requiredAttributes);
- }
-
- if (optionalAttributes == null || optionalAttributes.isEmpty())
- {
- this.optionalAttributes = new LinkedHashSet<>(0);
- }
- else
- {
- this.optionalAttributes = new LinkedHashSet<>(optionalAttributes);
- }
-
- if (prohibitedAttributes == null || prohibitedAttributes.isEmpty())
- {
- this.prohibitedAttributes = new LinkedHashSet<>(0);
- }
- else
- {
- this.prohibitedAttributes = new LinkedHashSet<>(prohibitedAttributes);
- }
-
- if (extraProperties == null || extraProperties.isEmpty())
- {
- this.extraProperties = new LinkedHashMap<>(0);
- }
- else
- {
- this.extraProperties = new LinkedHashMap<>(extraProperties);
- }
- }
-
-
-
- /**
- * Retrieves the structural objectclass for this DIT content rule.
- *
- * @return The structural objectclass for this DIT content rule.
- */
- public ObjectClass getStructuralClass()
- {
- return structuralClass;
- }
-
-
-
- /**
- * Retrieves the set of names that may be used to reference this DIT
- * content rule. The returned object will be a mapping between each
- * name in all lowercase characters and that name in a user-defined
- * form (which may include mixed capitalization).
- *
- * @return The set of names that may be used to reference this DIT
- * content rule.
- */
- public Map<String,String> getNames()
- {
- return names;
- }
-
-
-
- /**
- * Retrieves the primary name to use to reference this DIT content
- * rule.
- *
- * @return The primary name to use to reference this DIT content
- * rule, or {@code null} if there is none.
- */
- public String getNameOrOID()
- {
- return !names.isEmpty() ? names.values().iterator().next() : null;
- }
-
-
-
- /**
- * Indicates whether the provided lowercase name may be used to
- * reference this DIT content rule.
- *
- * @param lowerName The name for which to make the determination,
- * in all lowercase characters.
- *
- * @return {@code true} if the provided lowercase name may be used
- * to reference this DIT content rule, or {@code false} if
- * not.
- */
- public boolean hasName(String lowerName)
- {
- return names.containsKey(lowerName);
- }
-
-
-
- /**
- * Retrieves the set of auxiliary objectclasses that may be used for
- * entries associated with this DIT content rule.
- *
- * @return The set of auxiliary objectclasses that may be used for
- * entries associated with this DIT content rule.
- */
- public Set<ObjectClass> getAuxiliaryClasses()
- {
- return auxiliaryClasses;
- }
-
-
-
- /**
- * Retrieves the set of required attributes for this DIT content
- * rule.
- *
- * @return The set of required attributes for this DIT content
- * rule.
- */
- public Set<AttributeType> getRequiredAttributes()
- {
- return requiredAttributes;
- }
-
- /**
- * Retrieves the set of optional attributes for this DIT content
- * rule.
- *
- * @return The set of optional attributes for this DIT content
- * rule.
- */
- public Set<AttributeType> getOptionalAttributes()
- {
- return optionalAttributes;
- }
-
-
-
- /**
- * Indicates whether the provided attribute type is in the list of
- * required or optional attributes for this DIT content rule.
- *
- * @param attributeType The attribute type for which to make the
- * determination.
- *
- * @return {@code true} if the provided attribute type is required
- * or allowed for this DIT content rule, or {@code false}
- * if it is not.
- */
- public boolean isRequiredOrOptional(AttributeType attributeType)
- {
- return requiredAttributes.contains(attributeType) ||
- optionalAttributes.contains(attributeType);
- }
-
-
-
- /**
- * Retrieves the set of prohibited attributes for this DIT content
- * rule.
- *
- * @return The set of prohibited attributes for this DIT content
- * rule.
- */
- public Set<AttributeType> getProhibitedAttributes()
- {
- return prohibitedAttributes;
- }
-
-
- /**
- * Indicates whether this DIT content rule is declared "obsolete".
- *
- * @return {@code true} if this DIT content rule is declared
- * "obsolete", or {@code false} if it is not.
- */
- public boolean isObsolete()
- {
- return isObsolete;
- }
-
-
-
- /**
- * Retrieves a mapping between the names of any extra non-standard
- * properties that may be associated with this DIT content rule and
- * the value for that property.
- *
- * @return A mapping between the names of any extra non-standard
- * properties that may be associated with this DIT content
- * rule and the value for that property.
- */
- @Override
- public Map<String,List<String>> getExtraProperties()
- {
- return extraProperties;
- }
-
-
-
- /**
- * Indicates whether the provided object is equal to this DIT
- * content rule. The object will be considered equal if it is a DIT
- * content rule for the same structural objectclass and the same
- * sets of names. For performance reasons, the set of auxiliary
- * classes, and the sets of required, optional, and prohibited
- * attribute types will not be checked, so that should be done
- * manually if a more thorough equality comparison is required.
- *
- * @param o The object for which to make the determination.
- *
- * @return {@code true} if the provided object is equal to
- * this DIT content rule, or {@code false} if not.
- */
- @Override
- public boolean equals(Object o)
- {
- if (this == o)
- {
- return true;
- }
- if (!(o instanceof DITContentRule))
- {
- return false;
- }
-
- DITContentRule dcr = (DITContentRule) o;
- if (!structuralClass.equals(dcr.structuralClass))
- {
- return false;
- }
-
- if (names.size() != dcr.names.size())
- {
- return false;
- }
-
- Iterator<String> iterator = names.keySet().iterator();
- while (iterator.hasNext())
- {
- if (! dcr.names.containsKey(iterator.next()))
- {
- return false;
- }
- }
-
- return true;
- }
-
-
-
- /**
- * Retrieves the hash code for this DIT content rule. It will be
- * equal to the hash code for the associated structural objectclass.
- *
- * @return The hash code for this DIT content rule.
- */
- @Override
- public int hashCode()
- {
- return structuralClass.hashCode();
- }
-
-
-
- /**
- * Retrieves the string representation of this DIT content rule in
- * the form specified in RFC 2252.
- *
- * @return The string representation of this DIT content rule in
- * the form specified in RFC 2252.
- */
- @Override
- public String toString()
- {
- return definition;
- }
-
-
-
- @Override
- public String getDescription()
- {
- return description;
- }
-
-}
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/types/DirectoryConfig.java b/opendj-server-legacy/src/main/java/org/opends/server/types/DirectoryConfig.java
index 450c24c..d8e4ef5 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/types/DirectoryConfig.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/types/DirectoryConfig.java
@@ -23,6 +23,7 @@
import org.forgerock.opendj.ldap.DN;
import org.forgerock.opendj.ldap.ResultCode;
import org.forgerock.opendj.ldap.schema.AttributeType;
+import org.forgerock.opendj.ldap.schema.DITContentRule;
import org.forgerock.opendj.ldap.schema.MatchingRule;
import org.forgerock.opendj.ldap.schema.MatchingRuleUse;
import org.forgerock.opendj.ldap.schema.NameForm;
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/types/Entry.java b/opendj-server-legacy/src/main/java/org/opends/server/types/Entry.java
index a856c6d..80a07e9 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/types/Entry.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/types/Entry.java
@@ -46,6 +46,7 @@
import org.forgerock.opendj.ldap.ResultCode;
import org.forgerock.opendj.ldap.SearchScope;
import org.forgerock.opendj.ldap.schema.AttributeType;
+import org.forgerock.opendj.ldap.schema.DITContentRule;
import org.forgerock.opendj.ldap.schema.MatchingRule;
import org.forgerock.opendj.ldap.schema.NameForm;
import org.forgerock.opendj.ldap.schema.ObjectClass;
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/types/Schema.java b/opendj-server-legacy/src/main/java/org/opends/server/types/Schema.java
index e8e6ffc..65e707d 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/types/Schema.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/types/Schema.java
@@ -49,6 +49,7 @@
import org.forgerock.opendj.ldap.schema.AttributeType;
import org.forgerock.opendj.ldap.schema.ConflictingSchemaElementException;
import org.forgerock.opendj.ldap.schema.CoreSchema;
+import org.forgerock.opendj.ldap.schema.DITContentRule;
import org.forgerock.opendj.ldap.schema.MatchingRule;
import org.forgerock.opendj.ldap.schema.MatchingRuleUse;
import org.forgerock.opendj.ldap.schema.MatchingRuleUse.Builder;
@@ -62,7 +63,6 @@
import org.forgerock.util.Utils;
import org.opends.server.core.DirectoryServer;
import org.opends.server.core.SchemaConfigManager;
-import org.opends.server.schema.DITContentRuleSyntax;
import org.opends.server.schema.DITStructureRuleSyntax;
import org.opends.server.util.Base64;
import org.opends.server.util.ServerConstants;
@@ -110,13 +110,6 @@
private Map<AttributeType, List<AttributeType>> subordinateTypes;
/**
- * The set of DIT content rules for this schema, mapped between the structural
- * objectclass for the definition and the DIT content rule itself.
- */
- private ConcurrentHashMap<ObjectClass,DITContentRule>
- ditContentRules;
-
- /**
* The set of DIT structure rules for this schema, mapped between the name
* form for the definition and the DIT structure rule itself.
*/
@@ -175,7 +168,6 @@
{
switchSchema(schemaNG);
- ditContentRules = new ConcurrentHashMap<ObjectClass,DITContentRule>();
ditStructureRulesByID = new ConcurrentHashMap<Integer,DITStructureRule>();
ditStructureRulesByNameForm = new ConcurrentHashMap<NameForm,DITStructureRule>();
ldapSyntaxDescriptions = new ConcurrentHashMap<String,LDAPSyntaxDescription>();
@@ -383,6 +375,36 @@
}
/**
+ * Parses a a DIT content rule from its provided definition.
+ *
+ * @param definition
+ * The definition of the matching rule use
+ * @return the DIT content rule
+ * @throws DirectoryException
+ * If an error occurs
+ */
+ public DITContentRule parseDITContentRule(final String definition) throws DirectoryException
+ {
+ try
+ {
+ SchemaBuilder builder = new SchemaBuilder(schemaNG);
+ builder.addDITContentRule(definition, true);
+ org.forgerock.opendj.ldap.schema.Schema newSchema = builder.toSchema();
+ rejectSchemaWithWarnings(newSchema);
+ return newSchema.getDITContentRule(parseDITContentRuleOID(definition));
+ }
+ catch (UnknownSchemaElementException e)
+ {
+ LocalizableMessage msg = ERR_DIT_CONTENT_RULE_CANNOT_REGISTER.get(definition);
+ throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, msg, e);
+ }
+ catch (LocalizedIllegalArgumentException e)
+ {
+ throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX, e.getMessageObject(), e);
+ }
+ }
+
+ /**
* Registers a list of attribute types from their provided definitions.
* <p>
* This method allows to do only one schema change for multiple definitions,
@@ -591,6 +613,11 @@
return parseOID(definition, ResultCode.INVALID_ATTRIBUTE_SYNTAX, ERR_PARSING_NAME_FORM_OID);
}
+ private String parseDITContentRuleOID(String definition) throws DirectoryException
+ {
+ return parseOID(definition, ResultCode.INVALID_ATTRIBUTE_SYNTAX, ERR_PARSING_DIT_CONTENT_RULE_OID);
+ }
+
/**
* Returns the OID from the provided schema element definition, assuming the
* definition is valid.
@@ -1451,22 +1478,16 @@
/**
- * Retrieves the DIT content rule definitions for this schema, as a
- * mapping between the objectclass for the rule and the DIT content
- * rule itself. Each DIT content rule should only be present once,
- * since its only key is its objectclass. The contents of the
- * returned mapping must not be altered.
+ * Retrieves the DIT content rule definitions for this schema.
*
* @return The DIT content rule definitions for this schema.
*/
- public ConcurrentHashMap<ObjectClass,DITContentRule>
- getDITContentRules()
+ public Collection<DITContentRule> getDITContentRules()
{
- return ditContentRules;
+ return schemaNG.getDITContentRules();
}
-
/**
* Retrieves the DIT content rule definition for the specified
* objectclass.
@@ -1480,51 +1501,84 @@
*/
public DITContentRule getDITContentRule(ObjectClass objectClass)
{
- return ditContentRules.get(objectClass);
+ return schemaNG.getDITContentRule(objectClass);
}
/**
- * Registers the provided DIT content rule definition with this
- * schema.
+ * Registers the provided DIT content rule definition with this schema.
*
- * @param ditContentRule The DIT content rule to register.
- * @param overwriteExisting Indicates whether to overwrite an
- * existing mapping if there are any
- * conflicts (i.e., another DIT content
- * rule with the same objectclass).
- *
- * @throws DirectoryException If a conflict is encountered and the
- * <CODE>overwriteExisting</CODE> flag
- * is set to <CODE>false</CODE>
+ * @param ditContentRule
+ * The DIT content rule to register.
+ * @param schemaFile
+ * The schema file where this definition belongs, maybe {@code null}
+ * @param overwriteExisting
+ * Indicates whether to overwrite an existing mapping if there are any conflicts (i.e.,
+ * another DIT content rule with the same objectclass).
+ * @throws DirectoryException
+ * If a conflict is encountered and the <CODE>overwriteExisting</CODE> flag is set to
+ * <CODE>false</CODE>
*/
- public void registerDITContentRule(DITContentRule ditContentRule,
- boolean overwriteExisting)
- throws DirectoryException
+ public void registerDITContentRule(DITContentRule ditContentRule, String schemaFile, boolean overwriteExisting)
+ throws DirectoryException
{
- synchronized (ditContentRules)
+ exclusiveLock.lock();
+ try
{
- ObjectClass objectClass = ditContentRule.getStructuralClass();
-
- if (! overwriteExisting && ditContentRules.containsKey(objectClass))
+ SchemaBuilder builder = new SchemaBuilder(schemaNG);
+ DITContentRule.Builder dcrBuilder = builder.buildDITContentRule(ditContentRule);
+ if (schemaFile != null)
{
- DITContentRule conflictingRule =
- ditContentRules.get(objectClass);
-
- LocalizableMessage message = ERR_SCHEMA_CONFLICTING_DIT_CONTENT_RULE.
- get(ditContentRule.getNameOrOID(),
- objectClass.getNameOrOID(),
- conflictingRule.getNameOrOID());
- throw new DirectoryException(
- ResultCode.CONSTRAINT_VIOLATION, message);
+ dcrBuilder.removeExtraProperty(SCHEMA_PROPERTY_FILENAME)
+ .extraProperties(SCHEMA_PROPERTY_FILENAME, schemaFile);
}
-
- ditContentRules.put(objectClass, ditContentRule);
+ if (overwriteExisting)
+ {
+ dcrBuilder.addToSchemaOverwrite();
+ }
+ else
+ {
+ dcrBuilder.addToSchema();
+ }
+ switchSchema(builder.toSchema());
+ }
+ finally
+ {
+ exclusiveLock.unlock();
}
}
-
+ /**
+ * Registers the provided DIT content rule definition with this schema.
+ *
+ * @param definition
+ * The DIT content rule definition to register.
+ * @param schemaFile
+ * The schema file where this definition belongs, maybe {@code null}
+ * @param overwriteExisting
+ * Indicates whether to overwrite an existing mapping if there are any conflicts (i.e.,
+ * another DIT content rule with the same object class).
+ * @throws DirectoryException
+ * If a conflict is encountered and the <CODE>overwriteExisting</CODE> flag is set to
+ * <CODE>false</CODE>
+ */
+ public void registerDITContentRule(String definition, String schemaFile, boolean overwriteExisting)
+ throws DirectoryException
+ {
+ exclusiveLock.lock();
+ try
+ {
+ String definitionWithFile = getDefinitionWithSchemaFile(definition, schemaFile);
+ switchSchema(new SchemaBuilder(schemaNG)
+ .addDITContentRule(definitionWithFile, overwriteExisting)
+ .toSchema());
+ }
+ finally
+ {
+ exclusiveLock.unlock();
+ }
+ }
/**
* Deregisters the provided DIT content rule definition with this
@@ -1532,13 +1586,22 @@
*
* @param ditContentRule The DIT content rule to deregister with
* this schema.
+ * @throws DirectoryException
+ * May be thrown if the schema has constraint violations, although
+ * deregistering a DIT content rule should not break any constraint.
*/
- public void deregisterDITContentRule(DITContentRule ditContentRule)
+ public void deregisterDITContentRule(DITContentRule ditContentRule) throws DirectoryException
{
- synchronized (ditContentRules)
+ exclusiveLock.lock();
+ try
{
- ditContentRules.remove(ditContentRule.getStructuralClass(),
- ditContentRule);
+ SchemaBuilder builder = new SchemaBuilder(schemaNG);
+ builder.removeDITContentRule(ditContentRule.getNameOrOID());
+ switchSchema(builder.toSchema());
+ }
+ finally
+ {
+ exclusiveLock.unlock();
}
}
@@ -2041,14 +2104,13 @@
}
}
- for (DITContentRule dcr : ditContentRules.values())
+ for (DITContentRule dcr : getDITContentRules())
{
if (dcr.getRequiredAttributes().contains(type) || dcr.getOptionalAttributes().contains(type)
|| dcr.getProhibitedAttributes().contains(type))
{
- DITContentRule newDCR = recreateFromDefinition(dcr);
deregisterDITContentRule(dcr);
- registerDITContentRule(newDCR, true);
+ registerDITContentRule(dcr.toString(), getSchemaFileName(dcr), true);
}
}
@@ -2099,13 +2161,12 @@
}
}
- for (DITContentRule dcr : ditContentRules.values())
+ for (DITContentRule dcr : getDITContentRules())
{
if (dcr.getStructuralClass().equals(c) || dcr.getAuxiliaryClasses().contains(c))
{
- DITContentRule newDCR = recreateFromDefinition(dcr);
deregisterDITContentRule(dcr);
- registerDITContentRule(newDCR, true);
+ registerDITContentRule(dcr.toString(), getSchemaFileName(dcr), true);
}
}
}
@@ -2144,15 +2205,6 @@
return values != null && ! values.isEmpty() ? values.get(0) : null;
}
- private DITContentRule recreateFromDefinition(DITContentRule dcr)
- throws DirectoryException
- {
- ByteString value = ByteString.valueOfUtf8(dcr.toString());
- DITContentRule copy = DITContentRuleSyntax.decodeDITContentRule(value, this, false);
- setSchemaFile(copy, getSchemaFile(dcr));
- return copy;
- }
-
private DITStructureRule recreateFromDefinition(DITStructureRule dsr)
throws DirectoryException
{
@@ -2183,7 +2235,6 @@
}
dupSchema.subordinateTypes.putAll(subordinateTypes);
- dupSchema.ditContentRules.putAll(ditContentRules);
dupSchema.ditStructureRulesByID.putAll(ditStructureRulesByID);
dupSchema.ditStructureRulesByNameForm.putAll(ditStructureRulesByNameForm);
dupSchema.ldapSyntaxDescriptions.putAll(ldapSyntaxDescriptions);
@@ -2614,12 +2665,6 @@
schemaNG = null;
}
- if (ditContentRules != null)
- {
- ditContentRules.clear();
- ditContentRules = null;
- }
-
if (ditStructureRulesByID != null)
{
ditStructureRulesByID.clear();
diff --git a/opendj-server-legacy/src/messages/org/opends/messages/schema.properties b/opendj-server-legacy/src/messages/org/opends/messages/schema.properties
index c0ca996..82122c0 100644
--- a/opendj-server-legacy/src/messages/org/opends/messages/schema.properties
+++ b/opendj-server-legacy/src/messages/org/opends/messages/schema.properties
@@ -515,4 +515,6 @@
ERR_NAME_FORM_CANNOT_REGISTER_349=Name form could not be \
registered from definition: %s
ERR_PARSING_NAME_FORM_OID_350=Unable to parse the OID from the provided definition \
- of name form: '%s'
\ No newline at end of file
+ of name form: '%s'
+ERR_PARSING_DIT_CONTENT_RULE_OID_351=Unable to parse the OID from the provided definition \
+ of DIT content rule: '%s'
diff --git a/opendj-server-legacy/src/test/java/org/opends/server/backends/SchemaBackendTestCase.java b/opendj-server-legacy/src/test/java/org/opends/server/backends/SchemaBackendTestCase.java
index 4f5483c..245c348 100644
--- a/opendj-server-legacy/src/test/java/org/opends/server/backends/SchemaBackendTestCase.java
+++ b/opendj-server-legacy/src/test/java/org/opends/server/backends/SchemaBackendTestCase.java
@@ -40,6 +40,7 @@
import org.forgerock.opendj.ldap.ResultCode;
import org.forgerock.opendj.ldap.SearchScope;
import org.forgerock.opendj.ldap.schema.AttributeType;
+import org.forgerock.opendj.ldap.schema.DITContentRule;
import org.forgerock.opendj.ldap.schema.MatchingRule;
import org.forgerock.opendj.ldap.schema.MatchingRuleUse;
import org.forgerock.opendj.ldap.schema.ObjectClass;
@@ -58,7 +59,6 @@
import org.opends.server.protocols.internal.SearchRequest;
import org.opends.server.schema.SchemaConstants;
import org.opends.server.tools.LDAPModify;
-import org.opends.server.types.DITContentRule;
import org.opends.server.types.DirectoryException;
import org.opends.server.types.Entry;
import org.opends.server.types.InitializationException;
@@ -2593,7 +2593,7 @@
"NAME 'testAddDITContentRuleUndefinedOC' NOT description " +
"X-ORIGIN 'SchemaBackendTestCase' )");
- runModify(argsNotPermissive(), ldif, INVALID_ATTRIBUTE_SYNTAX);
+ runModify(argsNotPermissive(), ldif, CONSTRAINT_VIOLATION);
}
/**
@@ -2619,7 +2619,7 @@
"NAME 'testAddDITContentRuleAuxiliaryOC' NOT description " +
"X-ORIGIN 'SchemaBackendTestCase' )");
- runModify(argsNotPermissive(), ldif, INVALID_ATTRIBUTE_SYNTAX);
+ runModify(argsNotPermissive(), ldif, CONSTRAINT_VIOLATION);
}
/**
@@ -2705,7 +2705,7 @@
"NAME 'testAddDITContentRuleUndefinedAuxOC' " +
"AUX xxxundefinedxxx X-ORIGIN 'SchemaBackendTestCase' )");
- runModify(argsNotPermissive(), ldif, INVALID_ATTRIBUTE_SYNTAX);
+ runModify(argsNotPermissive(), ldif, CONSTRAINT_VIOLATION);
}
/**
@@ -2733,7 +2733,7 @@
"AUX ( posixAccount $ xxxundefinedxxx ) " +
"X-ORIGIN 'SchemaBackendTestCase' )");
- runModify(argsNotPermissive(), ldif, INVALID_ATTRIBUTE_SYNTAX);
+ runModify(argsNotPermissive(), ldif, CONSTRAINT_VIOLATION);
}
/**
@@ -2759,7 +2759,7 @@
"NAME 'testAddDITContentRuleAuxOCNotAuxOC' " +
"AUX person X-ORIGIN 'SchemaBackendTestCase' )");
- runModify(argsNotPermissive(), ldif, INVALID_ATTRIBUTE_SYNTAX);
+ runModify(argsNotPermissive(), ldif, CONSTRAINT_VIOLATION);
}
/**
@@ -2787,7 +2787,7 @@
"AUX ( posixAccount $ person ) " +
"X-ORIGIN 'SchemaBackendTestCase' )");
- runModify(argsNotPermissive(), ldif, INVALID_ATTRIBUTE_SYNTAX);
+ runModify(argsNotPermissive(), ldif, CONSTRAINT_VIOLATION);
}
/**
@@ -2843,7 +2843,7 @@
"NAME 'testAddDITContentRuleUndefinedReqAT' " +
"MUST xxxundefinedxxx X-ORIGIN 'SchemaBackendTestCase' )");
- runModify(argsNotPermissive(), ldif, INVALID_ATTRIBUTE_SYNTAX);
+ runModify(argsNotPermissive(), ldif, CONSTRAINT_VIOLATION);
}
/**
@@ -2871,7 +2871,7 @@
"MUST ( cn $ xxxundefinedxxx ) " +
"X-ORIGIN 'SchemaBackendTestCase' )");
- runModify(argsNotPermissive(), ldif, INVALID_ATTRIBUTE_SYNTAX);
+ runModify(argsNotPermissive(), ldif, CONSTRAINT_VIOLATION);
}
/**
@@ -2897,7 +2897,7 @@
"NAME 'testAddDITContentRuleUndefinedOptAT' " +
"MAY xxxundefinedxxx X-ORIGIN 'SchemaBackendTestCase' )");
- runModify(argsNotPermissive(), ldif, INVALID_ATTRIBUTE_SYNTAX);
+ runModify(argsNotPermissive(), ldif, CONSTRAINT_VIOLATION);
}
/**
@@ -2925,7 +2925,7 @@
"MAY ( cn $ xxxundefinedxxx ) " +
"X-ORIGIN 'SchemaBackendTestCase' )");
- runModify(argsNotPermissive(), ldif, INVALID_ATTRIBUTE_SYNTAX);
+ runModify(argsNotPermissive(), ldif, CONSTRAINT_VIOLATION);
}
/**
@@ -2951,7 +2951,7 @@
"NAME 'testAddDITContentRuleUndefinedNotAT' " +
"NOT xxxundefinedxxx X-ORIGIN 'SchemaBackendTestCase' )");
- runModify(argsNotPermissive(), ldif, INVALID_ATTRIBUTE_SYNTAX);
+ runModify(argsNotPermissive(), ldif, CONSTRAINT_VIOLATION);
}
/**
@@ -2979,7 +2979,7 @@
"NOT ( description $ xxxundefinedxxx ) " +
"X-ORIGIN 'SchemaBackendTestCase' )");
- runModify(argsNotPermissive(), ldif, INVALID_ATTRIBUTE_SYNTAX);
+ runModify(argsNotPermissive(), ldif, CONSTRAINT_VIOLATION);
}
/**
@@ -3006,7 +3006,7 @@
"NAME 'testAddDCRProhibitReqStructuralAT' " +
"NOT cn X-ORIGIN 'SchemaBackendTestCase' )");
- runModify(argsNotPermissive(), ldif, INVALID_ATTRIBUTE_SYNTAX);
+ runModify(argsNotPermissive(), ldif, CONSTRAINT_VIOLATION);
}
/**
@@ -3033,7 +3033,7 @@
"NAME 'testAddDCRProhibitReqAuxiliaryAT' AUX posixAccount " +
"NOT uid X-ORIGIN 'SchemaBackendTestCase' )");
- runModify(argsNotPermissive(), ldif, INVALID_ATTRIBUTE_SYNTAX);
+ runModify(argsNotPermissive(), ldif, CONSTRAINT_VIOLATION);
}
/**
--
Gitblit v1.10.0