From 08c8ebade44d94666be683c1c0794c5518d41341 Mon Sep 17 00:00:00 2001
From: Matthew Swift <matthew.swift@forgerock.com>
Date: Thu, 21 Aug 2014 14:25:56 +0000
Subject: [PATCH] Preparatory work for OPENDJ-1477: Constant re-allocation of DN per-schema caches

---
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/SchemaBuilder.java  |   11 
 opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/SchemaTestCase.java |    4 
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DelayedSchema.java  |   11 
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/Schema.java         |  346 +++++--------------------------------------------
 4 files changed, 50 insertions(+), 322 deletions(-)

diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DefaultSchema.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DelayedSchema.java
similarity index 76%
rename from opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DefaultSchema.java
rename to opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DelayedSchema.java
index 9414ceb..30ae44a 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DefaultSchema.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DelayedSchema.java
@@ -21,20 +21,21 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2011 ForgeRock AS
+ *      Copyright 2011-2014 ForgeRock AS
  */
 
 package org.forgerock.opendj.ldap.schema;
 
 /**
- * This class is used to maintain a reference to the default schema and avoid
+ * This class is used to maintain a reference to the global schemas and avoids
  * having to reference the core schema in the {@link Schema} class since this
  * can cause initialization errors because the CoreSchema depends on Schema.
  */
