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 }