mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

neil_a_wilson
29.10.2007 8a060091156c631c76476582458a32daa50a5bb2
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).

This provides the first part of the fix for issue #2158.
1 files added
1 files renamed
3 files modified
564 ■■■■■ changed files
opends/src/server/org/opends/server/api/CompressedSchema.java 125 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/core/DefaultCompressedSchema.java 324 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/core/DirectoryServer.java 18 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/types/Entry.java 20 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/types/EntryEncodeConfig.java 77 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/api/CompressedSchema.java
New file
@@ -0,0 +1,125 @@
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE
 * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
 * add the following below this CDDL HEADER, with the fields enclosed
 * by brackets "[]" replaced with your own identifying information:
 *      Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 *
 *
 *      Portions Copyright 2007 Sun Microsystems, Inc.
 */
package org.opends.server.api;
import java.util.Map;
import org.opends.server.types.Attribute;
import org.opends.server.types.DirectoryException;
import org.opends.server.types.ObjectClass;
/**
 * This class provides a utility for interacting with compressed
 * representations of schema elements.
 */
@org.opends.server.types.PublicAPI(
     stability=org.opends.server.types.StabilityLevel.UNCOMMITTED,
     mayInstantiate=false,
     mayExtend=true,
     mayInvoke=false)
public abstract class CompressedSchema
{
  /**
   * 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.
   */
  public abstract byte[]
         encodeObjectClasses(Map<ObjectClass,String> objectClasses)
         throws DirectoryException;
  /**
   * 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.
   */
  public abstract Map<ObjectClass,String>
         decodeObjectClasses(byte[] encodedObjectClasses)
         throws DirectoryException;
  /**
   * 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.
   */
  public abstract byte[] encodeAttribute(Attribute attribute)
         throws DirectoryException;
  /**
   * 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.
   */
  public abstract Attribute decodeAttribute(byte[] encodedEntry,
                                            int startPos, int length)
          throws DirectoryException;
}
opends/src/server/org/opends/server/core/DefaultCompressedSchema.java
File was renamed from opends/src/server/org/opends/server/types/CompressedSchema.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)
opends/src/server/org/opends/server/core/DirectoryServer.java
@@ -42,6 +42,7 @@
import org.opends.server.api.CertificateMapper;
import org.opends.server.api.ChangeNotificationListener;
import org.opends.server.api.ClientConnection;
import org.opends.server.api.CompressedSchema;
import org.opends.server.api.ConfigAddListener;
import org.opends.server.api.ConfigChangeListener;
import org.opends.server.api.ConfigDeleteListener;
@@ -503,6 +504,9 @@
  // The crypto manager for the Directory Server.
  private CryptoManager cryptoManager;
  // The default compressed schema manager.
  private DefaultCompressedSchema compressedSchema;
  // The environment configuration for the Directory Server.
  private DirectoryEnvironmentConfig environmentConfig;
@@ -1176,6 +1180,8 @@
                  e.getLocalizedMessage());
      throw new InitializationException(message);
    }
    compressedSchema = new DefaultCompressedSchema();
  }