-final class DefaultSchema {
-    static volatile Schema schema = Schema.getCoreSchema();
+final class DelayedSchema {
+    static final Schema EMPTY_SCHEMA = new SchemaBuilder("Empty Schema").toSchema().asNonStrictSchema();
+    static volatile Schema defaultSchema = Schema.getCoreSchema();
 
-    private DefaultSchema() {
+    private DelayedSchema() {
         // Prevent instantiation.
     }
 }
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/Schema.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/Schema.java
index 8c62757..4d8b361 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/Schema.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/Schema.java
@@ -22,7 +22,7 @@
  *
  *
  *      Copyright 2009-2010 Sun Microsystems, Inc.
- *      Portions copyright 2011-2012 ForgeRock AS
+ *      Portions copyright 2011-2014 ForgeRock AS
  *      Portions Copyright 2014 Manuel Gaupp
  */
 package org.forgerock.opendj.ldap.schema;
@@ -72,252 +72,11 @@
  * </UL>
  */
 public final class Schema {
-    private static final class EmptyImpl implements Impl {
-
-        private final boolean isStrict;
-
-        private EmptyImpl(final boolean isStrict) {
-            this.isStrict = isStrict;
-        }
-
-        @Override
-        public boolean allowMalformedNamesAndOptions() {
-            return true;
-        }
-
-        @Override
-        public boolean allowNonStandardTelephoneNumbers() {
-            return true;
-        }
-
-        @Override
-        public boolean allowMalformedJPEGPhotos() {
-            return true;
-        }
-
-        @Override
-        public boolean allowMalformedCertificates() {
-            return true;
-        }
-
-        @Override
-        public boolean allowZeroLengthDirectoryStrings() {
-            return false;
-        }
-
-        @Override
-        public Syntax getDefaultSyntax() {
-            return Schema.getCoreSchema().getDefaultSyntax();
-        }
-
-        @Override
-        public MatchingRule getDefaultMatchingRule() {
-            return Schema.getCoreSchema().getDefaultMatchingRule();
-        }
-
-        @Override
-        public AttributeType getAttributeType(final Schema schema, final String name) {
-            if (isStrict) {
-                throw new UnknownSchemaElementException(WARN_ATTR_TYPE_UNKNOWN.get(name));
-            } else {
-                // Return a place-holder.
-                return new AttributeType(schema, name);
-            }
-        }
-
-        @Override
-        public Collection<AttributeType> getAttributeTypes() {
-            return Collections.emptyList();
-        }
-
-        @Override
-        public List<AttributeType> getAttributeTypesWithName(final String name) {
-            return Collections.emptyList();
-        }
-
-        @Override
-        public DITContentRule getDITContentRule(final ObjectClass structuralClass) {
-            return null;
-        }
-
-        @Override
-        public DITContentRule getDITContentRule(final String name) {
-            throw new UnknownSchemaElementException(WARN_DCR_UNKNOWN.get(name));
-        }
-
-        @Override
-        public Collection<DITContentRule> getDITContentRules() {
-            return Collections.emptyList();
-        }
-
-        @Override
-        public Collection<DITContentRule> getDITContentRulesWithName(final String name) {
-            return Collections.emptyList();
-        }
-
-        @Override
-        public DITStructureRule getDITStructureRule(final int ruleID) {
-            throw new UnknownSchemaElementException(WARN_DSR_UNKNOWN.get(String.valueOf(ruleID)));
-        }
-
-        @Override
-        public Collection<DITStructureRule> getDITStructureRules(final NameForm nameForm) {
-            return Collections.emptyList();
-        }
-
-        @Override
-        public Collection<DITStructureRule> getDITStructureRulesWithName(final String name) {
-            return Collections.emptyList();
-        }
-
-        @Override
-        public Collection<DITStructureRule> getDITStuctureRules() {
-            return Collections.emptyList();
-        }
-
-        @Override
-        public MatchingRule getMatchingRule(final String name) {
-            throw new UnknownSchemaElementException(WARN_MR_UNKNOWN.get(name));
-        }
-
-        @Override
-        public Collection<MatchingRule> getMatchingRules() {
-            return Collections.emptyList();
-        }
-
-        @Override
-        public Collection<MatchingRule> getMatchingRulesWithName(final String name) {
-            return Collections.emptyList();
-        }
-
-        @Override
-        public MatchingRuleUse getMatchingRuleUse(final MatchingRule matchingRule) {
-            return null;
-        }
-
-        @Override
-        public MatchingRuleUse getMatchingRuleUse(final String name) {
-            throw new UnknownSchemaElementException(WARN_MRU_UNKNOWN.get(name));
-        }
-
-        @Override
-        public Collection<MatchingRuleUse> getMatchingRuleUses() {
-            return Collections.emptyList();
-        }
-
-        @Override
-        public Collection<MatchingRuleUse> getMatchingRuleUsesWithName(final String name) {
-            return Collections.emptyList();
-        }
-
-        @Override
-        public NameForm getNameForm(final String name) {
-            throw new UnknownSchemaElementException(WARN_NAMEFORM_UNKNOWN.get(name));
-        }
-
-        @Override
-        public Collection<NameForm> getNameForms() {
-            return Collections.emptyList();
-        }
-
-        @Override
-        public Collection<NameForm> getNameForms(final ObjectClass structuralClass) {
-            return Collections.emptyList();
-        }
-
-        @Override
-        public Collection<NameForm> getNameFormsWithName(final String name) {
-            return Collections.emptyList();
-        }
-
-        @Override
-        public ObjectClass getObjectClass(final String name) {
-            throw new UnknownSchemaElementException(WARN_OBJECTCLASS_UNKNOWN.get(name));
-        }
-
-        @Override
-        public Collection<ObjectClass> getObjectClasses() {
-            return Collections.emptyList();
-        }
-
-        @Override
-        public Collection<ObjectClass> getObjectClassesWithName(final String name) {
-            return Collections.emptyList();
-        }
-
-        /** {@inheritDoc} */
-        @Override
-        public String getSchemaName() {
-            return "Empty Schema";
-        }
-
-        @Override
-        public Syntax getSyntax(final Schema schema, final String numericOID) {
-            // Fake up a syntax substituted by the default syntax.
-            return new Syntax(schema, numericOID);
-        }
-
-        @Override
-        public Collection<Syntax> getSyntaxes() {
-            return Collections.emptyList();
-        }
-
-        @Override
-        public Collection<LocalizableMessage> getWarnings() {
-            return Collections.emptyList();
-        }
-
-        @Override
-        public boolean hasAttributeType(final String name) {
-            // In theory a non-strict schema always contains the requested
-            // attribute type, so we could always return true. However, we
-            // should provide a way for callers to differentiate between a
-            // real attribute type and a faked up attribute type.
-            return false;
-        }
-
-        @Override
-        public boolean hasDITContentRule(final String name) {
-            return false;
-        }
-
-        @Override
-        public boolean hasDITStructureRule(final int ruleID) {
-            return false;
-        }
-
-        @Override
-        public boolean hasMatchingRule(final String name) {
-            return false;
-        }
-
-        @Override
-        public boolean hasMatchingRuleUse(final String name) {
-            return false;
-        }
-
-        @Override
-        public boolean hasNameForm(final String name) {
-            return false;
-        }
-
-        @Override
-        public boolean hasObjectClass(final String name) {
-            return false;
-        }
-
-        @Override
-        public boolean hasSyntax(final String numericOID) {
-            return false;
-        }
-
-        @Override
-        public boolean isStrict() {
-            return isStrict;
-        }
-    }
-
     private static interface Impl {
+        Schema asNonStrictSchema();
+
+        Schema asStrictSchema();
+
         boolean allowMalformedNamesAndOptions();
 
         boolean allowMalformedJPEGPhotos();
@@ -417,6 +176,16 @@
         }
 
         @Override
+        public Schema asNonStrictSchema() {
+            return strictImpl.asNonStrictSchema();
+        }
+
+        @Override
+        public Schema asStrictSchema() {
+            return strictImpl.asStrictSchema();
+        }
+
+        @Override
         public boolean allowMalformedNamesAndOptions() {
             return strictImpl.allowMalformedNamesAndOptions();
         }
@@ -650,7 +419,7 @@
         }
     }
 
-    private static final class StrictImpl implements Impl {
+    static final class StrictImpl implements Impl {
         private final Map<Integer, DITStructureRule> id2StructureRules;
         private final Map<String, List<AttributeType>> name2AttributeTypes;
         private final Map<String, List<DITContentRule>> name2ContentRules;
@@ -677,6 +446,8 @@
         private final boolean allowMalformedNamesAndOptions;
         private final Syntax defaultSyntax;
         private final MatchingRule defaultMatchingRule;
+        private final Schema strictSchema;
+        private final Schema nonStrictSchema;
 
         StrictImpl(final String schemaName, final boolean allowMalformedNamesAndOptions,
                 final boolean allowMalformedJPEGPhotos,
@@ -730,6 +501,18 @@
             this.objectClass2NameForms = Collections.unmodifiableMap(objectClass2NameForms);
             this.nameForm2StructureRules = Collections.unmodifiableMap(nameForm2StructureRules);
             this.warnings = Collections.unmodifiableList(warnings);
+            this.strictSchema = new Schema(this);
+            this.nonStrictSchema = new Schema(new NonStrictImpl(this));
+        }
+
+        @Override
+        public Schema asNonStrictSchema() {
+            return nonStrictSchema;
+        }
+
+        @Override
+        public Schema asStrictSchema() {
+            return strictSchema;
         }
 
         @Override
@@ -1118,12 +901,6 @@
         }
     }
 
-    /*
-     * WARNING: do not reference the core schema in the following declarations.
-     */
-
-    private static final Schema EMPTY_STRICT_SCHEMA = new Schema(new EmptyImpl(true));
-    private static final Schema EMPTY_NON_STRICT_SCHEMA = new Schema(new EmptyImpl(false));
     static final String ATTR_ATTRIBUTE_TYPES = "attributeTypes";
     static final String ATTR_DIT_CONTENT_RULES = "dITContentRules";
     static final String ATTR_DIT_STRUCTURE_RULES = "dITStructureRules";
@@ -1164,7 +941,7 @@
      * @return The default schema which should be used by this application.
      */
     public static Schema getDefaultSchema() {
-        return DefaultSchema.schema;
+        return DelayedSchema.defaultSchema;
     }
 
     /**
@@ -1174,7 +951,7 @@
      * @return The empty schema.
      */
     public static Schema getEmptySchema() {
-        return EMPTY_NON_STRICT_SCHEMA;
+        return DelayedSchema.EMPTY_SCHEMA;
     }
 
     /**
@@ -1350,7 +1127,7 @@
      */
     public static void setDefaultSchema(final Schema schema) {
         Reject.ifNull(schema);
-        DefaultSchema.schema = schema;
+        DelayedSchema.defaultSchema = schema;
     }
 
     /**
@@ -1368,44 +1145,7 @@
 
     private final Impl impl;
 
-    Schema(final String schemaName, final boolean allowMalformedNamesAndOptions,
-            final boolean allowMalformedJPEGPhotos,
-            final boolean allowMalformedCertificates,
-            final boolean allowNonStandardTelephoneNumbers,
-            final boolean allowZeroLengthDirectoryStrings,
-            final Syntax defaultSyntax,
-            final MatchingRule defaultMatchingRule,
-            final Map<String, Syntax> numericOID2Syntaxes,
-            final Map<String, MatchingRule> numericOID2MatchingRules,
-            final Map<String, MatchingRuleUse> numericOID2MatchingRuleUses,
-            final Map<String, AttributeType> numericOID2AttributeTypes,
-            final Map<String, ObjectClass> numericOID2ObjectClasses,
-            final Map<String, NameForm> numericOID2NameForms,
-            final Map<String, DITContentRule> numericOID2ContentRules,
-            final Map<Integer, DITStructureRule> id2StructureRules,
-            final Map<String, List<MatchingRule>> name2MatchingRules,
-            final Map<String, List<MatchingRuleUse>> name2MatchingRuleUses,
-            final Map<String, List<AttributeType>> name2AttributeTypes,
-            final Map<String, List<ObjectClass>> name2ObjectClasses,
-            final Map<String, List<NameForm>> name2NameForms,
-            final Map<String, List<DITContentRule>> name2ContentRules,
-            final Map<String, List<DITStructureRule>> name2StructureRules,
-            final Map<String, List<NameForm>> objectClass2NameForms,
-            final Map<String, List<DITStructureRule>> nameForm2StructureRules,
-            final List<LocalizableMessage> warnings) {
-        impl =
-                new StrictImpl(schemaName, allowMalformedNamesAndOptions, allowMalformedJPEGPhotos,
-                        allowMalformedCertificates, allowNonStandardTelephoneNumbers,
-                        allowZeroLengthDirectoryStrings, defaultSyntax, defaultMatchingRule,
-                        numericOID2Syntaxes, numericOID2MatchingRules, numericOID2MatchingRuleUses,
-                        numericOID2AttributeTypes, numericOID2ObjectClasses, numericOID2NameForms,
-                        numericOID2ContentRules, id2StructureRules, name2MatchingRules,
-                        name2MatchingRuleUses, name2AttributeTypes, name2ObjectClasses,
-                        name2NameForms, name2ContentRules, name2StructureRules,
-                        objectClass2NameForms, nameForm2StructureRules, warnings);
-    }
-
-    private Schema(final Impl impl) {
+    Schema(final Impl impl) {
         this.impl = impl;
     }
 
@@ -1503,14 +1243,7 @@
      * @see Schema#isStrict()
      */
     public Schema asNonStrictSchema() {
-        if (!impl.isStrict()) {
-            return this;
-        } else if (impl instanceof StrictImpl) {
-            return new Schema(new NonStrictImpl((StrictImpl) impl));
-        } else {
-            // EmptyImpl
-            return EMPTY_NON_STRICT_SCHEMA;
-        }
+        return impl.asNonStrictSchema();
     }
 
     /**
@@ -1522,14 +1255,7 @@
      * @see Schema#isStrict()
      */
     public Schema asStrictSchema() {
-        if (impl.isStrict()) {
-            return this;
-        } else if (impl instanceof NonStrictImpl) {
-            return new Schema(((NonStrictImpl) impl).strictImpl);
-        } else {
-            // EmptyImpl
-            return EMPTY_STRICT_SCHEMA;
-        }
+        return impl.asStrictSchema();
     }
 
     /**
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/SchemaBuilder.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/SchemaBuilder.java
index 260aaf1..7697890 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/SchemaBuilder.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/SchemaBuilder.java
@@ -2578,15 +2578,16 @@
         }
 
         final Schema schema =
-                new Schema(localSchemaName, allowMalformedNamesAndOptions,
-                        allowMalformedJPEGPhotos, allowMalformedCertificates, allowNonStandardTelephoneNumbers,
-                        allowZeroLengthDirectoryStrings, defaultSyntax, defaultMatchingRule,
-                        numericOID2Syntaxes, numericOID2MatchingRules, numericOID2MatchingRuleUses,
+                new Schema.StrictImpl(localSchemaName, allowMalformedNamesAndOptions,
+                        allowMalformedJPEGPhotos, allowMalformedCertificates,
+                        allowNonStandardTelephoneNumbers, allowZeroLengthDirectoryStrings,
+                        defaultSyntax, defaultMatchingRule, numericOID2Syntaxes,
+                        numericOID2MatchingRules, numericOID2MatchingRuleUses,
                         numericOID2AttributeTypes, numericOID2ObjectClasses, numericOID2NameForms,
                         numericOID2ContentRules, id2StructureRules, name2MatchingRules,
                         name2MatchingRuleUses, name2AttributeTypes, name2ObjectClasses,
                         name2NameForms, name2ContentRules, name2StructureRules,
-                        objectClass2NameForms, nameForm2StructureRules, warnings);
+                        objectClass2NameForms, nameForm2StructureRules, warnings).asStrictSchema();
         validate(schema);
 
         // Re-init this builder so that it can continue to be used afterwards.
diff --git a/opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/SchemaTestCase.java b/opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/SchemaTestCase.java
index 989aa4b..7cf4601 100644
--- a/opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/SchemaTestCase.java
+++ b/opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/SchemaTestCase.java
@@ -34,7 +34,7 @@
  */
 @SuppressWarnings("javadoc")
 public class SchemaTestCase extends AbstractSchemaTestCase {
-    @Test(description = "Unit test for OPENDJ-1477", enabled = false)
+    @Test(description = "Unit test for OPENDJ-1477")
     public void asNonStrictSchemaAlwaysReturnsSameInstance() {
         final Schema schema = Schema.getCoreSchema();
         final Schema nonStrictSchema1 = schema.asNonStrictSchema();
@@ -43,7 +43,7 @@
         assertThat(nonStrictSchema1).isSameAs(nonStrictSchema2);
     }
 
-    @Test(description = "Unit test for OPENDJ-1477", enabled = false)
+    @Test(description = "Unit test for OPENDJ-1477")
     public void asStrictSchemaAlwaysReturnsSameInstance() {
         final Schema schema = Schema.getCoreSchema();
         final Schema strictSchema1 = schema.asStrictSchema();

--
Gitblit v1.10.0