From 691d99dba67f7f5a89135e3c129b006b3c956b1e Mon Sep 17 00:00:00 2001
From: pgamba <pgamba@localhost>
Date: Tue, 06 Oct 2009 12:34:32 +0000
Subject: [PATCH] Entry attributes for ECL - Protocol V4

---
 opendj-sdk/opends/src/server/org/opends/server/replication/protocol/AddMsg.java |  486 ++++++++++++++++++++++++++++++++++-------------------
 1 files changed, 310 insertions(+), 176 deletions(-)

diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/protocol/AddMsg.java b/opendj-sdk/opends/src/server/org/opends/server/replication/protocol/AddMsg.java
index eb9384e..83defc1 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/replication/protocol/AddMsg.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/protocol/AddMsg.java
@@ -41,7 +41,6 @@
 import org.opends.server.protocols.asn1.ASN1Writer;
 import org.opends.server.protocols.asn1.ASN1;
 import org.opends.server.protocols.asn1.ASN1Exception;
-import org.opends.server.protocols.asn1.ASN1Reader;
 import org.opends.server.replication.common.ChangeNumber;
 import org.opends.server.types.*;
 import org.opends.server.types.operation.PostOperationAddOperation;
@@ -55,7 +54,10 @@
  */
 public class AddMsg extends LDAPUpdateMsg
 {
+  // Attributes are managed encoded
   private byte[] encodedAttributes;
+
+  // Parent is managed decoded
   private String parentUniqueId;
 
   /**
@@ -68,12 +70,248 @@
           op.getRawEntryDN().toString());
 
     AddContext ctx = (AddContext) op.getAttachment(SYNCHROCONTEXT);
+
+    // Stores parentUniqueID not encoded
     this.parentUniqueId = ctx.getParentUid();
 
-    this.encodedAttributes =
-      encodeAttributes(op.getObjectClasses(),
-          op.getUserAttributes(),
-          op.getOperationalAttributes());
+    // Stores attributes encoded
+    this.encodedAttributes = encodeAttributes(op.getObjectClasses(),
+        op.getUserAttributes(), op.getOperationalAttributes());
+  }
+
+  /**
+   * Creates a new AddMessage.
+   *
+   * @param cn                    ChangeNumber of the add.
+   * @param dn                    DN of the added entry.
+   * @param uniqueId              The Unique identifier of the added entry.
+   * @param parentId              The unique Id of the parent of the added
+   *                              entry.
+   * @param objectClasses           objectclass of the added entry.
+   * @param userAttributes        user attributes of the added entry.
+   * @param operationalAttributes operational attributes of the added entry.
+   */
+  public AddMsg(ChangeNumber cn,
+                String dn,
+                String uniqueId,
+                String parentId,
+                Map<ObjectClass, String> objectClasses,
+                Map<AttributeType,List<Attribute>> userAttributes,
+                Map<AttributeType,List<Attribute>> operationalAttributes)
+  {
+    super (cn, uniqueId, dn);
+
+    // Stores parentUniqueID not encoded
+    this.parentUniqueId = parentId;
+
+    // Stores attributes encoded
+    this.encodedAttributes = encodeAttributes(objectClasses, userAttributes,
+        operationalAttributes);
+  }
+
+
+  /**
+   * Creates a new AddMessage.
+   *
+   * @param cn ChangeNumber of the add.
+   * @param dn DN of the added entry.
+   * @param uniqueId The Unique identifier of the added entry.
+   * @param parentId The unique Id of the parent of the added entry.
+   * @param objectClass objectclass of the added entry.
+   * @param userAttributes user attributes of the added entry.
+   * @param operationalAttributes operational attributes of the added entry.
+   */
+  public AddMsg(ChangeNumber cn,
+                String dn,
+                String uniqueId,
+                String parentId,
+                Attribute objectClass,
+                Collection<Attribute> userAttributes,
+                Collection<Attribute> operationalAttributes)
+  {
+    super (cn, uniqueId, dn);
+
+    // Stores parentUniqueID not encoded
+    this.parentUniqueId = parentId;
+
+    // Stores attributes encoded
+    this.encodedAttributes = encodeAttributes(objectClass, userAttributes,
+        operationalAttributes);
+  }
+
+  /**
+   * Creates a new Add message from a byte[].
+   *
+   * @param in The byte[] from which the operation must be read.
+   * @throws DataFormatException The input byte[] is not a valid AddMsg
+   * @throws UnsupportedEncodingException If UTF8 is not supported by the jvm
+   */
+  public AddMsg(byte[] in) throws DataFormatException,
+                                  UnsupportedEncodingException
+  {
+    byte[] allowedPduTypes = new byte[2];
+    allowedPduTypes[0] = MSG_TYPE_ADD;
+    allowedPduTypes[1] = MSG_TYPE_ADD_V1;
+    int pos = decodeHeader(allowedPduTypes, in);
+
+    // protocol version has been read as part of the header
+    if (protocolVersion <= 3)
+      decodeBody_V123(in, pos);
+    else
+    {
+      decodeBody_V4(in, pos);
+    }
+    if (protocolVersion==ProtocolVersion.getCurrentVersion())
+    {
+      bytes = in;
+    }
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public AddOperationBasis createOperation(
+      InternalClientConnection connection, String newDn)
+  throws LDAPException, ASN1Exception
+  {
+    ArrayList<RawAttribute> attr = decodeRawAttributes(encodedAttributes);
+
+    AddOperationBasis add =  new AddOperationBasis(connection,
+        InternalClientConnection.nextOperationID(),
+        InternalClientConnection.nextMessageID(), null,
+        ByteString.valueOf(newDn), attr);
+    AddContext ctx = new AddContext(getChangeNumber(), getUniqueId(),
+        parentUniqueId);
+    add.setAttachment(SYNCHROCONTEXT, ctx);
+    return add;
+  }
+
+  // ============
+  // Msg encoding
+  // ============
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public byte[] getBytes_V1() throws UnsupportedEncodingException
+  {
+    int bodyLength = encodedAttributes.length;
+    byte[] byteParentId = null;
+    if (parentUniqueId != null)
+    {
+      byteParentId = parentUniqueId.getBytes("UTF-8");
+      bodyLength += byteParentId.length + 1;
+    }
+    else
+    {
+      bodyLength += 1;
+    }
+
+    /* encode the header in a byte[] large enough to also contain the mods */
+    byte [] resultByteArray = encodeHeader_V1(MSG_TYPE_ADD_V1, bodyLength);
+
+    int pos = resultByteArray.length - bodyLength;
+
+    if (byteParentId != null)
+      pos = addByteArray(byteParentId, resultByteArray, pos);
+    else
+      resultByteArray[pos++] = 0;
+
+    /* put the attributes */
+    for (int i=0; i<encodedAttributes.length; i++,pos++)
+    {
+      resultByteArray[pos] = encodedAttributes[i];
+    }
+    return resultByteArray;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public byte[] getBytes_V23() throws UnsupportedEncodingException
+  {
+    // Put together the different encoded pieces
+    int bodyLength = encodedAttributes.length;
+
+    // Compute the total length of the body
+    byte[] byteParentId = null;
+    if (parentUniqueId != null)
+    {
+      // Encode parentID now to get the length of the encoded bytes
+      byteParentId = parentUniqueId.getBytes("UTF-8");
+      bodyLength += byteParentId.length + 1;
+    }
+    else
+    {
+      bodyLength += 1;
+    }
+
+    /* encode the header in a byte[] large enough to also contain the mods */
+    byte [] resultByteArray = encodeHeader(MSG_TYPE_ADD, bodyLength);
+
+    int pos = resultByteArray.length - bodyLength;
+
+    if (byteParentId != null)
+      pos = addByteArray(byteParentId, resultByteArray, pos);
+    else
+      resultByteArray[pos++] = 0;
+
+    /* put the attributes */
+    for (int i=0; i<encodedAttributes.length; i++,pos++)
+    {
+      resultByteArray[pos] = encodedAttributes[i];
+    }
+    return resultByteArray;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public byte[] getBytes_V4() throws UnsupportedEncodingException
+  {
+    // Put together the different encoded pieces
+    int bodyLength = 0;
+
+    // Compute the total length of the body
+    byte[] byteParentId = null;
+    if (parentUniqueId != null)
+    {
+      // Encode parentID now to get the length of the encoded bytes
+      byteParentId = parentUniqueId.getBytes("UTF-8");
+      bodyLength += byteParentId.length + 1;
+    }
+    else
+    {
+      bodyLength += 1;
+    }
+
+    byte[] byteAttrLen =
+      String.valueOf(encodedAttributes.length).getBytes("UTF-8");
+    bodyLength += byteAttrLen.length + 1;
+    bodyLength += encodedAttributes.length + 1;
+
+    byte[] byteEntryAttrLen =
+      String.valueOf(encodedEclIncludes.length).getBytes("UTF-8");
+    bodyLength += byteEntryAttrLen.length + 1;
+    bodyLength += encodedEclIncludes.length + 1;
+
+    /* encode the header in a byte[] large enough to also contain the mods */
+    byte [] encodedMsg = encodeHeader(MSG_TYPE_ADD, bodyLength);
+
+    int pos = encodedMsg.length - bodyLength;
+    if (byteParentId != null)
+      pos = addByteArray(byteParentId, encodedMsg, pos);
+    else
+      encodedMsg[pos++] = 0;
+    pos = addByteArray(byteAttrLen, encodedMsg, pos);
+    pos = addByteArray(encodedAttributes, encodedMsg, pos);
+    pos = addByteArray(byteEntryAttrLen, encodedMsg, pos);
+    pos = addByteArray(encodedEclIncludes, encodedMsg, pos);
+    return encodedMsg;
   }
 
   private byte[] encodeAttributes(
@@ -128,59 +366,13 @@
     return byteBuilder.toByteArray();
   }
 
-  /**
-   * Creates a new AddMessage.
-   *
-   * @param cn                    ChangeNumber of the add.
-   * @param dn                    DN of the added entry.
-   * @param uniqueId              The Unique identifier of the added entry.
-   * @param parentId              The unique Id of the parent of the added
-   *                              entry.
-   * @param objectClasses           objectclass of the added entry.
-   * @param userAttributes        user attributes of the added entry.
-   * @param operationalAttributes operational attributes of the added entry.
-   */
-  public AddMsg(ChangeNumber cn,
-                String dn,
-                String uniqueId,
-                String parentId,
-                Map<ObjectClass, String> objectClasses,
-                Map<AttributeType,List<Attribute>> userAttributes,
-                Map<AttributeType,List<Attribute>> operationalAttributes)
+  private byte[] encodeAttributes(
+      Attribute objectClass,
+      Collection<Attribute> userAttributes,
+      Collection<Attribute> operationalAttributes)
   {
-    super (cn, uniqueId, dn);
-    this.parentUniqueId = parentId;
-
-    encodedAttributes = encodeAttributes(objectClasses,
-                                        userAttributes, operationalAttributes);
-  }
-
-
-  /**
-   * Creates a new AddMessage.
-   *
-   * @param cn ChangeNumber of the add.
-   * @param dn DN of the added entry.
-   * @param uniqueId The Unique identifier of the added entry.
-   * @param parentId The unique Id of the parent of the added entry.
-   * @param objectClass objectclass of the added entry.
-   * @param userAttributes user attributes of the added entry.
-   * @param operationalAttributes operational attributes of the added entry.
-   */
-  public AddMsg(ChangeNumber cn,
-                String dn,
-                String uniqueId,
-                String parentId,
-                Attribute objectClass,
-                Collection<Attribute> userAttributes,
-                Collection<Attribute> operationalAttributes)
-  {
-    super (cn, uniqueId, dn);
-    this.parentUniqueId = parentId;
-
     ByteStringBuilder byteBuilder = new ByteStringBuilder();
     ASN1Writer writer = ASN1.getWriter(byteBuilder);
-
     try
     {
       new LDAPAttribute(objectClass).write(writer);
@@ -196,25 +388,16 @@
     {
       // Do something
     }
-
-    encodedAttributes = byteBuilder.toByteArray();
+    return byteBuilder.toByteArray();
   }
 
-  /**
-   * Creates a new Add message from a byte[].
-   *
-   * @param in The byte[] from which the operation must be read.
-   * @throws DataFormatException The input byte[] is not a valid AddMsg
-   * @throws UnsupportedEncodingException If UTF8 is not supported by the jvm
-   */
-  public AddMsg(byte[] in) throws DataFormatException,
-                                  UnsupportedEncodingException
-  {
-    byte[] allowedPduTypes = new byte[2];
-    allowedPduTypes[0] = MSG_TYPE_ADD;
-    allowedPduTypes[1] = MSG_TYPE_ADD_V1;
-    int pos = decodeHeader(allowedPduTypes, in);
+  // ============
+  // Msg decoding
+  // ============
 
+  private void decodeBody_V123(byte[] in, int pos)
+  throws DataFormatException, UnsupportedEncodingException
+  {
     // read the parent unique Id
     int length = getNextLength(in, pos);
     if (length != 0)
@@ -228,7 +411,7 @@
       pos += 1;
     }
 
-    // Read the attributes : all the remaining bytes
+    // Read/Don't decode attributes : all the remaining bytes
     encodedAttributes = new byte[in.length-pos];
     int i =0;
     while (pos<in.length)
@@ -237,72 +420,63 @@
     }
   }
 
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  public AddOperationBasis createOperation(
-         InternalClientConnection connection, String newDn)
-         throws LDAPException, ASN1Exception
+  private void decodeBody_V4(byte[] in, int pos)
+  throws DataFormatException, UnsupportedEncodingException
   {
-    ASN1Reader asn1Reader = ASN1.getReader(encodedAttributes);
-    ArrayList<RawAttribute> attr = new ArrayList<RawAttribute>();
-
-    while(asn1Reader.hasNextElement())
+    // read the parent unique Id
+    int length = getNextLength(in, pos);
+    if (length != 0)
     {
-      attr.add(LDAPAttribute.decode(asn1Reader));
-    }
-
-    AddOperationBasis add =  new AddOperationBasis(connection,
-                            InternalClientConnection.nextOperationID(),
-                            InternalClientConnection.nextMessageID(), null,
-        ByteString.valueOf(newDn), attr);
-    AddContext ctx = new AddContext(getChangeNumber(), getUniqueId(),
-                                    parentUniqueId);
-    add.setAttachment(SYNCHROCONTEXT, ctx);
-    return add;
-  }
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  public byte[] getBytes() throws UnsupportedEncodingException
-  {
-    if (bytes == null)
-    {
-      int length = encodedAttributes.length;
-      byte[] byteParentId = null;
-      if (parentUniqueId != null)
-      {
-        byteParentId = parentUniqueId.getBytes("UTF-8");
-        length += byteParentId.length + 1;
-      }
-      else
-      {
-        length += 1;
-      }
-
-      /* encode the header in a byte[] large enough to also contain the mods */
-      byte [] resultByteArray = encodeHeader(MSG_TYPE_ADD, length);
-
-      int pos = resultByteArray.length - length;
-
-      if (byteParentId != null)
-        pos = addByteArray(byteParentId, resultByteArray, pos);
-      else
-        resultByteArray[pos++] = 0;
-
-      /* put the attributes */
-      for (int i=0; i<encodedAttributes.length; i++,pos++)
-      {
-        resultByteArray[pos] = encodedAttributes[i];
-      }
-      return resultByteArray;
+      parentUniqueId = new String(in, pos, length, "UTF-8");
+      pos += length + 1;
     }
     else
     {
-      return bytes;
+      parentUniqueId = null;
+      pos += 1;
+    }
+
+    // Read attr len
+    length = getNextLength(in, pos);
+    int attrLen = Integer.valueOf(new String(in, pos, length,"UTF-8"));
+    pos += length + 1;
+
+    // Read/Don't decode attributes
+    this.encodedAttributes = new byte[attrLen];
+    try
+    {
+      System.arraycopy(in, pos, encodedAttributes, 0, attrLen);
+    } catch (IndexOutOfBoundsException e)
+    {
+      throw new DataFormatException(e.getMessage());
+    } catch (ArrayStoreException e)
+    {
+      throw new DataFormatException(e.getMessage());
+    } catch (NullPointerException e)
+    {
+      throw new DataFormatException(e.getMessage());
+    }
+    pos += attrLen + 1;
+
+    // Read ecl attr len
+    length = getNextLength(in, pos);
+    int eclAttrLen = Integer.valueOf(new String(in, pos, length,"UTF-8"));
+    pos += length + 1;
+
+    // Read/Don't decode entry attributes
+    encodedEclIncludes = new byte[eclAttrLen];
+    try
+    {
+      System.arraycopy(in, pos, encodedEclIncludes, 0, eclAttrLen);
+    } catch (IndexOutOfBoundsException e)
+    {
+      throw new DataFormatException(e.getMessage());
+    } catch (ArrayStoreException e)
+    {
+      throw new DataFormatException(e.getMessage());
+    } catch (NullPointerException e)
+    {
+      throw new DataFormatException(e.getMessage());
     }
   }
 
@@ -371,13 +545,7 @@
    */
   public List<Attribute> getAttributes() throws LDAPException, ASN1Exception
   {
-    List<Attribute> attrs = new ArrayList<Attribute>();
-
-    ASN1Reader reader = ASN1.getReader(encodedAttributes);
-
-    while (reader.hasNextElement())
-      attrs.add(LDAPAttribute.decode(reader).toAttribute());
-
+    List<Attribute> attrs = decodeAttributes(encodedAttributes);
     return attrs;
   }
 
@@ -406,42 +574,8 @@
   @Override
   public int size()
   {
-    return encodedAttributes.length + 40;
+    return encodedAttributes.length + + encodedEclIncludes.length
+      + headerSize();
   }
 
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  public byte[] getBytes_V1() throws UnsupportedEncodingException
-  {
-    int length = encodedAttributes.length;
-    byte[] byteParentId = null;
-    if (parentUniqueId != null)
-    {
-      byteParentId = parentUniqueId.getBytes("UTF-8");
-      length += byteParentId.length + 1;
-    }
-    else
-    {
-      length += 1;
-    }
-
-    /* encode the header in a byte[] large enough to also contain the mods */
-    byte [] resultByteArray = encodeHeader_V1(MSG_TYPE_ADD_V1, length);
-
-    int pos = resultByteArray.length - length;
-
-    if (byteParentId != null)
-      pos = addByteArray(byteParentId, resultByteArray, pos);
-    else
-      resultByteArray[pos++] = 0;
-
-    /* put the attributes */
-    for (int i=0; i<encodedAttributes.length; i++,pos++)
-    {
-      resultByteArray[pos] = encodedAttributes[i];
-    }
-    return resultByteArray;
-  }
 }

--
Gitblit v1.10.0