use of net.morimekta.providence.PMessage in project providence by morimekta.
the class PrettySerializer method deserialize.
@Nonnull
@Override
@SuppressWarnings("unchecked")
public <Message extends PMessage<Message, Field>, Field extends PField> PServiceCall<Message, Field> deserialize(@Nonnull InputStream input, @Nonnull PService service) throws IOException {
String methodName = null;
int sequence = 0;
PServiceCallType callType = null;
try {
// pretty printed service calls cannot be chained-serialized, so this should be totally safe.
Tokenizer tokenizer = new Tokenizer(input);
Token token = tokenizer.expect("Sequence or type");
if (token.isInteger()) {
sequence = (int) token.parseInteger();
tokenizer.expectSymbol("Sequence type sep", Token.kKeyValueSep);
token = tokenizer.expectIdentifier("Call Type");
}
callType = PServiceCallType.findByName(token.asString().toUpperCase(Locale.US));
if (callType == null) {
throw new TokenizerException(token, "No such call type %s", token.asString()).setLine(tokenizer.getLine()).setExceptionType(PApplicationExceptionType.INVALID_MESSAGE_TYPE);
}
token = tokenizer.expectIdentifier("method name");
methodName = token.asString();
PServiceMethod method = service.getMethod(methodName);
if (method == null) {
throw new TokenizerException(token, "no such method %s on service %s", methodName, service.getQualifiedName()).setLine(tokenizer.getLine()).setExceptionType(PApplicationExceptionType.UNKNOWN_METHOD);
}
tokenizer.expectSymbol("call params start", Token.kParamsStart);
Message message;
switch(callType) {
case CALL:
case ONEWAY:
message = (Message) readMessage(tokenizer, method.getRequestType(), true);
break;
case REPLY:
message = (Message) readMessage(tokenizer, method.getResponseType(), true);
break;
case EXCEPTION:
message = (Message) readMessage(tokenizer, PApplicationException.kDescriptor, true);
break;
default:
throw new IllegalStateException("Unreachable code reached");
}
return new PServiceCall<>(methodName, callType, sequence, message);
} catch (TokenizerException e) {
e.setCallType(callType).setSequenceNo(sequence).setMethodName(methodName);
throw e;
} catch (IOException e) {
throw new SerializerException(e, e.getMessage()).setCallType(callType).setSequenceNo(sequence).setMethodName(methodName);
}
}
use of net.morimekta.providence.PMessage in project providence by morimekta.
the class BinaryFormatUtils method readMessage.
/**
* Read message from reader.
*
* @param input The input reader.
* @param descriptor The message descriptor.
* @param strict If the message should be read in strict mode.
* @param <Message> The message type.
* @param <Field> The field type.
* @return The read and parsed message.
* @throws IOException If read failed.
*/
public static <Message extends PMessage<Message, Field>, Field extends PField> Message readMessage(BigEndianBinaryReader input, PMessageDescriptor<Message, Field> descriptor, boolean strict) throws IOException {
PMessageBuilder<Message, Field> builder = descriptor.builder();
if (builder instanceof BinaryReader) {
((BinaryReader) builder).readBinary(input, strict);
} else {
FieldInfo fieldInfo = readFieldInfo(input);
while (fieldInfo != null) {
PField field = descriptor.findFieldById(fieldInfo.getId());
if (field != null) {
Object value = readFieldValue(input, fieldInfo, field.getDescriptor(), strict);
builder.set(field.getId(), value);
} else {
readFieldValue(input, fieldInfo, null, false);
}
fieldInfo = readFieldInfo(input);
}
if (strict) {
try {
builder.validate();
} catch (IllegalStateException e) {
throw new SerializerException(e, e.getMessage());
}
}
}
return builder.build();
}
use of net.morimekta.providence.PMessage in project providence by morimekta.
the class MessageGenerator method dumpGeneratedMessages.
/**
* Dump all generated messages.
*
* @throws IOException If writing the messages failed.
*/
@SuppressWarnings("unchecked")
private void dumpGeneratedMessages() throws IOException {
MessageWriter writer = this.writer;
if (writer == null) {
writer = new IOMessageWriter(System.err, outputSerializer);
}
for (PMessage message : generated) {
writer.write(message);
writer.separator();
}
}
use of net.morimekta.providence.PMessage in project providence by morimekta.
the class BinarySerializer method deserialize.
@Nonnull
@Override
@SuppressWarnings("unchecked")
public <Message extends PMessage<Message, Field>, Field extends PField> PServiceCall<Message, Field> deserialize(@Nonnull InputStream is, @Nonnull PService service) throws IOException {
BigEndianBinaryReader in = new BigEndianBinaryReader(is);
String methodName = null;
int sequence = 0;
PServiceCallType type = null;
try {
int methodNameLen = in.expectInt();
int typeKey;
// versioned
if (methodNameLen <= 0) {
int version = methodNameLen & VERSION_MASK;
if (version == VERSION_1) {
typeKey = methodNameLen & 0xFF;
methodNameLen = in.expectInt();
if (methodNameLen > MAX_METHOD_NAME_LEN) {
throw new SerializerException("Exceptionally long method name of %s bytes", methodNameLen).setExceptionType(PApplicationExceptionType.PROTOCOL_ERROR);
}
if (methodNameLen < 1) {
throw new SerializerException("Exceptionally short method name of %s bytes", methodNameLen).setExceptionType(PApplicationExceptionType.PROTOCOL_ERROR);
}
methodName = new String(in.expectBytes(methodNameLen), UTF_8);
} else {
throw new SerializerException("Bad protocol version: %08x", version >>> 16).setExceptionType(PApplicationExceptionType.INVALID_PROTOCOL);
}
} else {
if (strict && versioned) {
throw new SerializerException("Missing protocol version").setExceptionType(PApplicationExceptionType.INVALID_PROTOCOL);
}
if (methodNameLen > MAX_METHOD_NAME_LEN) {
if (methodNameLen >>> 24 == '<') {
throw new SerializerException("Received HTML in service call").setExceptionType(PApplicationExceptionType.PROTOCOL_ERROR);
}
if (methodNameLen >>> 24 == '{' || methodNameLen >>> 24 == '[') {
throw new SerializerException("Received JSON in service call").setExceptionType(PApplicationExceptionType.PROTOCOL_ERROR);
}
throw new SerializerException("Exceptionally long method name of %s bytes", methodNameLen).setExceptionType(PApplicationExceptionType.PROTOCOL_ERROR);
}
methodName = new String(in.expectBytes(methodNameLen), UTF_8);
typeKey = in.expectByte();
}
sequence = in.expectInt();
type = PServiceCallType.findById(typeKey);
PServiceMethod method = service.getMethod(methodName);
if (type == null) {
throw new SerializerException("Invalid call type " + typeKey).setExceptionType(PApplicationExceptionType.INVALID_MESSAGE_TYPE);
} else if (type == PServiceCallType.EXCEPTION) {
PApplicationException ex = readMessage(in, PApplicationException.kDescriptor, strict);
return (PServiceCall<Message, Field>) new PServiceCall<>(methodName, type, sequence, ex);
} else if (method == null) {
throw new SerializerException("No such method " + methodName + " on " + service.getQualifiedName()).setExceptionType(PApplicationExceptionType.UNKNOWN_METHOD);
}
@SuppressWarnings("unchecked") PMessageDescriptor<Message, Field> descriptor = isRequestCallType(type) ? method.getRequestType() : method.getResponseType();
Message message = readMessage(in, descriptor, strict);
return new PServiceCall<>(methodName, type, sequence, message);
} catch (SerializerException se) {
throw new SerializerException(se).setMethodName(methodName).setCallType(type).setSequenceNo(sequence);
} catch (IOException e) {
throw new SerializerException(e, e.getMessage()).setMethodName(methodName).setCallType(type).setSequenceNo(sequence);
}
}
use of net.morimekta.providence.PMessage in project providence by morimekta.
the class TProtocolSerializer method readMessage.
private <Message extends PMessage<Message, Field>, Field extends PField> Message readMessage(TProtocol protocol, PMessageDescriptor<Message, Field> descriptor) throws SerializerException, TException {
TField f;
PMessageBuilder<Message, Field> builder = descriptor.builder();
// ignored.
protocol.readStructBegin();
while ((f = protocol.readFieldBegin()) != null) {
if (f.type == BinaryType.STOP) {
break;
}
PField field;
// f.name is never fulled out, rely on f.id being correct.
field = descriptor.findFieldById(f.id);
if (field != null) {
if (f.type != forType(field.getDescriptor().getType())) {
throw new SerializerException("Incompatible serialized type " + asString(f.type) + " for field " + field.getName() + ", expected " + asString(forType(field.getDescriptor().getType())));
}
Object value = readTypedValue(f.type, field.getDescriptor(), protocol, true);
if (value != null) {
builder.set(field.getId(), value);
}
} else {
TProtocolUtil.skip(protocol, f.type);
}
protocol.readFieldEnd();
}
protocol.readStructEnd();
if (readStrict) {
try {
builder.validate();
} catch (IllegalStateException e) {
throw new SerializerException(e, e.getMessage());
}
}
return builder.build();
}
Aggregations