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 import org.opends.messages.Message;
029
030 import static org.opends.server.loggers.debug.DebugLogger.debugEnabled;
031 import static org.opends.server.loggers.debug.DebugLogger.getTracer;
032
033 import java.io.Serializable;
034 import java.io.UnsupportedEncodingException;
035 import java.util.zip.DataFormatException;
036
037 import org.opends.server.loggers.debug.DebugTracer;
038
039 /**
040 * This message is part of the replication protocol.
041 * This message is sent by a server or a replication server when an error
042 * is detected in the context of a total update.
043 */
044 public class ErrorMessage extends RoutableMessage implements
045 Serializable
046 {
047 private static final long serialVersionUID = 2726389860247088266L;
048
049 // The tracer object for the debug logger
050 private static final DebugTracer TRACER = getTracer();
051
052 // Specifies the messageID built from the error that was detected
053 private int msgID;
054
055 // Specifies the complementary details about the error that was detected
056 private Message details = null;
057
058 /**
059 * Creates an ErrorMessage providing the destination server.
060 *
061 * @param sender The server ID of the server that send this message.
062 * @param destination The destination server or servers of this message.
063 * @param details The message containing the details of the error.
064 */
065 public ErrorMessage(short sender, short destination,
066 Message details)
067 {
068 super(sender, destination);
069 this.msgID = details.getDescriptor().getId();
070 this.details = details;
071
072 if (debugEnabled())
073 TRACER.debugInfo(" Creating error message" + this.toString());
074 }
075
076 /**
077 * Creates an ErrorMessage.
078 *
079 * @param destination replication server id
080 * @param details details of the error
081 */
082 public ErrorMessage(short destination, Message details)
083 {
084 super((short)-2, destination);
085 this.msgID = details.getDescriptor().getId();
086 this.details = details;
087
088 if (debugEnabled())
089 TRACER.debugInfo(this.toString());
090 }
091
092 /**
093 * Creates a new ErrorMessage by decoding the provided byte array.
094 *
095 * @param in A byte array containing the encoded information for the Message
096 * @throws DataFormatException If the in does not contain a properly
097 * encoded message.
098 */
099 public ErrorMessage(byte[] in) throws DataFormatException
100 {
101 super();
102 try
103 {
104 /* first byte is the type */
105 if (in[0] != MSG_TYPE_ERROR)
106 throw new DataFormatException("input is not a valid InitializeMessage");
107 int pos = 1;
108
109 // sender
110 int length = getNextLength(in, pos);
111 String senderString = new String(in, pos, length, "UTF-8");
112 senderID = Short.valueOf(senderString);
113 pos += length +1;
114
115 // destination
116 length = getNextLength(in, pos);
117 String serverIdString = new String(in, pos, length, "UTF-8");
118 destination = Short.valueOf(serverIdString);
119 pos += length +1;
120
121 // MsgID
122 length = getNextLength(in, pos);
123 String msgIdString = new String(in, pos, length, "UTF-8");
124 msgID = Integer.valueOf(msgIdString);
125 pos += length +1;
126
127 // Details
128 length = getNextLength(in, pos);
129 details = Message.raw(new String(in, pos, length, "UTF-8"));
130 pos += length +1;
131
132 }
133 catch (UnsupportedEncodingException e)
134 {
135 throw new DataFormatException("UTF-8 is not supported by this jvm.");
136 }
137 }
138
139 /**
140 * Get the base DN from this InitializeMessage.
141 *
142 * @return the base DN from this InitializeMessage.
143 */
144 public Message getDetails()
145 {
146 return details;
147 }
148
149 /**
150 * Get the base DN from this InitializeMessage.
151 *
152 * @return the base DN from this InitializeMessage.
153 */
154 public int getMsgID()
155 {
156 return msgID;
157 }
158
159 /**
160 * {@inheritDoc}
161 */
162 @Override
163 public byte[] getBytes()
164 {
165 /* The InitializeMessage is stored in the form :
166 * <operation type><basedn><serverid>
167 */
168 try {
169 byte[] byteSender = String.valueOf(senderID).getBytes("UTF-8");
170 byte[] byteDestination = String.valueOf(destination).getBytes("UTF-8");
171 byte[] byteErrMsgId = String.valueOf(msgID).getBytes("UTF-8");
172 byte[] byteDetails = details.toString().getBytes("UTF-8");
173
174 int length = 1 + byteSender.length + 1
175 + byteDestination.length + 1
176 + byteErrMsgId.length + 1
177 + byteDetails.length + 1;
178
179 byte[] resultByteArray = new byte[length];
180
181 // put the type of the operation
182 resultByteArray[0] = MSG_TYPE_ERROR;
183 int pos = 1;
184
185 // sender
186 pos = addByteArray(byteSender, resultByteArray, pos);
187
188 // destination
189 pos = addByteArray(byteDestination, resultByteArray, pos);
190
191 // MsgId
192 pos = addByteArray(byteErrMsgId, resultByteArray, pos);
193
194 // details
195 pos = addByteArray(byteDetails, resultByteArray, pos);
196
197 return resultByteArray;
198 }
199 catch (UnsupportedEncodingException e)
200 {
201 return null;
202 }
203 }
204
205 /**
206 * Returns a string representation of the message.
207 *
208 * @return the string representation of this message.
209 */
210 public String toString()
211 {
212 return "ErrorMessage=["+
213 " sender=" + this.senderID +
214 " destination=" + this.destination +
215 " msgID=" + this.msgID +
216 " details=" + this.details + "]";
217 }
218 }