From 22094368c2865dcfb6daf8366425212b721a4657 Mon Sep 17 00:00:00 2001
From: matthew_swift <matthew_swift@localhost>
Date: Thu, 05 Feb 2009 17:42:14 +0000
Subject: [PATCH] Merge ASN1 branch to trunk

---
 opends/src/server/org/opends/server/core/DefaultCompressedSchema.java |  341 ++++++++++++++++++++------------------------------------
 1 files changed, 123 insertions(+), 218 deletions(-)

diff --git a/opends/src/server/org/opends/server/core/DefaultCompressedSchema.java b/opends/src/server/org/opends/server/core/DefaultCompressedSchema.java
index 6f67cff..d4316bd 100644
--- a/opends/src/server/org/opends/server/core/DefaultCompressedSchema.java
+++ b/opends/src/server/org/opends/server/core/DefaultCompressedSchema.java
@@ -31,7 +31,6 @@
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
-import java.util.ArrayList;
 import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
 import java.util.Map;
@@ -42,21 +41,10 @@
 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;
-import org.opends.server.protocols.asn1.ASN1OctetString;
 import org.opends.server.protocols.asn1.ASN1Reader;
-import org.opends.server.protocols.asn1.ASN1Sequence;
+import org.opends.server.protocols.asn1.ASN1;
 import org.opends.server.protocols.asn1.ASN1Writer;
-import org.opends.server.types.Attribute;
-import org.opends.server.types.AttributeBuilder;
-import org.opends.server.types.AttributeType;
-import org.opends.server.types.AttributeValue;
-import org.opends.server.types.Attributes;
-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 org.opends.server.types.*;
 
 import static org.opends.server.config.ConfigConstants.*;
 import static org.opends.server.loggers.debug.DebugLogger.*;
@@ -87,21 +75,22 @@
   private AtomicInteger ocCounter;
 
   // The map between encoded representations and attribute types.
-  private ConcurrentHashMap<ByteArray,AttributeType> atDecodeMap;
+  private ConcurrentHashMap<ByteSequence,AttributeType> atDecodeMap;
 
   // The map between encoded representations and attribute options.
-  private ConcurrentHashMap<ByteArray,Set<String>> aoDecodeMap;
+  private ConcurrentHashMap<ByteSequence,Set<String>> aoDecodeMap;
 
   // The map between encoded representations and object class sets.
-  private ConcurrentHashMap<ByteArray,Map<ObjectClass,String>> ocDecodeMap;
+  private ConcurrentHashMap<ByteSequence,Map<ObjectClass,String>> ocDecodeMap;
 
   // The map between attribute descriptions and their encoded
   // representations.
-  private ConcurrentHashMap<AttributeType,
-               ConcurrentHashMap<Set<String>,ByteArray>> adEncodeMap;
+  private final ConcurrentHashMap<AttributeType,
+                ConcurrentHashMap<Set<String>, ByteSequence>> adEncodeMap;
 
   // The map between object class sets and encoded representations.
-  private ConcurrentHashMap<Map<ObjectClass,String>,ByteArray> ocEncodeMap;
+  private final ConcurrentHashMap<Map<ObjectClass,String>,
+      ByteSequence> ocEncodeMap;
 
 
 
