Search in sources :

Example 1 with PServiceCallType

use of net.morimekta.providence.PServiceCallType in project providence by morimekta.

the class FastBinarySerializer 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 SerializerException {
    String methodName = null;
    int sequence = 0;
    PServiceCallType type = null;
    try {
        LittleEndianBinaryReader in = new LittleEndianBinaryReader(is);
        // Max method name length: 255 chars.
        int tag = in.readIntVarint();
        int len = tag >>> 3;
        int typeKey = tag & 0x07;
        methodName = new String(in.expectBytes(len), UTF_8);
        sequence = in.readIntVarint();
        type = PServiceCallType.findById(typeKey);
        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);
            return (PServiceCall<Message, Field>) new PServiceCall<>(methodName, type, sequence, ex);
        }
        PServiceMethod method = service.getMethod(methodName);
        if (method == null) {
            throw new SerializerException("No such method %s on %s", methodName, service.getQualifiedName()).setExceptionType(PApplicationExceptionType.UNKNOWN_METHOD);
        }
        @SuppressWarnings("unchecked") PMessageDescriptor<Message, Field> descriptor = isRequestCallType(type) ? method.getRequestType() : method.getResponseType();
        if (descriptor == null) {
            throw new SerializerException("No such %s descriptor for %s", isRequestCallType(type) ? "request" : "response", service.getQualifiedName()).setExceptionType(PApplicationExceptionType.UNKNOWN_METHOD);
        }
        Message message = readMessage(in, descriptor);
        return new PServiceCall<>(methodName, type, sequence, message);
    } catch (SerializerException e) {
        throw new SerializerException(e).setCallType(type).setMethodName(methodName).setSequenceNo(sequence);
    } catch (IOException e) {
        throw new SerializerException(e, e.getMessage()).setCallType(type).setMethodName(methodName).setSequenceNo(sequence);
    }
}
Also used : PMessage(net.morimekta.providence.PMessage) PServiceCallType(net.morimekta.providence.PServiceCallType) IOException(java.io.IOException) PField(net.morimekta.providence.descriptor.PField) PApplicationException(net.morimekta.providence.PApplicationException) PServiceCall(net.morimekta.providence.PServiceCall) LittleEndianBinaryReader(net.morimekta.util.io.LittleEndianBinaryReader) PServiceMethod(net.morimekta.providence.descriptor.PServiceMethod) Nonnull(javax.annotation.Nonnull)

Example 2 with PServiceCallType

use of net.morimekta.providence.PServiceCallType in project providence by morimekta.

the class JsonSerializer method parseServiceCall.

@SuppressWarnings("unchecked")
private <T extends PMessage<T, F>, F extends PField> PServiceCall<T, F> parseServiceCall(JsonTokenizer tokenizer, PService service) throws IOException {
    PServiceCallType type = null;
    String methodName = null;
    int sequence = 0;
    try {
        tokenizer.expectSymbol("service call start", JsonToken.kListStart);
        methodName = tokenizer.expectString("method name").rawJsonLiteral();
        tokenizer.expectSymbol("entry sep", JsonToken.kListSep);
        JsonToken callTypeToken = tokenizer.expect("call type");
        if (callTypeToken.isInteger()) {
            int typeKey = callTypeToken.byteValue();
            type = PServiceCallType.findById(typeKey);
            if (type == null) {
                throw new SerializerException("Service call type " + typeKey + " is not valid").setExceptionType(PApplicationExceptionType.INVALID_MESSAGE_TYPE);
            }
        } else if (callTypeToken.isLiteral()) {
            String typeName = callTypeToken.rawJsonLiteral();
            type = PServiceCallType.findByName(typeName.toUpperCase(Locale.US));
            if (type == null) {
                throw new SerializerException("Service call type \"" + Strings.escape(typeName) + "\" is not valid").setExceptionType(PApplicationExceptionType.INVALID_MESSAGE_TYPE);
            }
        } else {
            throw new SerializerException("Invalid service call type token " + callTypeToken.asString()).setExceptionType(PApplicationExceptionType.INVALID_MESSAGE_TYPE);
        }
        tokenizer.expectSymbol("entry sep", JsonToken.kListSep);
        sequence = tokenizer.expectNumber("Service call sequence").intValue();
        tokenizer.expectSymbol("entry sep", JsonToken.kListSep);
        if (type == PServiceCallType.EXCEPTION) {
            PApplicationException ex = (PApplicationException) parseTypedValue(tokenizer.expect("Message start"), tokenizer, PApplicationException.kDescriptor, false);
            tokenizer.expectSymbol("service call end", JsonToken.kListEnd);
            return (PServiceCall<T, F>) new PServiceCall<>(methodName, type, sequence, ex);
        }
        PServiceMethod method = service.getMethod(methodName);
        if (method == null) {
            throw new SerializerException("No such method " + methodName + " on " + service.getQualifiedName()).setExceptionType(PApplicationExceptionType.UNKNOWN_METHOD);
        }
        @SuppressWarnings("unchecked") PMessageDescriptor<T, F> descriptor = isRequestCallType(type) ? method.getRequestType() : method.getResponseType();
        if (descriptor == null) {
            throw new SerializerException("No %s type for %s.%s()", isRequestCallType(type) ? "request" : "response", service.getQualifiedName(), methodName).setExceptionType(PApplicationExceptionType.UNKNOWN_METHOD);
        }
        T message = (T) parseTypedValue(tokenizer.expect("message start"), tokenizer, descriptor, false);
        tokenizer.expectSymbol("service call end", JsonToken.kListEnd);
        return new PServiceCall<>(methodName, type, sequence, message);
    } catch (SerializerException se) {
        throw new SerializerException(se).setMethodName(methodName).setCallType(type).setSequenceNo(sequence);
    } catch (JsonException je) {
        throw new JsonSerializerException(je).setMethodName(methodName).setCallType(type).setSequenceNo(sequence);
    }
}
Also used : JsonException(net.morimekta.util.json.JsonException) PServiceCallType(net.morimekta.providence.PServiceCallType) PApplicationException(net.morimekta.providence.PApplicationException) PServiceCall(net.morimekta.providence.PServiceCall) JsonToken(net.morimekta.util.json.JsonToken) PServiceMethod(net.morimekta.providence.descriptor.PServiceMethod)

