From 88cfe5045d77d433ce02b0ef10ee84c9d4fb15e2 Mon Sep 17 00:00:00 2001
From: Jean-Noel Rouvignac <jean-noel.rouvignac@forgerock.com>
Date: Fri, 23 May 2014 15:17:15 +0000
Subject: [PATCH] (CR-3599) Convert all protocols message to use ByteArrayBuilder + ByteArrayScanner

---
 opends/src/server/org/opends/server/replication/protocol/ReplServerStartMsg.java |  344 +++++++++-----------------------------------------------
 1 files changed, 58 insertions(+), 286 deletions(-)

diff --git a/opends/src/server/org/opends/server/replication/protocol/ReplServerStartMsg.java b/opends/src/server/org/opends/server/replication/protocol/ReplServerStartMsg.java
index 5938813..5a58fd6 100644
--- a/opends/src/server/org/opends/server/replication/protocol/ReplServerStartMsg.java
+++ b/opends/src/server/org/opends/server/replication/protocol/ReplServerStartMsg.java
@@ -22,16 +22,14 @@
  *
  *
  *      Copyright 2006-2009 Sun Microsystems, Inc.
- *      Portions copyright 2013 ForgeRock AS.
+ *      Portions copyright 2013-2014 ForgeRock AS.
  */
 package org.opends.server.replication.protocol;
 
-import java.io.UnsupportedEncodingException;
 import java.util.zip.DataFormatException;
 
 import org.opends.server.replication.common.ServerState;
 import org.opends.server.types.DN;
