package lsr.paxos.messages;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
/**
* This class is responsible for serializing and deserializing messages to /
* from byte array or input stream. The message has to be serialized using
* <code>serialize()</code> method to deserialized it correctly.
*/
public final class MessageFactory {
/**
* Creates a <code>Message</code> from serialized byte array.
*
* @param message - serialized byte array with message content
* @return deserialized message
* @throws ClassNotFoundException
* @throws IOException
*/
public static Message readByteArray(byte[] message) throws IOException {
DataInputStream input = new DataInputStream(new ByteArrayInputStream(message));
return create(input);
}
/**
* Creates a <code>Message</code> from input stream. Reads byte array and
* creates message from it. Byte array must have been written by
* Message::toByteArray().
*
* @param input - the input stream with serialized message inside
* @return correct object from one of message subclasses
* @throws IOException
*
* @throws IllegalArgumentException if a correct message could not be read
* from input
*/
public static Message create(DataInputStream input) throws IOException {
MessageType type = MessageType.values()[input.readUnsignedByte()];
Message message = createMessage(type, input);
return message;
}
/**
* Creates new message of specified type from given stream.
*
* @param type - the type of message to create
* @param input - the stream with serialized message
* @return deserialized message
*
* @throws IOException if I/O error occurs
*/
private static Message createMessage(MessageType type, DataInputStream input)
throws IOException {
assert type != MessageType.ANY && type != MessageType.SENT : "Message type " + type +
" cannot be serialized";
Message message;
switch (type) {
case Accept:
message = new Accept(input);
break;
case Alive:
message = new Alive(input);
break;
case CatchUpQuery:
message = new CatchUpQuery(input);
break;
case CatchUpResponse:
message = new CatchUpResponse(input);
break;
case CatchUpSnapshot:
message = new CatchUpSnapshot(input);
break;
case Prepare:
message = new Prepare(input);
break;
case PrepareOK:
message = new PrepareOK(input);
break;
case Propose:
message = new Propose(input);
break;
case Recovery:
message = new Recovery(input);
break;
case RecoveryAnswer:
message = new RecoveryAnswer(input);
break;
case ForwardedClientBatch:
message = new ForwardClientBatch(input);
break;
case AskForClientBatch:
message = new AskForClientBatch(input);
break;
case ForwardedClientRequests:
message = new ForwardClientRequests(input);
break;
default:
throw new IllegalArgumentException("Unknown message type: " + type);
}
return message;
}
}