Example 3 with PServiceCallType

use of net.morimekta.providence.PServiceCallType 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 4 with PServiceCallType

use of net.morimekta.providence.PServiceCallType 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 5 with PServiceCallType

use of net.morimekta.providence.PServiceCallType in project providence by morimekta.

the class TProtocolSerializer 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 SerializerException {
    PServiceCallType type = null;
    TMessage tm = null;
    try {
        TTransport transport = new TIOStreamTransport(input);
        TProtocol protocol = protocolFactory.getProtocol(transport);
        tm = protocol.readMessageBegin();
        type = PServiceCallType.findById(tm.type);
        if (type == null) {
            throw new SerializerException("Unknown call type for id " + tm.type).setExceptionType(PApplicationExceptionType.INVALID_MESSAGE_TYPE);
        } else if (type == PServiceCallType.EXCEPTION) {
            PApplicationException exception = readMessage(protocol, PApplicationException.kDescriptor);
            return new PServiceCall(tm.name, type, tm.seqid, exception);
        }
        PServiceMethod method = service.getMethod(tm.name);
        if (method == null) {
            throw new SerializerException("No such method " + tm.name + " on " + service.getQualifiedName()).setExceptionType(PApplicationExceptionType.UNKNOWN_METHOD);
        }
        @SuppressWarnings("unchecked") PMessageDescriptor<Message, Field> descriptor = isRequestCallType(type) ? method.getRequestType() : method.getResponseType();
        Message message = readMessage(protocol, descriptor);
        protocol.readMessageEnd();
        return new PServiceCall<>(tm.name, type, tm.seqid, message);
    } catch (TTransportException e) {
        throw new SerializerException(e, e.getMessage()).setExceptionType(PApplicationExceptionType.findById(e.getType())).setCallType(type).setSequenceNo(tm != null ? tm.seqid : 0).setMethodName(tm != null ? tm.name : null);
    } catch (TException e) {
        throw new SerializerException(e, e.getMessage()).setExceptionType(PApplicationExceptionType.PROTOCOL_ERROR).setCallType(type).setSequenceNo(tm != null ? tm.seqid : 0).setMethodName(tm != null ? tm.name : null);
    } catch (SerializerException e) {
        e.setMethodName(tm.name).setSequenceNo(tm.seqid).setCallType(type);
        throw e;
    }
}
Also used : TException(org.apache.thrift.TException) PMessage(net.morimekta.providence.PMessage) TMessage(org.apache.thrift.protocol.TMessage) PServiceCallType(net.morimekta.providence.PServiceCallType) TTransportException(org.apache.thrift.transport.TTransportException) TIOStreamTransport(org.apache.thrift.transport.TIOStreamTransport) SerializerException(net.morimekta.providence.serializer.SerializerException) TField(org.apache.thrift.protocol.TField) PField(net.morimekta.providence.descriptor.PField) TMessage(org.apache.thrift.protocol.TMessage) TProtocol(org.apache.thrift.protocol.TProtocol) PApplicationException(net.morimekta.providence.PApplicationException) PServiceCall(net.morimekta.providence.PServiceCall) TTransport(org.apache.thrift.transport.TTransport) PServiceMethod(net.morimekta.providence.descriptor.PServiceMethod) Nonnull(javax.annotation.Nonnull)

Aggregations

PServiceCall (net.morimekta.providence.PServiceCall)6 PServiceCallType (net.morimekta.providence.PServiceCallType)6 PServiceMethod (net.morimekta.providence.descriptor.PServiceMethod)6 Nonnull (javax.annotation.Nonnull)5 PApplicationException (net.morimekta.providence.PApplicationException)5 PMessage (net.morimekta.providence.PMessage)5 PField (net.morimekta.providence.descriptor.PField)4 IOException (java.io.IOException)3 SerializerException (net.morimekta.providence.serializer.SerializerException)2 TException (org.apache.thrift.TException)2 TMessage (org.apache.thrift.protocol.TMessage)2 TIOStreamTransport (org.apache.thrift.transport.TIOStreamTransport)2 TTransport (org.apache.thrift.transport.TTransport)2 TTransportException (org.apache.thrift.transport.TTransportException)2 BinaryFormatUtils.readMessage (net.morimekta.providence.serializer.binary.BinaryFormatUtils.readMessage)1 BinaryFormatUtils.writeMessage (net.morimekta.providence.serializer.binary.BinaryFormatUtils.writeMessage)1 Token (net.morimekta.providence.serializer.pretty.Token)1 Tokenizer (net.morimekta.providence.serializer.pretty.Tokenizer)1 TokenizerException (net.morimekta.providence.serializer.pretty.TokenizerException)1 BigEndianBinaryReader (net.morimekta.util.io.BigEndianBinaryReader)1