-import org.opends.server.types.DirectoryException;
 
 /**
  * Message sent by a replication server to another replication server
@@ -39,17 +37,17 @@
  */
 public class ReplServerStartMsg extends StartMsg
 {
-  private Integer serverId;
-  private String serverURL;
-  private DN baseDN;
-  private int windowSize;
-  private ServerState serverState;
+  private final int serverId;
+  private final String serverURL;
+  private final DN baseDN;
+  private final int windowSize;
+  private final ServerState serverState;
 
   /**
    * Whether to continue using SSL to encrypt messages after the start
    * messages have been exchanged.
    */
-  private boolean sslEncryption;
+  private final boolean sslEncryption;
 
   /**
    * NOTE: Starting from protocol V4, we introduce a dedicated PDU for answering
@@ -106,166 +104,28 @@
    * @throws DataFormatException If the in does not contain a properly
    *                             encoded ReplServerStartMsg.
    */
-  public ReplServerStartMsg(byte[] in) throws DataFormatException
+  ReplServerStartMsg(byte[] in) throws DataFormatException
   {
-    byte[] allowedPduTypes = new byte[2];
-    allowedPduTypes[0] = MSG_TYPE_REPL_SERVER_START;
-    allowedPduTypes[1] = MSG_TYPE_REPL_SERVER_START_V1;
-    headerLength = decodeHeader(allowedPduTypes, in);
+    final ByteArrayScanner scanner = new ByteArrayScanner(in);
+    decodeHeader(scanner,
+        MSG_TYPE_REPL_SERVER_START, MSG_TYPE_REPL_SERVER_START_V1);
 
-    // Protocol version has been read as part of the header:
-    // decode the body according to the protocol version read in the header
-    switch(protocolVersion)
+    /* The ReplServerStartMsg payload is stored in the form :
+     * <baseDN><serverId><serverURL><windowSize><sslEncryption>
+     * <degradedStatusThreshold><serverState>
+     */
+    baseDN = scanner.nextDN();
+    serverId = scanner.nextIntUTF8();
+    serverURL = scanner.nextString();
+    windowSize = scanner.nextIntUTF8();
+    sslEncryption = Boolean.valueOf(scanner.nextString());
+
+    if (protocolVersion > ProtocolVersion.REPLICATION_PROTOCOL_V1)
     {
-      case ProtocolVersion.REPLICATION_PROTOCOL_V1:
-        decodeBody_V1(in, headerLength);
-        return;
+      degradedStatusThreshold = scanner.nextIntUTF8();
     }
 
-    try
-    {
-      /* The ReplServerStartMsg payload is stored in the form :
-       * <baseDN><serverId><serverURL><windowSize><sslEncryption>
-       * <degradedStatusThreshold><serverState>
-       */
-
-      /* first bytes are the header */
-      int pos = headerLength;
-
-      /* read the dn
-       * first calculate the length then construct the string
-       */
-      int length = getNextLength(in, pos);
-      baseDN = DN.decode(new String(in, pos, length, "UTF-8"));
-      pos += length +1;
-
-      /*
-       * read the ServerId
-       */
-      length = getNextLength(in, pos);
-      String serverIdString = new String(in, pos, length, "UTF-8");
-      serverId = Integer.valueOf(serverIdString);
-      pos += length +1;
-
-      /*
-       * read the ServerURL
-       */
-      length = getNextLength(in, pos);
-      serverURL = new String(in, pos, length, "UTF-8");
-      pos += length +1;
-
-      /*
-       * read the window size
-       */
-      length = getNextLength(in, pos);
-      windowSize = Integer.valueOf(new String(in, pos, length, "UTF-8"));
-      pos += length +1;
-
-      /*
-       * read the sslEncryption setting
-       */
-      length = getNextLength(in, pos);
-      sslEncryption = Boolean.valueOf(new String(in, pos, length, "UTF-8"));
-      pos += length +1;
-
-      /**
-       * read the degraded status threshold
-       */
-      length = getNextLength(in, pos);
-      degradedStatusThreshold =
-        Integer.valueOf(new String(in, pos, length, "UTF-8"));
-      pos += length + 1;
-
-      // Read the ServerState
-      // Caution: ServerState MUST be the last field. Because ServerState can
-      // contain null character (string termination of serverid string ..) it
-      // cannot be decoded using getNextLength() like the other fields. The
-      // only way is to rely on the end of the input buffer : and that forces
-      // the ServerState to be the last. This should be changed and we want to
-      // have more than one ServerState field.
-      serverState = new ServerState(in, pos, in.length - 1);
-    }
-    catch (UnsupportedEncodingException e)
-    {
-      throw new DataFormatException("UTF-8 is not supported by this jvm.");
-    }
-    catch (DirectoryException e)
-    {
-      throw new DataFormatException(e.getLocalizedMessage());
-    }
-  }
-
-  /**
-   * Decodes the body of a just received ReplServerStartMsg. The body is in the
-   * passed array, and starts at the provided location. This is for a PDU
-   * encoded in V1 protocol version.
-   * @param in A byte array containing the body for the ReplServerStartMsg
-   * @param pos The position in the array where the decoding should start
-   * @throws DataFormatException If the in does not contain a properly
-   *                             encoded ReplServerStartMsg.
-   */
-  public void decodeBody_V1(byte[] in, int pos) throws DataFormatException
-  {
-    try
-    {
-      /* The ReplServerStartMsg payload is stored in the form :
-       * <baseDN><serverId><serverURL><windowSize><sslEncryption>
-       * <serverState>
-       */
-
-      /* read the dn
-       * first calculate the length then construct the string
-       */
-      int length = getNextLength(in, pos);
-      baseDN = DN.decode(new String(in, pos, length, "UTF-8"));
-      pos += length +1;
-
-      /*
-       * read the ServerId
-       */
-      length = getNextLength(in, pos);
-      String serverIdString = new String(in, pos, length, "UTF-8");
-      serverId = Integer.valueOf(serverIdString);
-      pos += length +1;
-
-      /*
-       * read the ServerURL
-       */
-      length = getNextLength(in, pos);
-      serverURL = new String(in, pos, length, "UTF-8");
-      pos += length +1;
-
-      /*
-       * read the window size
-       */
-      length = getNextLength(in, pos);
-      windowSize = Integer.valueOf(new String(in, pos, length, "UTF-8"));
-      pos += length +1;
-
-      /*
-       * read the sslEncryption setting
-       */
-      length = getNextLength(in, pos);
-      sslEncryption = Boolean.valueOf(new String(in, pos, length, "UTF-8"));
-      pos += length +1;
-
-      // Read the ServerState
-      // Caution: ServerState MUST be the last field. Because ServerState can
-      // contain null character (string termination of serverid string ..) it
-      // cannot be decoded using getNextLength() like the other fields. The
-      // only way is to rely on the end of the input buffer : and that forces
-      // the ServerState to be the last. This should be changed and we want to
-      // have more than one ServerState field.
-      serverState = new ServerState(in, pos, in.length - 1);
-    }
-    catch (UnsupportedEncodingException e)
-    {
-      throw new DataFormatException("UTF-8 is not supported by this jvm.");
-    }
-    catch (DirectoryException e)
-    {
-      throw new DataFormatException(e.getLocalizedMessage());
-    }
+    serverState = scanner.nextServerState();
   }
 
   /**
@@ -305,69 +165,43 @@
     return this.serverState;
   }
 
-  /**
-   * {@inheritDoc}
-   */
+  /** {@inheritDoc} */
   @Override
-  public byte[] getBytes(short sessionProtocolVersion)
-     throws UnsupportedEncodingException
+  public byte[] getBytes(short protocolVersion)
   {
-    // If an older version requested, encode in the requested way
-    switch(sessionProtocolVersion)
+    final ByteArrayBuilder builder = new ByteArrayBuilder();
+    if (protocolVersion == ProtocolVersion.REPLICATION_PROTOCOL_V1)
     {
-      case ProtocolVersion.REPLICATION_PROTOCOL_V1:
-        return getBytes_V1();
+      /*
+       * The ReplServerStartMessage is stored in the form :
+       * <operation type><basedn><serverid><serverURL><windowsize><serverState>
+       */
+      encodeHeader_V1(MSG_TYPE_REPL_SERVER_START_V1, builder);
+      builder.append(baseDN);
+      builder.appendUTF8(serverId);
+      builder.append(serverURL);
+      builder.appendUTF8(windowSize);
+      builder.append(Boolean.toString(sslEncryption));
+      // Caution: ServerState MUST be the last field.
+      builder.append(serverState);
     }
-
-    /* The ReplServerStartMsg is stored in the form :
-     * <operation type><baseDN><serverId><serverURL><windowSize><sslEncryption>
-     * <degradedStatusThreshold><serverState>
-     */
-
-    byte[] byteDn = baseDN.toNormalizedString().getBytes("UTF-8");
-    byte[] byteServerId = String.valueOf(serverId).getBytes("UTF-8");
-    byte[] byteServerUrl = serverURL.getBytes("UTF-8");
-    byte[] byteServerState = serverState.getBytes();
-    byte[] byteWindowSize = String.valueOf(windowSize).getBytes("UTF-8");
-    byte[] byteSSLEncryption =
-      String.valueOf(sslEncryption).getBytes("UTF-8");
-    byte[] byteDegradedStatusThreshold =
-      String.valueOf(degradedStatusThreshold).getBytes("UTF-8");
-
-    int length = byteDn.length + 1 + byteServerId.length + 1 +
-      byteServerUrl.length + 1 + byteWindowSize.length + 1 +
-      byteSSLEncryption.length + 1 +
-      byteDegradedStatusThreshold.length + 1 +
-      byteServerState.length + 1;
-
-    /* encode the header in a byte[] large enough */
-    byte resultByteArray[] = encodeHeader(MSG_TYPE_REPL_SERVER_START, length,
-        sessionProtocolVersion);
-
-    int pos = headerLength;
-
-    /* put the baseDN and a terminating 0 */
-    pos = addByteArray(byteDn, resultByteArray, pos);
-
-    /* put the ServerId */
-    pos = addByteArray(byteServerId, resultByteArray, pos);
-
-    /* put the ServerURL */
-    pos = addByteArray(byteServerUrl, resultByteArray, pos);
-
-    /* put the window size */
-    pos = addByteArray(byteWindowSize, resultByteArray, pos);
-
-    /* put the SSL Encryption setting */
-    pos = addByteArray(byteSSLEncryption, resultByteArray, pos);
-
-    /* put the degraded status threshold */
-    pos = addByteArray(byteDegradedStatusThreshold, resultByteArray, pos);
-
-    /* put the ServerState */
-    pos = addByteArray(byteServerState, resultByteArray, pos);
-
-    return resultByteArray;
+    else
+    {
+      /* The ReplServerStartMsg is stored in the form :
+       * <operation type><baseDN><serverId><serverURL><windowSize><sslEncryption>
+       * <degradedStatusThreshold><serverState>
+       */
+      encodeHeader(MSG_TYPE_REPL_SERVER_START, builder, protocolVersion);
+      builder.append(baseDN);
+      builder.appendUTF8(serverId);
+      builder.append(serverURL);
+      builder.appendUTF8(windowSize);
+      builder.append(Boolean.toString(sslEncryption));
+      builder.appendUTF8(degradedStatusThreshold);
+      // Caution: ServerState MUST be the last field.
+      builder.append(serverState);
+    }
+    return builder.toByteArray();
   }
 
   /**
@@ -410,9 +244,7 @@
     this.degradedStatusThreshold = degradedStatusThreshold;
   }
 
-  /**
-   * {@inheritDoc}
-   */
+  /** {@inheritDoc} */
   @Override
   public String toString()
   {
@@ -428,64 +260,4 @@
       "\ndegradedStatusThreshold: " + degradedStatusThreshold +
       "\nwindowSize: " + windowSize;
   }
-
-  /**
-   * Get the byte array representation of this Message. This uses the version
-   * 1 of the replication protocol (used for compatibility purpose).
-   *
-   * @return The byte array representation of this Message.
-   *
-   * @throws UnsupportedEncodingException  When the encoding of the message
-   *         failed because the UTF-8 encoding is not supported.
-   */
-  public byte[] getBytes_V1() throws UnsupportedEncodingException
-  {
-    /*
-     * The ReplServerStartMessage is stored in the form :
-     * <operation type><basedn><serverid><serverURL><windowsize><serverState>
-     */
-    try {
-      byte[] byteDn = baseDN.toNormalizedString().getBytes("UTF-8");
-      byte[] byteServerId = String.valueOf(serverId).getBytes("UTF-8");
-      byte[] byteServerUrl = serverURL.getBytes("UTF-8");
-      byte[] byteServerState = serverState.getBytes();
-      byte[] byteWindowSize = String.valueOf(windowSize).getBytes("UTF-8");
-      byte[] byteSSLEncryption =
-                     String.valueOf(sslEncryption).getBytes("UTF-8");
-
-      int length = byteDn.length + 1 + byteServerId.length + 1 +
-                   byteServerUrl.length + 1 + byteWindowSize.length + 1 +
-                   byteSSLEncryption.length + 1 +
-                   byteServerState.length + 1;
-
-      /* encode the header in a byte[] large enough */
-      byte resultByteArray[] = encodeHeader_V1(MSG_TYPE_REPL_SERVER_START_V1,
-        length);
-      int pos = headerLength;
-
-      /* put the baseDN and a terminating 0 */
-      pos = addByteArray(byteDn, resultByteArray, pos);
-
-      /* put the ServerId */
-      pos = addByteArray(byteServerId, resultByteArray, pos);
-
-      /* put the ServerURL */
-      pos = addByteArray(byteServerUrl, resultByteArray, pos);
-
-      /* put the window size */
-      pos = addByteArray(byteWindowSize, resultByteArray, pos);
-
-      /* put the SSL Encryption setting */
-      pos = addByteArray(byteSSLEncryption, resultByteArray, pos);
-
-      /* put the ServerState */
-      pos = addByteArray(byteServerState, resultByteArray, pos);
-
-      return resultByteArray;
-    }
-    catch (UnsupportedEncodingException e)
-    {
-      return null;
-    }
-  }
 }

--
Gitblit v1.10.0