From 5ee33e1763d2574f769a8a278806e882694feb00 Mon Sep 17 00:00:00 2001
From: Nicolas Capponi <nicolas.capponi@forgerock.com>
Date: Fri, 09 Sep 2016 09:45:23 +0000
Subject: [PATCH] OPENDJ-3089 Update AddSchemaFileTask class to replace server Schema usage by SchemaHandler
---
opendj-server-legacy/src/main/java/org/opends/server/core/SchemaHandler.java | 122 ++++++++++++++++++++++++++++-
opendj-server-legacy/src/main/java/org/opends/server/tasks/AddSchemaFileTask.java | 63 +++++++++++----
opendj-server-legacy/src/messages/org/opends/messages/task.properties | 2
3 files changed, 164 insertions(+), 23 deletions(-)
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/core/SchemaHandler.java b/opendj-server-legacy/src/main/java/org/opends/server/core/SchemaHandler.java
index cd1eb96..e72e7af 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/core/SchemaHandler.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/core/SchemaHandler.java
@@ -17,8 +17,6 @@
import static org.opends.messages.ConfigMessages.ERR_CONFIG_SCHEMA_DIR_NOT_DIRECTORY;
import static org.opends.messages.ConfigMessages.ERR_CONFIG_SCHEMA_NO_SCHEMA_DIR;
-
-import static org.forgerock.opendj.ldap.schema.CoreSchema.*;
import static org.opends.messages.SchemaMessages.NOTE_SCHEMA_IMPORT_FAILED;
import static org.opends.server.util.SchemaUtils.getElementSchemaFile;
import static org.forgerock.util.Utils.closeSilently;
@@ -51,13 +49,17 @@
import org.opends.server.schema.SubtreeSpecificationSyntax;
import org.forgerock.i18n.LocalizableMessage;
import org.forgerock.i18n.slf4j.LocalizedLogger;
+import org.forgerock.opendj.adapter.server3x.Converters;
import org.forgerock.opendj.config.ClassPropertyDefinition;
import org.forgerock.opendj.config.server.ConfigException;
+import org.forgerock.opendj.ldap.AttributeDescription;
import org.forgerock.opendj.ldap.ByteString;
import org.forgerock.opendj.ldap.Entry;
+import org.forgerock.opendj.ldap.ModificationType;
import org.forgerock.opendj.ldap.ResultCode;
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.DITStructureRule;
import org.forgerock.opendj.ldap.schema.MatchingRule;
@@ -81,11 +83,14 @@
import org.opends.server.types.Attribute;
import org.opends.server.types.DirectoryException;
import org.opends.server.types.InitializationException;
+import org.opends.server.types.Modification;
import org.opends.server.types.SchemaWriter;
import org.opends.server.util.ActivateOnceSDKSchemaIsUsed;
import org.opends.server.util.SchemaUtils;
import org.opends.server.util.StaticUtils;
+import com.sun.corba.se.spi.ior.WriteContents;
+
/**
* Responsible for loading the server schema.
* <p>
@@ -107,8 +112,13 @@
private static final String CONFIG_SCHEMA_ELEMENTS_FILE = "02-config.ldif";
private static final String CORE_SCHEMA_ELEMENTS_FILE = "00-core.ldif";
- private static final AttributeType attributeTypesType = getAttributeTypesAttributeType();
- private static final AttributeType objectClassesType = getObjectClassesAttributeType();
+ private static final AttributeType attributeTypesType = CoreSchema.getAttributeTypesAttributeType();
+ private static final AttributeType objectClassesType = CoreSchema.getObjectClassesAttributeType();
+ private static final AttributeType ditStructureRulesType = CoreSchema.getDITStructureRulesAttributeType();
+ private static final AttributeType ditContentRulesType = CoreSchema.getDITContentRulesAttributeType();
+ private static final AttributeType ldapSyntaxesType = CoreSchema.getLDAPSyntaxesAttributeType();
+ private static final AttributeType matchingRuleUsesType = CoreSchema.getMatchingRuleUseAttributeType();
+ private static final AttributeType nameFormsType = CoreSchema.getNameFormsAttributeType();
private ServerContext serverContext;
@@ -335,6 +345,29 @@
}
/**
+ * Replaces the schema with the provided schema and update the concatened schema files.
+ *
+ * @param newSchema
+ * The new schema to use
+ * @throws DirectoryException
+ * If an error occurs during update of schema or schema files
+ */
+ public void updateSchemaAndConcatenatedSchemaFiles(Schema newSchema) throws DirectoryException
+ {
+ exclusiveLock.lock();
+ try
+ {
+ switchSchema(newSchema);
+ SchemaWriter.writeConcatenatedSchema();
+ youngestModificationTime = System.currentTimeMillis();
+ }
+ finally
+ {
+ exclusiveLock.unlock();
+ }
+ }
+
+ /**
* Updates the schema option if the new value differs from the old value.
*
* @param <T> the schema option's type
@@ -657,7 +690,7 @@
for (String schemaFile : schemaFileNames)
{
- loadSchemaFile(new File(schemaDirectory, schemaFile), schemaBuilder, Schema.getDefaultSchema());
+ loadSchemaFile(new File(schemaDirectory, schemaFile), schemaBuilder, Schema.getDefaultSchema(), false);
}
}
@@ -749,6 +782,75 @@
}
/**
+ * Loads the contents of the provided schema file into the provided schema builder.
+ *
+ * @param schemaFile
+ * The schema file to load.
+ * @param schemaBuilder
+ * The schema builder to update.
+ * @param readSchema
+ * The schema used to read the schema file.
+ * @throws InitializationException
+ * If a problem occurs when reading the schema file.
+ * @throws ConfigException
+ * If a problem occurs when updating the schema builder.
+ */
+ public void loadSchemaFileIntoSchemaBuilder(final File schemaFile, final SchemaBuilder schemaBuilder,
+ final Schema readSchema) throws InitializationException, ConfigException
+ {
+ loadSchemaFile(schemaFile, schemaBuilder, readSchema, true);
+ }
+
+ /**
+ * Loads the contents of the provided schema file into the provided schema builder and returns the list
+ * of modifications.
+ *
+ * @param schemaFile
+ * The schema file to load.
+ * @param schemaBuilder
+ * The schema builder to update.
+ * @param readSchema
+ * The schema used to read the schema file.
+ * @return A list of the modifications that could be performed in order to obtain the contents of
+ * the file.
+ * @throws ConfigException
+ * If a configuration problem causes the schema element initialization to fail.
+ * @throws InitializationException
+ * If a problem occurs while initializing the schema elements that is not related to the
+ * server configuration.
+ */
+ public List<Modification> loadSchemaFileIntoSchemaBuilderAndReturnModifications(final File schemaFile,
+ final SchemaBuilder schemaBuilder, final Schema readSchema) throws InitializationException, ConfigException
+ {
+ final Entry entry = loadSchemaFile(schemaFile, schemaBuilder, readSchema, true);
+ if (entry != null)
+ {
+ return createAddModifications(entry,
+ ldapSyntaxesType,
+ attributeTypesType,
+ objectClassesType,
+ nameFormsType,
+ ditContentRulesType,
+ ditStructureRulesType,
+ matchingRuleUsesType);
+ }
+ return Collections.emptyList();
+ }
+
+ private List<Modification> createAddModifications(Entry entry, AttributeType... attrTypes)
+ {
+ List<Modification> mods = new ArrayList<>(entry.getAttributeCount());
+ for (AttributeType attrType : attrTypes)
+ {
+ for (org.forgerock.opendj.ldap.Attribute a : entry.getAllAttributes(AttributeDescription.create(attrType)))
+ {
+ mods.add(new Modification(ModificationType.ADD, Converters.toAttribute(a)));
+ }
+ }
+ return mods;
+ }
+
+ /**
* Add the schema from the provided schema file to the provided schema
* builder.
*
@@ -759,10 +861,16 @@
* be loaded.
* @param readSchema
* The schema used to read the file.
+ * @param failOnError
+ * Indicates whether an exception must be thrown if an error occurs
+ * @return the schema entry that has been read from the schema file
* @throws InitializationException
* If a problem occurs while initializing the schema elements.
+ * @throws ConfigException
+ * If a problem occurs when updating the schema builder.
*/
- private void loadSchemaFile(final File schemaFile, final SchemaBuilder schemaBuilder, final Schema readSchema)
+ private Entry loadSchemaFile(final File schemaFile, final SchemaBuilder schemaBuilder, final Schema readSchema,
+ boolean failOnError)
throws InitializationException, ConfigException
{
EntryReader reader = null;
@@ -772,9 +880,9 @@
final Entry entry = readSchemaEntry(reader, schemaFile);
if (entry != null)
{
- boolean failOnError = true;
updateSchemaBuilderWithEntry(schemaBuilder, entry, schemaFile.getName(), failOnError);
}
+ return entry;
}
finally {
Utils.closeSilently(reader);
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/tasks/AddSchemaFileTask.java b/opendj-server-legacy/src/main/java/org/opends/server/tasks/AddSchemaFileTask.java
index d70a4c4..3f1ad23 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/tasks/AddSchemaFileTask.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/tasks/AddSchemaFileTask.java
@@ -27,13 +27,16 @@
import org.forgerock.opendj.ldap.ByteString;
import org.forgerock.opendj.ldap.ResultCode;
import org.forgerock.opendj.ldap.schema.AttributeType;
+import org.forgerock.opendj.ldap.schema.Schema;
+import org.forgerock.opendj.ldap.schema.SchemaBuilder;
import org.forgerock.opendj.server.config.server.SynchronizationProviderCfg;
import org.opends.server.api.ClientConnection;
import org.opends.server.api.SynchronizationProvider;
import org.opends.server.backends.task.Task;
import org.opends.server.backends.task.TaskState;
import org.opends.server.core.DirectoryServer;
-import org.opends.server.core.SchemaConfigManager;
+import org.opends.server.core.SchemaHandler;
+import org.opends.server.core.ServerContext;
import org.opends.server.types.Attribute;
import org.opends.server.types.AttributeBuilder;
import org.opends.server.types.DirectoryException;
@@ -43,8 +46,6 @@
import org.opends.server.types.Modification;
import org.opends.server.types.Operation;
import org.opends.server.types.Privilege;
-import org.opends.server.types.Schema;
-import org.opends.server.types.SchemaWriter;
import org.opends.server.util.SchemaUtils;
import static org.opends.messages.TaskMessages.*;
@@ -89,7 +90,8 @@
// Get the attribute that specifies which schema file(s) to add.
Entry taskEntry = getTaskEntry();
- AttributeType attrType = DirectoryServer.getSchema().getAttributeType(ATTR_TASK_ADDSCHEMAFILE_FILENAME);
+ ServerContext serverContext = getServerContext();
+ AttributeType attrType = serverContext.getSchema().getAttributeType(ATTR_TASK_ADDSCHEMAFILE_FILENAME);
List<Attribute> attrList = taskEntry.getAllAttributes(attrType);
if (attrList.isEmpty())
{
@@ -100,7 +102,7 @@
// Get the name(s) of the schema files to add and make sure they exist in
// the schema directory.
- String schemaInstanceDirectory = DirectoryServer.getEnvironmentConfig().getSchemaDirectory().getPath();
+ File schemaInstanceDirectory = getSchemaDirectory();
filesToAdd = new TreeSet<>();
for (Attribute a : attrList)
{
@@ -133,17 +135,20 @@
}
}
- // Create a new dummy schema and make sure that we can add the contents of
- // all the schema files into it. Even though this duplicates work we'll
- // have to do later, it will be good to do it now as well so we can reject
+ // Make sure that we can add the contents of all the schema files into the schema.
+ // Even though this duplicates work we'll have to do later,
+ // it will be good to do it now as well so we can reject
// the entry immediately which will fail the attempt by the client to add it
// to the server, rather than having to check its status after the fact.
- Schema schema = DirectoryServer.getSchema().duplicate();
+ final SchemaHandler schemaHandler = serverContext.getSchemaHandler();
+ final Schema currentSchema = schemaHandler.getSchema();
+ final SchemaBuilder schemaBuilder = new SchemaBuilder(currentSchema);
for (String schemaFile : filesToAdd)
{
try
{
- SchemaConfigManager.loadSchemaFile(schema, schemaFile);
+ File file = new File(schemaInstanceDirectory, schemaFile);
+ schemaHandler.loadSchemaFileIntoSchemaBuilder(file, schemaBuilder, currentSchema);
}
catch (ConfigException | InitializationException e)
{
@@ -155,6 +160,19 @@
}
}
+ private File getSchemaDirectory() throws DirectoryException
+ {
+ try
+ {
+ return getServerContext().getSchemaHandler().getSchemaDirectoryPath();
+ }
+ catch (InitializationException e)
+ {
+ logger.traceException(e);
+ throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, e.getMessageObject());
+ }
+ }
+
@Override
protected TaskState runTask()
{
@@ -170,12 +188,16 @@
try
{
LinkedList<Modification> mods = new LinkedList<>();
- Schema schema = DirectoryServer.getSchema().duplicate();
+ final SchemaHandler schemaHandler = getServerContext().getSchemaHandler();
+ final Schema currentSchema = schemaHandler.getSchema();
+ final SchemaBuilder schemaBuilder = new SchemaBuilder(currentSchema);
for (String schemaFile : filesToAdd)
{
try
{
- List<Modification> modList = SchemaConfigManager.loadSchemaFileReturnModifications(schema, schemaFile);
+ File file = new File(getSchemaDirectory(), schemaFile);
+ List<Modification> modList =
+ schemaHandler.loadSchemaFileIntoSchemaBuilderAndReturnModifications(file, schemaBuilder, currentSchema);
for (Modification m : modList)
{
Attribute a = m.getAttribute();
@@ -188,7 +210,7 @@
mods.add(new Modification(m.getModificationType(), builder.toAttribute()));
}
}
- catch (ConfigException | InitializationException e)
+ catch (DirectoryException | ConfigException | InitializationException e)
{
logger.traceException(e);
logger.error(ERR_TASK_ADDSCHEMAFILE_ERROR_LOADING_SCHEMA_FILE, schemaFile, e.getMessage());
@@ -214,11 +236,20 @@
}
}
- SchemaWriter.writeConcatenatedSchema();
+ final Schema newSchema = schemaBuilder.toSchema();
+ try
+ {
+ schemaHandler.updateSchemaAndConcatenatedSchemaFiles(newSchema);
+ }
+ catch (DirectoryException e)
+ {
+ // This is very unlikely to happen because each schema file was previously loaded without error
+ logger.traceException(e);
+ logger.error(ERR_TASK_ADDSCHEMAFILE_SCHEMA_VALIDATION_ERROR, e.getMessage());
+ return TaskState.STOPPED_BY_ERROR;
+ }
}
- schema.setYoungestModificationTime(System.currentTimeMillis());
- DirectoryServer.setSchema(schema);
return TaskState.COMPLETED_SUCCESSFULLY;
}
finally
diff --git a/opendj-server-legacy/src/messages/org/opends/messages/task.properties b/opendj-server-legacy/src/messages/org/opends/messages/task.properties
index ff49037..e5a9d88 100644
--- a/opendj-server-legacy/src/messages/org/opends/messages/task.properties
+++ b/opendj-server-legacy/src/messages/org/opends/messages/task.properties
@@ -193,3 +193,5 @@
does not appear to be a replication server
ERR_TASK_RESET_CHANGE_NUMBER_INVALID_114=Invalid change number (%d) specified, it must be greater than zero
ERR_TASK_RESET_CHANGE_NUMBER_FAILED_115=Unable to reset the change number index: %s
+ERR_TASK_ADDSCHEMAFILE_SCHEMA_VALIDATION_ERROR_116=An error occurred while attempting to \
+ validate the schema after changes made by the add schema file task: %s
\ No newline at end of file
--
Gitblit v1.10.0