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 * Abstract class that must be used when defining messages that can
034 * be sent for replication purpose between servers.
035 *
036 * When extending this class one should also create a new MSG_TYPE
037 * and should update the generateMsg() method.
038 */
039 public abstract class ReplicationMessage
040 {
041 static final byte MSG_TYPE_MODIFY_REQUEST = 1;
042 static final byte MSG_TYPE_ADD_REQUEST = 2;
043 static final byte MSG_TYPE_DELETE_REQUEST = 3;
044 static final byte MSG_TYPE_MODIFYDN_REQUEST = 4;
045 static final byte MSG_TYPE_ACK = 5;
046 static final byte MSG_TYPE_SERVER_START = 6;
047 static final byte MSG_TYPE_REPL_SERVER_START = 7;
048 static final byte MSG_TYPE_WINDOW = 8;
049 static final byte MSG_TYPE_HEARTBEAT = 9;
050 static final byte MSG_TYPE_INITIALIZE_REQUEST = 10;
051 static final byte MSG_TYPE_INITIALIZE_TARGET = 11;
052 static final byte MSG_TYPE_ENTRY = 12;
053 static final byte MSG_TYPE_DONE = 13;
054 static final byte MSG_TYPE_ERROR = 14;
055 static final byte MSG_TYPE_WINDOW_PROBE = 15;
056 static final byte MSG_TYPE_REPL_SERVER_INFO = 16;
057 static final byte MSG_TYPE_RESET_GENERATION_ID = 17;
058 static final byte MSG_TYPE_REPL_SERVER_MONITOR_REQUEST = 18;
059 static final byte MSG_TYPE_REPL_SERVER_MONITOR = 19;
060
061 // Adding a new type of message here probably requires to
062 // change accordingly generateMsg method below
063
064 /**
065 * Return the byte[] representation of this message.
066 * Depending on the message type, the first byte of the byte[] must be.
067 * MSG_TYPE_MODIFY_REQUEST
068 * MSG_TYPE_ADD_REQUEST
069 * MSG_TYPE_DELETE_REQUEST
070 * MSG_TYPE_MODIFY_DN_REQUEST
071 * MSG_TYPE_ACK
072 * MSG_TYPE_SERVER_START
073 * MSG_TYPE_REPL_SERVER_START
074 * MSG_TYPE_WINDOW
075 * MSG_TYPE_HEARTBEAT
076 * MSG_TYPE_INITIALIZE
077 * MSG_TYPE_INITIALIZE_TARGET
078 * MSG_TYPE_ENTRY
079 * MSG_TYPE_DONE
080 * MSG_TYPE_ERROR
081 * MSG_TYPE_WINDOW_PROBE
082 * MSG_TYPE_REPL_SERVER_INFO
083 * MSG_TYPE_RESET_GENERATION_ID
084 * MSG_TYPE_REPL_SERVER_MONITOR_REQUEST
085 * MSG_TYPE_REPL_SERVER_MONITOR
086 *
087 * @return the byte[] representation of this message.
088 * @throws UnsupportedEncodingException When the encoding of the message
089 * failed because the UTF-8 encoding is not supported.
090 */
091 public abstract byte[] getBytes() throws UnsupportedEncodingException;
092
093
094 /**
095 * Generates a ReplicationMessage from its encoded form.
096 *
097 * @param buffer The encode form of the ReplicationMessage.
098 * @return the generated SycnhronizationMessage.
099 * @throws DataFormatException if the encoded form was not a valid msg.
100 * @throws UnsupportedEncodingException if UTF8 is not supported.
101 */
102 public static ReplicationMessage generateMsg(byte[] buffer)
103 throws DataFormatException, UnsupportedEncodingException
104 {
105 ReplicationMessage msg = null;
106 switch (buffer[0])
107 {
108 case MSG_TYPE_MODIFY_REQUEST:
109 msg = new ModifyMsg(buffer);
110 break;
111 case MSG_TYPE_ADD_REQUEST:
112 msg = new AddMsg(buffer);
113 break;
114 case MSG_TYPE_DELETE_REQUEST:
115 msg = new DeleteMsg(buffer);
116 break;
117 case MSG_TYPE_MODIFYDN_REQUEST:
118 msg = new ModifyDNMsg(buffer);
119 break;
120 case MSG_TYPE_ACK:
121 msg = new AckMessage(buffer);
122 break;
123 case MSG_TYPE_SERVER_START:
124 msg = new ServerStartMessage(buffer);
125 break;
126 case MSG_TYPE_REPL_SERVER_START:
127 msg = new ReplServerStartMessage(buffer);
128 break;
129 case MSG_TYPE_WINDOW:
130 msg = new WindowMessage(buffer);
131 break;
132 case MSG_TYPE_HEARTBEAT:
133 msg = new HeartbeatMessage(buffer);
134 break;
135 case MSG_TYPE_INITIALIZE_REQUEST:
136 msg = new InitializeRequestMessage(buffer);
137 break;
138 case MSG_TYPE_INITIALIZE_TARGET:
139 msg = new InitializeTargetMessage(buffer);
140 break;
141 case MSG_TYPE_ENTRY:
142 msg = new EntryMessage(buffer);
143 break;
144 case MSG_TYPE_DONE:
145 msg = new DoneMessage(buffer);
146 break;
147 case MSG_TYPE_ERROR:
148 msg = new ErrorMessage(buffer);
149 break;
150 case MSG_TYPE_RESET_GENERATION_ID:
151 msg = new ResetGenerationId(buffer);
152 break;
153 case MSG_TYPE_WINDOW_PROBE:
154 msg = new WindowProbe(buffer);
155 break;
156 case MSG_TYPE_REPL_SERVER_INFO:
157 msg = new ReplServerInfoMessage(buffer);
158 break;
159 case MSG_TYPE_REPL_SERVER_MONITOR_REQUEST:
160 msg = new MonitorRequestMessage(buffer);
161 break;
162 case MSG_TYPE_REPL_SERVER_MONITOR:
163 msg = new MonitorMessage(buffer);
164 break;
165 default:
166 throw new DataFormatException("received message with unknown type");
167 }
168 return msg;
169 }
170
171 /**
172 * Concatenate the tail byte array into the resultByteArray.
173 * The resultByteArray must be large enough before calling this method.
174 *
175 * @param tail the byte array to concatenate.
176 * @param resultByteArray The byte array to concatenate to.
177 * @param pos the position where to concatenate.
178 * @return the next position to use in the resultByteArray.
179 */
180 protected int addByteArray(byte[] tail, byte[] resultByteArray, int pos)
181 {
182 for (int i=0; i<tail.length; i++,pos++)
183 {
184 resultByteArray[pos] = tail[i];
185 }
186 resultByteArray[pos++] = 0;
187 return pos;
188 }
189
190 /**
191 * Get the length of the next String encoded in the in byte array.
192 *
193 * @param in the byte array where to calculate the string.
194 * @param pos the position whre to start from in the byte array.
195 * @return the length of the next string.
196 * @throws DataFormatException If the byte array does not end with null.
197 */
198 protected int getNextLength(byte[] in, int pos) throws DataFormatException
199 {
200 int offset = pos;
201 int length = 0;
202 while (in[offset++] != 0)
203 {
204 if (offset >= in.length)
205 throw new DataFormatException("byte[] is not a valid msg");
206 length++;
207 }
208 return length;
209 }
210 }