@@ -2403,6 +2409,18 @@
  /**
   * Retrieves the default compressed schema manager for the Directory Server.
   *
   * @return  The default compressed schema manager for the Directory Server.
   */
  public static CompressedSchema getDefaultCompressedSchema()
  {
    return directoryServer.compressedSchema;
  }
  /**
   * Gets all of the add, delete, and change listeners from the provided
   * configuration entry and all of its descendants and puts them in the
   * appropriate lists.
opends/src/server/org/opends/server/types/Entry.java
@@ -4102,7 +4102,8 @@
    LinkedList<byte[]> ocBytes = new LinkedList<byte[]>();
    if (config.compressObjectClassSets())
    {
      byte[] b = CompressedSchema.encodeObjectClasses(objectClasses);
      byte[] b = config.getCompressedSchema().
                      encodeObjectClasses(objectClasses);
      ocBytes.add(b);
      ocLength = ASN1Element.encodeLength(b.length);
      totalBytes += ocLength.length + b.length;
@@ -4138,7 +4139,8 @@
          numUserAttributes++;
          byte[] attrBytes = CompressedSchema.encodeAttribute(a);
          byte[] attrBytes =
               config.getCompressedSchema().encodeAttribute(a);
          byte[] lengthBytes =
               ASN1Element.encodeLength(attrBytes.length);
          userAttrBytes.add(lengthBytes);
@@ -4228,7 +4230,8 @@
          numOperationalAttributes++;
          byte[] attrBytes = CompressedSchema.encodeAttribute(a);
          byte[] attrBytes =
               config.getCompressedSchema().encodeAttribute(a);
          byte[] lengthBytes =
               ASN1Element.encodeLength(attrBytes.length);
          operationalAttrBytes.add(lengthBytes);
@@ -4877,7 +4880,8 @@
      {
        byte[] ocBytes = new byte[ocLength];
        System.arraycopy(entryBytes, pos, ocBytes, 0, ocLength);
        objectClasses = CompressedSchema.decodeObjectClasses(ocBytes);
        objectClasses = config.getCompressedSchema().
                             decodeObjectClasses(ocBytes);
        pos += ocLength;
      }
      else
@@ -4945,8 +4949,8 @@
          }
          // Decode the attribute.
          Attribute a = CompressedSchema.decodeAttribute(entryBytes,
                             pos, attrLength);
          Attribute a = config.getCompressedSchema().decodeAttribute(
                             entryBytes, pos, attrLength);
          List<Attribute> attrList =
               userAttributes.get(a.getAttributeType());
          if (attrList == null)
@@ -5108,8 +5112,8 @@
          }
          // Decode the attribute.
          Attribute a = CompressedSchema.decodeAttribute(entryBytes,
                             pos, attrLength);
          Attribute a = config.getCompressedSchema().decodeAttribute(
                             entryBytes, pos, attrLength);
          List<Attribute> attrList =
               operationalAttributes.get(a.getAttributeType());
          if (attrList == null)
opends/src/server/org/opends/server/types/EntryEncodeConfig.java
@@ -25,13 +25,17 @@
 *      Portions Copyright 2007 Sun Microsystems, Inc.
 */
package org.opends.server.types;
import org.opends.messages.Message;
import org.opends.server.api.CompressedSchema;
import org.opends.server.core.DirectoryServer;
import static org.opends.messages.CoreMessages.*;
/**
 * This class defines a data structure that contains configuration
 * information about how an entry should be encoded.
@@ -89,6 +93,9 @@
  // The encoded representation of this encode configuration.
  private final byte[] encodedRepresentation;
  // The compressed schema handler for this encode configuration.
  private final CompressedSchema compressedSchema;
  /**
@@ -101,6 +108,8 @@
    compressAttrDescriptions = false;
    compressObjectClassSets  = false;
    compressedSchema = DirectoryServer.getDefaultCompressedSchema();
    encodedRepresentation = new byte[] { 0x00 };
  }
@@ -125,6 +134,52 @@
    this.compressAttrDescriptions = compressAttrDescriptions;
    this.compressObjectClassSets  = compressObjectClassSets;
    compressedSchema = DirectoryServer.getDefaultCompressedSchema();
    byte flagByte = 0x00;
    if (excludeDN)
    {
      flagByte |= ENCODE_FLAG_EXCLUDE_DN;
    }
    if (compressAttrDescriptions)
    {
      flagByte |= ENCODE_FLAG_COMPRESS_ADS;
    }
    if (compressObjectClassSets)
    {
      flagByte |= ENCODE_FLAG_COMPRESS_OCS;
    }
    encodedRepresentation = new byte[] { flagByte };
  }
  /**
   * Creates a new encoded entry configuration wtih the specified
   * settings.
   *
   * @param  excludeDN                 Indicates whether to exclude
   *                                   the DN from the encoded entry.
   * @param  compressAttrDescriptions  Indicates whether to compress
   *                                   attribute descriptions.
   * @param  compressObjectClassSets   Indicates whether to compress
   *                                   object class sets.
   * @param  compressedSchema          The compressed schema manager
   *                                   for this encode config.
   */
  public EntryEncodeConfig(boolean excludeDN,
                           boolean compressAttrDescriptions,
                           boolean compressObjectClassSets,
                           CompressedSchema compressedSchema)
  {
    this.excludeDN                = excludeDN;
    this.compressAttrDescriptions = compressAttrDescriptions;
    this.compressObjectClassSets  = compressObjectClassSets;
    this.compressedSchema         = compressedSchema;
    byte flagByte = 0x00;
    if (excludeDN)
    {
@@ -188,6 +243,22 @@
  /**
   * Retrieves the compressed schema manager that may be used to
   * generate compact schema encodings with this entry encode
   * configuration.
   *
   * @return  The compressed schema manager that may be used to
   *          generate compact schema encodings with this entry encode
   *          configuration.
   */
  public CompressedSchema getCompressedSchema()
  {
    return compressedSchema;
  }
  /**
   * Encodes this entry encode configuration into a byte array
   * suitable for inclusion in the encoded entry.
   *