Search in sources :

Example 16 with PMessage

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);
    }
}
Also used : PMessage(net.morimekta.providence.PMessage) PServiceCallType(net.morimekta.providence.PServiceCallType) PServiceCall(net.morimekta.providence.PServiceCall) Token(net.morimekta.providence.serializer.pretty.Token) TokenizerException(net.morimekta.providence.serializer.pretty.TokenizerException) IOException(java.io.IOException) Tokenizer(net.morimekta.providence.serializer.pretty.Tokenizer) PServiceMethod(net.morimekta.providence.descriptor.PServiceMethod) Nonnull(javax.annotation.Nonnull)

Example 17 with PMessage

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();
}
Also used : PField(net.morimekta.providence.descriptor.PField) PMessage(net.morimekta.providence.PMessage) PField(net.morimekta.providence.descriptor.PField) BigEndianBinaryReader(net.morimekta.util.io.BigEndianBinaryReader) SerializerException(net.morimekta.providence.serializer.SerializerException)

Example 18 with PMessage

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();
    }
}
Also used : IOMessageWriter(net.morimekta.providence.mio.IOMessageWriter) PMessage(net.morimekta.providence.PMessage) MessageWriter(net.morimekta.providence.mio.MessageWriter) IOMessageWriter(net.morimekta.providence.mio.IOMessageWriter)

Example 19 with PMessage

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);
    }
}
Also used : BinaryFormatUtils.writeMessage(net.morimekta.providence.serializer.binary.BinaryFormatUtils.writeMessage) BinaryFormatUtils.readMessage(net.morimekta.providence.serializer.binary.BinaryFormatUtils.readMessage) PMessage(net.morimekta.providence.PMessage) PServiceCallType(net.morimekta.providence.PServiceCallType) BigEndianBinaryReader(net.morimekta.util.io.BigEndianBinaryReader) IOException(java.io.IOException) PField(net.morimekta.providence.descriptor.PField) PApplicationException(net.morimekta.providence.PApplicationException) PServiceCall(net.morimekta.providence.PServiceCall) PServiceMethod(net.morimekta.providence.descriptor.PServiceMethod) Nonnull(javax.annotation.Nonnull)

Example 20 with PMessage

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();
}
Also used : TField(org.apache.thrift.protocol.TField) PField(net.morimekta.providence.descriptor.PField) TField(org.apache.thrift.protocol.TField) PMessage(net.morimekta.providence.PMessage) TMessage(org.apache.thrift.protocol.TMessage) PField(net.morimekta.providence.descriptor.PField) SerializerException(net.morimekta.providence.serializer.SerializerException)

Aggregations

PMessage (net.morimekta.providence.PMessage)31 PField (net.morimekta.providence.descriptor.PField)20 Nonnull (javax.annotation.Nonnull)7 TokenizerException (net.morimekta.providence.serializer.pretty.TokenizerException)7 IOException (java.io.IOException)6 PEnumValue (net.morimekta.providence.PEnumValue)6 PServiceCall (net.morimekta.providence.PServiceCall)6 PServiceCallType (net.morimekta.providence.PServiceCallType)6 Token (net.morimekta.providence.serializer.pretty.Token)6 Map (java.util.Map)5 PApplicationException (net.morimekta.providence.PApplicationException)5 PMessageDescriptor (net.morimekta.providence.descriptor.PMessageDescriptor)5 SerializerException (net.morimekta.providence.serializer.SerializerException)5 Binary (net.morimekta.util.Binary)5 ArrayList (java.util.ArrayList)4 PMessageBuilder (net.morimekta.providence.PMessageBuilder)4 PServiceMethod (net.morimekta.providence.descriptor.PServiceMethod)4 TMessage (org.apache.thrift.protocol.TMessage)4 ByteArrayInputStream (java.io.ByteArrayInputStream)3 ByteArrayOutputStream (java.io.ByteArrayOutputStream)3