001    /*
002     * CDDL HEADER START
003     *
004     * The contents of this file are subject to the terms of the
005     * Common Development and Distribution License, Version 1.0 only
006     * (the "License").  You may not use this file except in compliance
007     * with the License.
008     *
009     * You can obtain a copy of the license at
010     * trunk/opends/resource/legal-notices/OpenDS.LICENSE
011     * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
012     * See the License for the specific language governing permissions
013     * and limitations under the License.
014     *
015     * When distributing Covered Code, include this CDDL HEADER in each
016     * file and include the License file at
017     * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
018     * add the following below this CDDL HEADER, with the fields enclosed
019     * by brackets "[]" replaced with your own identifying information:
020     *      Portions Copyright [yyyy] [name of copyright owner]
021     *
022     * CDDL HEADER END
023     *
024     *
025     *      Copyright 2006-2008 Sun Microsystems, Inc.
026     */
027    package org.opends.server.replication.protocol;
028    
029    import java.io.UnsupportedEncodingException;
030    import java.util.zip.DataFormatException;
031    
032    
033    /**
034     * This abstract message class is the superclass for start messages used
035     * by LDAP servers and Replication servers to initiate their communications.
036     * This class specifies a message header that contains the Replication
037     * Protocol version.
038     */
039    public abstract class StartMessage extends ReplicationMessage
040    {
041      private short protocolVersion;
042      private long  generationId;
043    
044      /**
045       * The length of the header of this message.
046       */
047      protected int headerLength;
048    
049      /**
050       * Create a new StartMessage.
051       *
052       * @param protocolVersion The Replication Protocol version of the server
053       *                        for which the StartMessage is created.
054       * @param generationId    The generationId for this server.
055       *
056       */
057      public StartMessage(short protocolVersion, long generationId)
058      {
059        this.protocolVersion = protocolVersion;
060        this.generationId = generationId;
061      }
062    
063      /**
064       * Creates a new ServerStartMessage from its encoded form.
065       *
066       * @param type The type of the message to create.
067       * @param encodedMsg The byte array containing the encoded form of the
068       *           StartMessage.
069       * @throws DataFormatException If the byte array does not contain a valid
070       *                             encoded form of the ServerStartMessage.
071       */
072      public StartMessage(byte type, byte [] encodedMsg) throws DataFormatException
073      {
074        headerLength = decodeHeader(type, encodedMsg);
075      }
076    
077      /**
078       * Encode the header for the start message.
079       *
080       * @param type The type of the message to create.
081       * @param additionalLength additional length needed to encode the remaining
082       *                         part of the UpdateMessage.
083       * @return a byte array containing the common header and enough space to
084       *         encode the reamining bytes of the UpdateMessage as was specified
085       *         by the additionalLength.
086       *         (byte array length = common header length + additionalLength)
087       * @throws UnsupportedEncodingException if UTF-8 is not supported.
088       */
089      public byte[] encodeHeader(byte type, int additionalLength)
090      throws UnsupportedEncodingException
091      {
092        byte[] versionByte = Short.toString(protocolVersion).getBytes("UTF-8");
093        byte[] byteGenerationID =
094          String.valueOf(generationId).getBytes("UTF-8");
095    
096        /* The message header is stored in the form :
097         * <message type><protocol version>
098         */
099        int length = 1 + versionByte.length + 1 +
100                         byteGenerationID.length + 1 +
101                         additionalLength;
102    
103        byte[] encodedMsg = new byte[length];
104    
105        /* put the type of the operation */
106        encodedMsg[0] = type;
107        int pos = 1;
108    
109        /* put the protocol version */
110        pos = addByteArray(versionByte, encodedMsg, pos);
111    
112        /* put the generationId */
113        headerLength = addByteArray(byteGenerationID, encodedMsg, pos);
114    
115        return encodedMsg;
116      }
117    
118      /**
119       * Decode the Header part of this message, and check its type.
120       *
121       * @param type The type of this message.
122       * @param encodedMsg the encoded form of the message.
123       * @return the position at which the remaining part of the message starts.
124       * @throws DataFormatException if the encodedMsg does not contain a valid
125       *         common header.
126       */
127      public int decodeHeader(byte type, byte [] encodedMsg)
128      throws DataFormatException
129      {
130        /* first byte is the type */
131        if (encodedMsg[0] != type)
132          throw new DataFormatException("byte[] is not a valid msg");
133    
134        try
135        {
136          /* then read the version */
137          int pos = 1;
138          int length = getNextLength(encodedMsg, pos);
139          protocolVersion = Short.valueOf(
140              new String(encodedMsg, pos, length, "UTF-8"));
141          pos += length + 1;
142    
143          /* read the generationId */
144          length = getNextLength(encodedMsg, pos);
145          generationId = Long.valueOf(new String(encodedMsg, pos, length,
146              "UTF-8"));
147          pos += length +1;
148    
149    
150          return pos;
151        } catch (UnsupportedEncodingException e)
152        {
153          throw new DataFormatException("UTF-8 is not supported by this jvm.");
154        }
155    
156      }
157    
158      /**
159       * Get the version included in the Start Message mean the replication
160       * protocol version used by the server that created the message.
161       *
162       * @return The version used by the server that created the message.
163       */
164      public short getVersion()
165      {
166        return protocolVersion;
167      }
168    
169      /**
170       * Get the generationId from this message.
171       * @return The generationId.
172       */
173      public long getGenerationId()
174      {
175        return generationId;
176      }
177    
178    }