From 8a060091156c631c76476582458a32daa50a5bb2 Mon Sep 17 00:00:00 2001
From: neil_a_wilson <neil_a_wilson@localhost>
Date: Wed, 29 Aug 2007 06:10:13 +0000
Subject: [PATCH] Add an API that can be used to allow compressed schema tokens to be stored in alternate repositories. The current implementation is still the default server-wide mechanism using the config/schematokens.dat file, but it will be possible to use this API to create alternate implementations (e.g., one for the JE backend that stores the tokens in the database).
---
opends/src/server/org/opends/server/core/DefaultCompressedSchema.java | 324 ++++++++++++++++++++---------------------------------
1 files changed, 124 insertions(+), 200 deletions(-)
diff --git a/opends/src/server/org/opends/server/types/CompressedSchema.java b/opends/src/server/org/opends/server/core/DefaultCompressedSchema.java
similarity index 63%
rename from opends/src/server/org/opends/server/types/CompressedSchema.java
rename to opends/src/server/org/opends/server/core/DefaultCompressedSchema.java
index d7548b9..c045ed3 100644
--- a/opends/src/server/org/opends/server/types/CompressedSchema.java
+++ b/opends/src/server/org/opends/server/core/DefaultCompressedSchema.java
@@ -24,8 +24,7 @@
*
* Portions Copyright 2007 Sun Microsystems, Inc.
*/
-package org.opends.server.types;
-import org.opends.messages.Message;
+package org.opends.server.core;
@@ -39,7 +38,8 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
-import org.opends.server.core.DirectoryServer;
+import org.opends.messages.Message;
+import org.opends.server.api.CompressedSchema;
import org.opends.server.loggers.debug.DebugTracer;
import org.opends.server.protocols.asn1.ASN1Element;
import org.opends.server.protocols.asn1.ASN1Integer;
@@ -47,6 +47,13 @@
import org.opends.server.protocols.asn1.ASN1Reader;
import org.opends.server.protocols.asn1.ASN1Sequence;
import org.opends.server.protocols.asn1.ASN1Writer;
+import org.opends.server.types.Attribute;
+import org.opends.server.types.AttributeType;
+import org.opends.server.types.AttributeValue;
+import org.opends.server.types.ByteArray;
+import org.opends.server.types.DebugLogLevel;
+import org.opends.server.types.DirectoryException;
+import org.opends.server.types.ObjectClass;
import static org.opends.server.config.ConfigConstants.*;
import static org.opends.server.loggers.debug.DebugLogger.*;
@@ -56,15 +63,12 @@
/**
- * This class provides a utility for interacting with compressed
- * representations of schema elements.
+ * This class provides a default implementation of a compressed schema manager
+ * that will store the schema definitions in a binary file
+ * (config/schematokens.dat).
*/
-@org.opends.server.types.PublicAPI(
- stability=org.opends.server.types.StabilityLevel.PRIVATE,
- mayInstantiate=false,
- mayExtend=false,
- mayInvoke=false)
-public final class CompressedSchema
+public final class DefaultCompressedSchema
+ extends CompressedSchema
{
/**
* The tracer object for the debug logger.
@@ -73,13 +77,6 @@
- /**
- * The singleton instance that will be used to perform the mapping.
- */
- private static CompressedSchema instance = new CompressedSchema();
-
-
-
// The counter used for attribute descriptions.
private AtomicInteger adCounter;
@@ -90,40 +87,33 @@
private ConcurrentHashMap<ByteArray,AttributeType> atDecodeMap;
// The map between encoded representations and attribute options.
- private ConcurrentHashMap<ByteArray,
- LinkedHashSet<String>> aoDecodeMap;
+ private ConcurrentHashMap<ByteArray,LinkedHashSet<String>> aoDecodeMap;
// The map between encoded representations and object class sets.
- private ConcurrentHashMap<ByteArray,
- Map<ObjectClass,String>> ocDecodeMap;
+ private ConcurrentHashMap<ByteArray,Map<ObjectClass,String>> ocDecodeMap;
// The map between attribute descriptions and their encoded
// representations.
private ConcurrentHashMap<AttributeType,
- ConcurrentHashMap<LinkedHashSet<String>,ByteArray>>
- adEncodeMap;
+ ConcurrentHashMap<LinkedHashSet<String>,ByteArray>> adEncodeMap;
// The map between object class sets and encoded representations.
- private ConcurrentHashMap<Map<ObjectClass,String>,
- ByteArray> ocEncodeMap;
+ private ConcurrentHashMap<Map<ObjectClass,String>,ByteArray> ocEncodeMap;
/**
* Creates a new instance of this compressed schema manager.
*/
- private CompressedSchema()
+ public DefaultCompressedSchema()
{
atDecodeMap = new ConcurrentHashMap<ByteArray,AttributeType>();
- aoDecodeMap = new ConcurrentHashMap<ByteArray,
- LinkedHashSet<String>>();
- ocDecodeMap = new ConcurrentHashMap<ByteArray,
- Map<ObjectClass,String>>();
- adEncodeMap = new ConcurrentHashMap<AttributeType,
- ConcurrentHashMap<LinkedHashSet<String>,
- ByteArray>>();
- ocEncodeMap = new ConcurrentHashMap<Map<ObjectClass,String>,
- ByteArray>();
+ aoDecodeMap = new ConcurrentHashMap<ByteArray,LinkedHashSet<String>>();
+ ocDecodeMap = new ConcurrentHashMap<ByteArray,Map<ObjectClass,String>>();
+ adEncodeMap =
+ new ConcurrentHashMap<AttributeType,
+ ConcurrentHashMap<LinkedHashSet<String>,ByteArray>>();
+ ocEncodeMap = new ConcurrentHashMap<Map<ObjectClass,String>,ByteArray>();
adCounter = new AtomicInteger(1);
ocCounter = new AtomicInteger(1);
@@ -142,10 +132,9 @@
try
{
- // Determine the location of the compressed schema data file
- // It should be in the config directory with a name of
- // "schematokens.dat". If that file doesn't exist, then don't
- // do anything.
+ // Determine the location of the compressed schema data file. It should
+ // be in the config directory with a name of "schematokens.dat". If that
+ // file doesn't exist, then don't do anything.
String path = DirectoryServer.getServerRoot() + File.separator +
CONFIG_DIR_NAME + File.separator +
COMPRESSED_SCHEMA_FILE_NAME;
@@ -157,17 +146,14 @@
reader = new ASN1Reader(inputStream);
- // The first element in the file should be a sequence of object
- // class sets. Each object class set will itself be a sequence
- // of octet strings, where the first one is the token and the
- // remaining elements are the names of the associated object
- // classes.
- ASN1Sequence ocSequence =
- reader.readElement().decodeAsSequence();
+ // The first element in the file should be a sequence of object class
+ // sets. Each object class set will itself be a sequence of octet
+ // strings, where the first one is the token and the remaining elements
+ // are the names of the associated object classes.
+ ASN1Sequence ocSequence = reader.readElement().decodeAsSequence();
for (ASN1Element element : ocSequence.elements())
{
- ArrayList<ASN1Element> elements =
- element.decodeAsSequence().elements();
+ ArrayList<ASN1Element> elements = element.decodeAsSequence().elements();
ASN1OctetString os = elements.get(0).decodeAsOctetString();
ByteArray token = new ByteArray(os.value());
@@ -178,8 +164,7 @@
os = elements.get(i).decodeAsOctetString();
String ocName = os.stringValue();
String lowerName = toLowerCase(ocName);
- ObjectClass oc =
- DirectoryServer.getObjectClass(lowerName, true);
+ ObjectClass oc = DirectoryServer.getObjectClass(lowerName, true);
ocMap.put(oc, ocName);
}
@@ -188,24 +173,21 @@
}
- // The second element in the file should be an integer element
- // that holds the value to use to initialize the object class
- // counter.
+ // The second element in the file should be an integer element that holds
+ // the value to use to initialize the object class counter.
ASN1Element counterElement = reader.readElement();
ocCounter.set(counterElement.decodeAsInteger().intValue());
- // The third element in the file should be a sequence of
- // attribute description components. Each attribute description
- // component will itself be a sequence of octet strings, where
- // the first one is the token, the second is the attribute name,
- // and all remaining elements are the attribute options.
- ASN1Sequence adSequence =
- reader.readElement().decodeAsSequence();
+ // The third element in the file should be a sequence of attribute
+ // description components. Each attribute description component will
+ // itself be a sequence of octet strings, where the first one is the
+ // token, the second is the attribute name, and all remaining elements are
+ // the attribute options.
+ ASN1Sequence adSequence = reader.readElement().decodeAsSequence();
for (ASN1Element element : adSequence.elements())
{
- ArrayList<ASN1Element> elements =
- element.decodeAsSequence().elements();
+ ArrayList<ASN1Element> elements = element.decodeAsSequence().elements();
ASN1OctetString os = elements. get(0).decodeAsOctetString();
ByteArray token = new ByteArray(os.value());
@@ -230,8 +212,7 @@
adEncodeMap.get(attrType);
if (map == null)
{
- map = new ConcurrentHashMap<LinkedHashSet<String>,
- ByteArray>(1);
+ map = new ConcurrentHashMap<LinkedHashSet<String>,ByteArray>(1);
map.put(options, token);
adEncodeMap.put(attrType, map);
}
@@ -242,9 +223,8 @@
}
- // The fourth element in the file should be an integer element
- // that holds the value to use to initialize the attribute
- // description counter.
+ // The fourth element in the file should be an integer element that holds
+ // the value to use to initialize the attribute description counter.
counterElement = reader.readElement();
adCounter.set(counterElement.decodeAsInteger().intValue());
}
@@ -282,8 +262,8 @@
/**
* Writes the compressed schema information to disk.
*
- * @throws DirectoryException If a problem occurs while writing
- * the updated information.
+ * @throws DirectoryException If a problem occurs while writing the updated
+ * information.
*/
private void save()
throws DirectoryException
@@ -291,9 +271,9 @@
ASN1Writer writer = null;
try
{
- // Determine the location of the "live" compressed schema data
- // file, and then append ".tmp" to get the name of the temporary
- // file that we will use.
+ // Determine the location of the "live" compressed schema data file, and
+ // then append ".tmp" to get the name of the temporary file that we will
+ // use.
String path = DirectoryServer.getServerRoot() + File.separator +
CONFIG_DIR_NAME + File.separator +
COMPRESSED_SCHEMA_FILE_NAME;
@@ -303,11 +283,10 @@
writer = new ASN1Writer(outputStream);
- // The first element in the file should be a sequence of object
- // class sets. Each object class set will itself be a sequence
- // of octet strings, where the first one is the token and the
- // remaining elements are the names of the associated object
- // classes.
+ // The first element in the file should be a sequence of object class
+ // sets. Each object class set will itself be a sequence of octet
+ // strings, where the first one is the token and the remaining elements
+ // are the names of the associated object classes.
ArrayList<ASN1Element> ocElements =
new ArrayList<ASN1Element>(ocDecodeMap.size());
for (Map.Entry<ByteArray,Map<ObjectClass,String>> mapEntry :
@@ -330,17 +309,16 @@
writer.writeElement(new ASN1Sequence(ocElements));
- // The second element in the file should be an integer element
- // that holds the value to use to initialize the object class
- // counter.
+ // The second element in the file should be an integer element that holds
+ // the value to use to initialize the object class counter.
writer.writeElement(new ASN1Integer(ocCounter.get()));
- // The third element in the file should be a sequence of
- // attribute description components. Each attribute description
- // component will itself be a sequence of octet strings, where
- // the first one is the token, the second is the attribute name,
- // and all remaining elements are the attribute options.
+ // The third element in the file should be a sequence of attribute
+ // description components. Each attribute description component will
+ // itself be a sequence of octet strings, where the first one is the
+ // token, the second is the attribute name, and all remaining elements are
+ // the attribute options.
ArrayList<ASN1Element> adElements =
new ArrayList<ASN1Element>(atDecodeMap.size());
for (ByteArray token : atDecodeMap.keySet())
@@ -362,9 +340,8 @@
writer.writeElement(new ASN1Sequence(adElements));
- // The fourth element in the file should be an integer element
- // that holds the value to use to initialize the attribute
- // description counter.
+ // The fourth element in the file should be an integer element that holds
+ // the value to use to initialize the attribute description counter.
writer.writeElement(new ASN1Integer(adCounter.get()));
@@ -375,8 +352,7 @@
if (liveFile.exists())
{
- File saveFile =
- new File(liveFile.getAbsolutePath() + ".save");
+ File saveFile = new File(liveFile.getAbsolutePath() + ".save");
if (saveFile.exists())
{
saveFile.delete();
@@ -392,12 +368,10 @@
TRACER.debugCaught(DebugLogLevel.ERROR, e);
}
- Message message =
- ERR_COMPRESSEDSCHEMA_CANNOT_WRITE_UPDATED_DATA.
- get(stackTraceToSingleLineString(e));
- throw new DirectoryException(
- DirectoryServer.getServerErrorResultCode(),
- message, e);
+ Message message = ERR_COMPRESSEDSCHEMA_CANNOT_WRITE_UPDATED_DATA.get(
+ stackTraceToSingleLineString(e));
+ throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
+ message, e);
}
finally
{
@@ -421,39 +395,25 @@
/**
- * Encodes the provided set of object classes to a byte array. If
- * the same set had been previously encoded, then the cached value
- * will be used. Otherwise, a new value will be created.
- *
- * @param objectClasses The set of object classes for which to
- * retrieve the corresponding byte array
- * token.
- *
- * @return A byte array containing the identifier assigned to the
- * object class set.
- *
- * @throws DirectoryException If a problem occurs while attempting
- * to determine the appropriate
- * identifier.
+ * {@inheritDoc}
*/
- public static byte[]
- encodeObjectClasses(Map<ObjectClass,String> objectClasses)
+ @Override()
+ public byte[] encodeObjectClasses(Map<ObjectClass,String> objectClasses)
throws DirectoryException
{
- ByteArray encodedClasses =
- instance.ocEncodeMap.get(objectClasses);
+ ByteArray encodedClasses = ocEncodeMap.get(objectClasses);
if (encodedClasses == null)
{
- synchronized (instance.ocEncodeMap)
+ synchronized (ocEncodeMap)
{
- int setValue = instance.ocCounter.getAndIncrement();
+ int setValue = ocCounter.getAndIncrement();
byte[] array = encodeInt(setValue);
encodedClasses = new ByteArray(array);
- instance.ocEncodeMap.put(objectClasses, encodedClasses);
- instance.ocDecodeMap.put(encodedClasses, objectClasses);
+ ocEncodeMap.put(objectClasses, encodedClasses);
+ ocDecodeMap.put(encodedClasses, objectClasses);
- instance.save();
+ save();
return array;
}
}
@@ -466,30 +426,21 @@
/**
- * Decodes an object class set from the provided byte array.
- *
- * @param encodedObjectClasses The byte array containing the
- * object class set identifier.
- *
- * @return The decoded object class set.
- *
- * @throws DirectoryException If the provided byte array cannot be
- * decoded as an object class set.
+ * {@inheritDoc}
*/
- public static Map<ObjectClass,String>
- decodeObjectClasses(byte[] encodedObjectClasses)
+ @Override()
+ public Map<ObjectClass,String> decodeObjectClasses(
+ byte[] encodedObjectClasses)
throws DirectoryException
{
ByteArray byteArray = new ByteArray(encodedObjectClasses);
- Map<ObjectClass,String> ocMap =
- instance.ocDecodeMap.get(byteArray);
+ Map<ObjectClass,String> ocMap = ocDecodeMap.get(byteArray);
if (ocMap == null)
{
Message message = ERR_COMPRESSEDSCHEMA_UNKNOWN_OC_TOKEN.get(
- bytesToHex(encodedObjectClasses));
- throw new DirectoryException(
- DirectoryServer.getServerErrorResultCode(),
- message);
+ bytesToHex(encodedObjectClasses));
+ throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
+ message);
}
else
{
@@ -500,42 +451,33 @@
/**
- * Encodes the information in the provided attribute to a byte
- * array.
- *
- * @param attribute The attribute to be encoded.
- *
- * @return An encoded representation of the provided attribute.
- *
- * @throws DirectoryException If a problem occurs while attempting
- * to determine the appropriate
- * identifier.
+ * {@inheritDoc}
*/
- public static byte[] encodeAttribute(Attribute attribute)
+ @Override()
+ public byte[] encodeAttribute(Attribute attribute)
throws DirectoryException
{
AttributeType type = attribute.getAttributeType();
LinkedHashSet<String> options = attribute.getOptions();
ConcurrentHashMap<LinkedHashSet<String>,ByteArray> map =
- instance.adEncodeMap.get(type);
+ adEncodeMap.get(type);
if (map == null)
{
byte[] array;
- synchronized (instance.adEncodeMap)
+ synchronized (adEncodeMap)
{
- map = new ConcurrentHashMap<LinkedHashSet<String>,
- ByteArray>(1);
+ map = new ConcurrentHashMap<LinkedHashSet<String>,ByteArray>(1);
- int intValue = instance.adCounter.getAndIncrement();
+ int intValue = adCounter.getAndIncrement();
array = encodeInt(intValue);
ByteArray byteArray = new ByteArray(array);
map.put(options,byteArray);
- instance.adEncodeMap.put(type, map);
- instance.atDecodeMap.put(byteArray, type);
- instance.aoDecodeMap.put(byteArray, options);
- instance.save();
+ adEncodeMap.put(type, map);
+ atDecodeMap.put(byteArray, type);
+ aoDecodeMap.put(byteArray, options);
+ save();
}
return encodeAttribute(array, attribute);
@@ -548,14 +490,14 @@
byte[] array;
synchronized (map)
{
- int intValue = instance.adCounter.getAndIncrement();
+ int intValue = adCounter.getAndIncrement();
array = encodeInt(intValue);
byteArray = new ByteArray(array);
map.put(options,byteArray);
- instance.atDecodeMap.put(byteArray, type);
- instance.aoDecodeMap.put(byteArray, options);
- instance.save();
+ atDecodeMap.put(byteArray, type);
+ aoDecodeMap.put(byteArray, options);
+ save();
}
return encodeAttribute(array, attribute);
@@ -579,8 +521,7 @@
*
* @return An encoded representation of the provided attribute.
*/
- private static byte[] encodeAttribute(byte[] adArray,
- Attribute attribute)
+ private byte[] encodeAttribute(byte[] adArray, Attribute attribute)
{
LinkedHashSet<AttributeValue> values = attribute.getValues();
int totalValuesLength = 0;
@@ -624,26 +565,15 @@
/**
- * Decodes the contents of the provided array as an attribute.
- *
- * @param encodedEntry The byte array containing the encoded
- * entry.
- * @param startPos The position within the array of the first
- * byte for the attribute to decode.
- * @param length The number of bytes contained in the
- * encoded attribute.
- *
- * @return The decoded attribute.
- *
- * @throws DirectoryException If the attribute could not be
- * decoded properly for some reason.
+ * {@inheritDoc}
*/
- public static Attribute decodeAttribute(byte[] encodedEntry,
- int startPos, int length)
+ @Override()
+ public Attribute decodeAttribute(byte[] encodedEntry, int startPos,
+ int length)
throws DirectoryException
{
- // Figure out how many bytes are in the token that is the
- // placeholder for the attribute description.
+ // Figure out how many bytes are in the token that is the placeholder for
+ // the attribute description.
int pos = startPos;
int adArrayLength = encodedEntry[pos] & 0x7F;
if (adArrayLength != encodedEntry[pos++])
@@ -652,27 +582,24 @@
adArrayLength = 0;
for (int i=0; i < numLengthBytes; i++, pos++)
{
- adArrayLength =
- (adArrayLength << 8) | (encodedEntry[pos] & 0xFF);
+ adArrayLength = (adArrayLength << 8) | (encodedEntry[pos] & 0xFF);
}
}
- // Get the attribute description token and make sure it resolves
- // to an attribute type and option set.
+ // Get the attribute description token and make sure it resolves to an
+ // attribute type and option set.
ByteArray adArray = new ByteArray(new byte[adArrayLength]);
- System.arraycopy(encodedEntry, pos, adArray.array(), 0,
- adArrayLength);
+ System.arraycopy(encodedEntry, pos, adArray.array(), 0, adArrayLength);
pos += adArrayLength;
- AttributeType attrType = instance.atDecodeMap.get(adArray);
- LinkedHashSet<String> options = instance.aoDecodeMap.get(adArray);
+ AttributeType attrType = atDecodeMap.get(adArray);
+ LinkedHashSet<String> options = aoDecodeMap.get(adArray);
if ((attrType == null) || (options == null))
{
- Message message = ERR_COMPRESSEDSCHEMA_UNRECOGNIZED_AD_TOKEN.
- get(bytesToHex(adArray.array()));
- throw new DirectoryException(
- DirectoryServer.getServerErrorResultCode(),
- message);
+ Message message = ERR_COMPRESSEDSCHEMA_UNRECOGNIZED_AD_TOKEN.get(
+ bytesToHex(adArray.array()));
+ throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
+ message);
}
@@ -701,20 +628,17 @@
valueLength = 0;
for (int j=0; j < valueLengthBytes; j++, pos++)
{
- valueLength =
- (valueLength << 8) | (encodedEntry[pos] & 0xFF);
+ valueLength = (valueLength << 8) | (encodedEntry[pos] & 0xFF);
}
}
byte[] valueBytes = new byte[valueLength];
System.arraycopy(encodedEntry, pos, valueBytes, 0, valueLength);
pos += valueLength;
- values.add(new AttributeValue(attrType,
- new ASN1OctetString(valueBytes)));
+ values.add(new AttributeValue(attrType, new ASN1OctetString(valueBytes)));
}
- return new Attribute(attrType, attrType.getPrimaryName(), options,
- values);
+ return new Attribute(attrType, attrType.getPrimaryName(), options, values);
}
@@ -726,7 +650,7 @@
*
* @return The byte array containing the encoded int value.
*/
- private static byte[] encodeInt(int intValue)
+ private byte[] encodeInt(int intValue)
{
byte[] array;
if (intValue <= 0xFF)
--
Gitblit v1.10.0