@@ -110,12 +99,14 @@
    */
   public DefaultCompressedSchema()
   {
-    atDecodeMap = new ConcurrentHashMap<ByteArray, AttributeType>();
-    aoDecodeMap = new ConcurrentHashMap<ByteArray, Set<String>>();
-    ocDecodeMap = new ConcurrentHashMap<ByteArray, Map<ObjectClass, String>>();
+    atDecodeMap = new ConcurrentHashMap<ByteSequence, AttributeType>();
+    aoDecodeMap = new ConcurrentHashMap<ByteSequence, Set<String>>();
+    ocDecodeMap =
+        new ConcurrentHashMap<ByteSequence, Map<ObjectClass, String>>();
     adEncodeMap = new ConcurrentHashMap
-      <AttributeType, ConcurrentHashMap<Set<String>, ByteArray>>();
-    ocEncodeMap = new ConcurrentHashMap<Map<ObjectClass, String>, ByteArray>();
+      <AttributeType, ConcurrentHashMap<Set<String>, ByteSequence>>();
+    ocEncodeMap = new ConcurrentHashMap<Map<ObjectClass, String>,
+        ByteSequence>();
 
     adCounter = new AtomicInteger(1);
     ocCounter = new AtomicInteger(1);
@@ -130,7 +121,7 @@
    */
   private void load()
   {
-    ASN1Reader reader = null;
+    FileInputStream inputStream = null;
 
     try
     {
@@ -144,41 +135,40 @@
       {
         return;
       }
-      FileInputStream inputStream = new FileInputStream(path);
-      reader = new ASN1Reader(inputStream);
+      inputStream = new FileInputStream(path);
+      ASN1Reader reader = ASN1.getReader(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();
-      for (ASN1Element element : ocSequence.elements())
+      reader.readStartSequence();
+      while(reader.hasNextElement())
       {
-        ArrayList<ASN1Element> elements = element.decodeAsSequence().elements();
-        ASN1OctetString os = elements.get(0).decodeAsOctetString();
-        ByteArray token = new ByteArray(os.value());
+        reader.readStartSequence();
+        ByteSequence token = reader.readOctetString();
 
         LinkedHashMap<ObjectClass,String> ocMap =
-             new LinkedHashMap<ObjectClass,String>(elements.size()-1);
-        for (int i=1; i < elements.size(); i++)
+             new LinkedHashMap<ObjectClass,String>();
+        while(reader.hasNextElement())
         {
-          os = elements.get(i).decodeAsOctetString();
-          String ocName = os.stringValue();
+          String ocName = reader.readOctetStringAsString();
           String lowerName = toLowerCase(ocName);
           ObjectClass oc = DirectoryServer.getObjectClass(lowerName, true);
           ocMap.put(oc, ocName);
         }
+        reader.readEndSequence();
 
         ocEncodeMap.put(ocMap, token);
         ocDecodeMap.put(token, ocMap);
       }
+      reader.readEndSequence();
 
 
       // 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());
+      ocCounter.set((int)reader.readInteger());
 
 
       // The third element in the file should be a sequence of attribute
@@ -186,35 +176,32 @@
       // 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())
+      reader.readStartSequence();
+      while(reader.hasNextElement())
       {
-        ArrayList<ASN1Element> elements = element.decodeAsSequence().elements();
-        ASN1OctetString os = elements. get(0).decodeAsOctetString();
-        ByteArray token = new ByteArray(os.value());
-
-        os = elements.get(1).decodeAsOctetString();
-        String attrName = os.stringValue();
+        reader.readStartSequence();
+        ByteSequence token = reader.readOctetString();
+        String attrName = reader.readOctetStringAsString();
         String lowerName = toLowerCase(attrName);
         AttributeType attrType =
-             DirectoryServer.getAttributeType(lowerName, true);
+            DirectoryServer.getAttributeType(lowerName, true);
 
         LinkedHashSet<String> options =
-             new LinkedHashSet<String>(elements.size()-2);
-        for (int i=2; i < elements.size(); i++)
+            new LinkedHashSet<String>();
+        while(reader.hasNextElement())
         {
-          os = elements.get(i).decodeAsOctetString();
-          options.add(os.stringValue());
+          options.add(reader.readOctetStringAsString());
         }
+        reader.readEndSequence();
 
         atDecodeMap.put(token, attrType);
         aoDecodeMap.put(token, options);
 
-        ConcurrentHashMap<Set<String>, ByteArray> map = adEncodeMap
+        ConcurrentHashMap<Set<String>, ByteSequence> map = adEncodeMap
             .get(attrType);
         if (map == null)
         {
-          map = new ConcurrentHashMap<Set<String>, ByteArray>(1);
+          map = new ConcurrentHashMap<Set<String>, ByteSequence>(1);
           map.put(options, token);
           adEncodeMap.put(attrType, map);
         }
@@ -223,12 +210,12 @@
           map.put(options, token);
         }
       }
+      reader.readEndSequence();
 
 
       // 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());
+      adCounter.set((int)reader.readInteger());
     }
     catch (Exception e)
     {
@@ -244,9 +231,9 @@
     {
       try
       {
-        if (reader != null)
+        if (inputStream != null)
         {
-          reader.close();
+          inputStream.close();
         }
       }
       catch (Exception e)
@@ -270,7 +257,7 @@
   private void save()
           throws DirectoryException
   {
-    ASN1Writer writer = null;
+    FileOutputStream outputStream = null;
     try
     {
       // Determine the location of the "live" compressed schema data file, and
@@ -281,39 +268,34 @@
                     COMPRESSED_SCHEMA_FILE_NAME;
       String tempPath = path + ".tmp";
 
-      FileOutputStream outputStream = new FileOutputStream(tempPath);
-      writer = new ASN1Writer(outputStream);
+      outputStream = new FileOutputStream(tempPath);
+      ASN1Writer writer = ASN1.getWriter(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.
-      ArrayList<ASN1Element> ocElements =
-           new ArrayList<ASN1Element>(ocDecodeMap.size());
-      for (Map.Entry<ByteArray,Map<ObjectClass,String>> mapEntry :
+      writer.writeStartSequence();
+      for (Map.Entry<ByteSequence,Map<ObjectClass,String>> mapEntry :
            ocDecodeMap.entrySet())
       {
-        ByteArray token = mapEntry.getKey();
+        writer.writeStartSequence();
+        writer.writeOctetString(mapEntry.getKey());
         Map<ObjectClass,String> ocMap = mapEntry.getValue();
 
-        ArrayList<ASN1Element> elements =
-             new ArrayList<ASN1Element>(ocMap.size()+1);
-        elements.add(new ASN1OctetString(token.array()));
-
         for (String ocName : ocMap.values())
         {
-          elements.add(new ASN1OctetString(ocName));
+          writer.writeOctetString(ocName);
         }
-
-        ocElements.add(new ASN1Sequence(elements));
+        writer.writeEndSequence();
       }
-      writer.writeElement(new ASN1Sequence(ocElements));
+      writer.writeEndSequence();
 
 
       // 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()));
+      writer.writeInteger(ocCounter.get());
 
 
       // The third element in the file should be a sequence of attribute
@@ -321,34 +303,31 @@
       // 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())
+      writer.writeStartSequence();
+      for (ByteSequence token : atDecodeMap.keySet())
       {
+        writer.writeStartSequence();
         AttributeType attrType = atDecodeMap.get(token);
         Set<String> options = aoDecodeMap.get(token);
 
-        ArrayList<ASN1Element> elements =
-             new ArrayList<ASN1Element>(options.size()+2);
-        elements.add(new ASN1OctetString(token.array()));
-        elements.add(new ASN1OctetString(attrType.getNameOrOID()));
+        writer.writeOctetString(token);
+        writer.writeOctetString(attrType.getNameOrOID());
         for (String option : options)
         {
-          elements.add(new ASN1OctetString(option));
+          writer.writeOctetString(option);
         }
-
-        adElements.add(new ASN1Sequence(elements));
+        writer.writeEndSequence();
       }
-      writer.writeElement(new ASN1Sequence(adElements));
+      writer.writeEndSequence();
 
 
       // 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()));
+      writer.writeInteger(adCounter.get());
 
 
       // Close the writer and swing the temp file into place.
-      writer.close();
+      outputStream.close();
       File liveFile = new File(path);
       File tempFile = new File(tempPath);
 
@@ -379,9 +358,9 @@
     {
       try
       {
-        if (writer != null)
+        if (outputStream != null)
         {
-          writer.close();
+          outputStream.close();
         }
       }
       catch (Exception e)
@@ -400,29 +379,27 @@
    * {@inheritDoc}
    */
   @Override()
-  public byte[] encodeObjectClasses(Map<ObjectClass,String> objectClasses)
+  public void encodeObjectClasses(ByteStringBuilder entryBuffer,
+                                  Map<ObjectClass,String> objectClasses)
          throws DirectoryException
   {
-    ByteArray encodedClasses = ocEncodeMap.get(objectClasses);
+    ByteSequence encodedClasses = ocEncodeMap.get(objectClasses);
     if (encodedClasses == null)
     {
       synchronized (ocEncodeMap)
       {
         int setValue = ocCounter.getAndIncrement();
-        byte[] array = encodeInt(setValue);
 
-        encodedClasses = new ByteArray(array);
+        encodedClasses = ByteString.wrap(encodeInt(setValue));
         ocEncodeMap.put(objectClasses, encodedClasses);
         ocDecodeMap.put(encodedClasses, objectClasses);
 
         save();
-        return array;
       }
     }
-    else
-    {
-      return encodedClasses.array();
-    }
+
+    entryBuffer.appendBERLength(encodedClasses.length());
+    encodedClasses.copyTo(entryBuffer);
   }
 
 
@@ -432,17 +409,17 @@
    */
   @Override()
   public Map<ObjectClass,String> decodeObjectClasses(
-                                      byte[] encodedObjectClasses)
-         throws DirectoryException
+      ByteSequenceReader entryBufferReader) throws DirectoryException
   {
-    ByteArray byteArray = new ByteArray(encodedObjectClasses);
+    int tokenLength = entryBufferReader.getBERLength();
+    ByteSequence byteArray = entryBufferReader.getByteSequence(tokenLength);
     Map<ObjectClass,String> ocMap = ocDecodeMap.get(byteArray);
     if (ocMap == null)
     {
-      Message message = ERR_COMPRESSEDSCHEMA_UNKNOWN_OC_TOKEN.get(
-                             bytesToHex(encodedObjectClasses));
+      Message message = ERR_COMPRESSEDSCHEMA_UNKNOWN_OC_TOKEN.get(byteArray
+          .toByteString().toHex());
       throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
-                                   message);
+          message);
     }
     else
     {
@@ -456,23 +433,22 @@
    * {@inheritDoc}
    */
   @Override()
-  public byte[] encodeAttribute(Attribute attribute)
-         throws DirectoryException
+  public void encodeAttribute(ByteStringBuilder entryBuffer,
+                              Attribute attribute) throws DirectoryException
   {
     AttributeType type = attribute.getAttributeType();
     Set<String> options = attribute.getOptions();
 
-    ConcurrentHashMap<Set<String>, ByteArray> map = adEncodeMap.get(type);
+    ConcurrentHashMap<Set<String>, ByteSequence> map = adEncodeMap.get(type);
     if (map == null)
     {
-      byte[] array;
+      ByteString byteArray;
       synchronized (adEncodeMap)
       {
-        map = new ConcurrentHashMap<Set<String>,ByteArray>(1);
+        map = new ConcurrentHashMap<Set<String>, ByteSequence>(1);
 
         int intValue = adCounter.getAndIncrement();
-        array = encodeInt(intValue);
-        ByteArray byteArray = new ByteArray(array);
+        byteArray = ByteString.wrap(encodeInt(intValue));
         map.put(options,byteArray);
 
         adEncodeMap.put(type, map);
@@ -481,32 +457,26 @@
         save();
       }
 
-      return encodeAttribute(array, attribute);
+      encodeAttribute(entryBuffer, byteArray, attribute);
     }
     else
     {
-      ByteArray byteArray = map.get(options);
+      ByteSequence byteArray = map.get(options);
       if (byteArray == null)
       {
-        byte[] array;
         synchronized (map)
         {
           int intValue = adCounter.getAndIncrement();
-          array = encodeInt(intValue);
-          byteArray = new ByteArray(array);
+          byteArray = ByteString.wrap(encodeInt(intValue));
           map.put(options,byteArray);
 
           atDecodeMap.put(byteArray, type);
           aoDecodeMap.put(byteArray, options);
           save();
         }
+      }
 
-        return encodeAttribute(array, attribute);
-      }
-      else
-      {
-        return encodeAttribute(byteArray.array(), attribute);
-      }
+      encodeAttribute(entryBuffer, byteArray, attribute);
     }
   }
 
@@ -516,50 +486,27 @@
    * Encodes the information in the provided attribute to a byte
    * array.
    *
+   * @param  buffer     The byte buffer to encode the attribute into.
    * @param  adArray    The byte array that is a placeholder for the
    *                    attribute type and set of options.
    * @param  attribute  The attribute to be encoded.
-   *
-   * @return  An encoded representation of the provided attribute.
    */
-  private byte[] encodeAttribute(byte[] adArray, Attribute attribute)
+  private void encodeAttribute(ByteStringBuilder buffer, ByteSequence adArray,
+                               Attribute attribute)
   {
-    int totalValuesLength = 0;
-    byte[][] subArrays = new  byte[attribute.size()*2][];
-    int pos = 0;
-    for (AttributeValue v : attribute)
+    // Write the length of the adArray followed by the adArray.
+    buffer.appendBERLength(adArray.length());
+    adArray.copyTo(buffer);
+
+    // Write the number of attributes
+    buffer.appendBERLength(attribute.size());
+
+    // Write the attribute values as length / value pairs
+    for(AttributeValue v : attribute)
     {
-      byte[] vBytes = v.getValueBytes();
-      byte[] lBytes = ASN1Element.encodeLength(vBytes.length);
-
-      subArrays[pos++] = lBytes;
-      subArrays[pos++] = vBytes;
-
-      totalValuesLength += lBytes.length + vBytes.length;
+      buffer.appendBERLength(v.getValue().length());
+      buffer.append(v.getValue());
     }
-
-    byte[] adArrayLength = ASN1Element.encodeLength(adArray.length);
-    byte[] countBytes = ASN1Element.encodeLength(attribute.size());
-    int totalLength = adArrayLength.length + adArray.length +
-                      countBytes.length + totalValuesLength;
-    byte[] array = new byte[totalLength];
-
-    System.arraycopy(adArrayLength, 0, array, 0,
-                     adArrayLength.length);
-    pos = adArrayLength.length;
-    System.arraycopy(adArray, 0, array, pos, adArray.length);
-    pos += adArray.length;
-    System.arraycopy(countBytes, 0, array, pos, countBytes.length);
-    pos += countBytes.length;
-
-    for (int i=0; i < subArrays.length; i++)
-    {
-      System.arraycopy(subArrays[i], 0, array, pos,
-                       subArrays[i].length);
-      pos += subArrays[i].length;
-    }
-
-    return array;
   }
 
 
@@ -568,75 +515,43 @@
    * {@inheritDoc}
    */
   @Override()
-  public Attribute decodeAttribute(byte[] encodedEntry, int startPos,
-                                   int length)
+  public Attribute decodeAttribute(ByteSequenceReader entryBufferReader)
          throws DirectoryException
   {
     // 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++])
-    {
-      int numLengthBytes = adArrayLength;
-      adArrayLength = 0;
-      for (int i=0; i < numLengthBytes; i++, pos++)
-      {
-        adArrayLength = (adArrayLength << 8) | (encodedEntry[pos] & 0xFF);
-      }
-    }
+    int adArrayLength = entryBufferReader.getBERLength();
 
 
     // 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);
-    pos += adArrayLength;
+    ByteSequence adArray = entryBufferReader.getByteSequence(adArrayLength);
 
     AttributeType attrType = atDecodeMap.get(adArray);
     Set<String> options = aoDecodeMap.get(adArray);
     if ((attrType == null) || (options == null))
     {
-      Message message = ERR_COMPRESSEDSCHEMA_UNRECOGNIZED_AD_TOKEN.get(
-                             bytesToHex(adArray.array()));
+      Message message = ERR_COMPRESSEDSCHEMA_UNRECOGNIZED_AD_TOKEN.get(adArray
+          .toByteString().toHex());
       throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
-                                   message);
+          message);
     }
 
 
     // Determine the number of values for the attribute.
-    int numValues = encodedEntry[pos] & 0x7F;
-    if (numValues != encodedEntry[pos++])
-    {
-      int numValuesBytes = numValues;
-      numValues = 0;
-      for (int i=0; i < numValuesBytes; i++, pos++)
-      {
-        numValues = (numValues << 8) | (encodedEntry[pos] & 0xFF);
-      }
-    }
+    int numValues = entryBufferReader.getBERLength();
 
 
     // For the common case of a single value with no options, generate
     // less garbage.
     if (numValues == 1 && options.isEmpty())
     {
-      int valueLength = encodedEntry[pos] & 0x7F;
-      if (valueLength != encodedEntry[pos++])
-      {
-        int valueLengthBytes = valueLength;
-        valueLength = 0;
-        for (int j = 0; j < valueLengthBytes; j++, pos++)
-        {
-          valueLength = (valueLength << 8) | (encodedEntry[pos] & 0xFF);
-        }
-      }
+      int valueLength = entryBufferReader.getBERLength();
 
-      byte[] valueBytes = new byte[valueLength];
-      System.arraycopy(encodedEntry, pos, valueBytes, 0, valueLength);
-
-      return Attributes.create(attrType, new AttributeValue(attrType,
-          new ASN1OctetString(valueBytes)));
+      ByteString valueBytes =
+          entryBufferReader.getByteSequence(valueLength).toByteString();
+      return Attributes.create(attrType,
+          AttributeValues.create(attrType,valueBytes));
     }
     else
     {
@@ -646,22 +561,12 @@
       builder.setInitialCapacity(numValues);
       for (int i = 0; i < numValues; i++)
       {
-        int valueLength = encodedEntry[pos] & 0x7F;
-        if (valueLength != encodedEntry[pos++])
-        {
-          int valueLengthBytes = valueLength;
-          valueLength = 0;
-          for (int j = 0; j < valueLengthBytes; j++, pos++)
-          {
-            valueLength = (valueLength << 8) | (encodedEntry[pos] & 0xFF);
-          }
-        }
+        int valueLength = entryBufferReader.getBERLength();
 
-        byte[] valueBytes = new byte[valueLength];
-        System.arraycopy(encodedEntry, pos, valueBytes, 0, valueLength);
-        pos += valueLength;
-        builder.add(new AttributeValue(attrType,
-            new ASN1OctetString(valueBytes)));
+        ByteString valueBytes =
+            entryBufferReader.getByteSequence(valueLength).toByteString();
+        builder.add(AttributeValues.create(attrType,
+            valueBytes));
       }
 
       return builder.toAttribute();

--
Gitblit v1.10.0