Search in sources :

Example 1 with PServiceMethod

use of net.morimekta.providence.descriptor.PServiceMethod 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 PServiceMethod

use of net.morimekta.providence.descriptor.PServiceMethod 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 PServiceMethod

use of net.morimekta.providence.descriptor.PServiceMethod 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 PServiceMethod

use of net.morimekta.providence.descriptor.PServiceMethod in project providence by morimekta.

the class WrappedProcessorTest method testWrapper.

@Test
public void testWrapper() throws IOException {
    PProcessor processor = mock(PProcessor.class);
    WrappedProcessor wrap = new WrappedProcessor(processor, (call, p) -> {
        // before call
        PServiceCall reply = p.handleCall(call, p.getDescriptor());
        // after call
        return reply;
    });
    PApplicationException c = new PApplicationException("call", PApplicationExceptionType.INTERNAL_ERROR);
    PApplicationException r = new PApplicationException("call", PApplicationExceptionType.INTERNAL_ERROR);
    AtomicReference<PService> service = new AtomicReference<>();
    service.set(new PService("test", "Service", service::get, new PServiceMethod[] {}) {

        @Nullable
        @Override
        public PServiceMethod getMethod(String name) {
            for (PServiceMethod method : getMethods()) {
                if (method.getName().equals(name)) {
                    return method;
                }
            }
            return null;
        }
    });
    PServiceCall call = new PServiceCall<>("test", PServiceCallType.CALL, 44, c);
    PServiceCall reply = new PServiceCall<>("reply", PServiceCallType.REPLY, 44, r);
    when(processor.getDescriptor()).thenReturn(service.get());
    when(processor.handleCall(call, service.get())).thenReturn(reply);
    assertThat(wrap.handleCall(call), sameInstance(reply));
    verify(processor, atLeastOnce()).getDescriptor();
    verify(processor).handleCall(call, service.get());
    verifyNoMoreInteractions(processor);
}
Also used : PProcessor(net.morimekta.providence.PProcessor) PServiceCall(net.morimekta.providence.PServiceCall) PApplicationException(net.morimekta.providence.PApplicationException) AtomicReference(java.util.concurrent.atomic.AtomicReference) PServiceMethod(net.morimekta.providence.descriptor.PServiceMethod) Nullable(javax.annotation.Nullable) PService(net.morimekta.providence.descriptor.PService) Test(org.junit.Test)

Example 5 with PServiceMethod

use of net.morimekta.providence.descriptor.PServiceMethod 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)

Aggregations

PServiceCall (net.morimekta.providence.PServiceCall)7 PServiceMethod (net.morimekta.providence.descriptor.PServiceMethod)7 PApplicationException (net.morimekta.providence.PApplicationException)6 PServiceCallType (net.morimekta.providence.PServiceCallType)6 Nonnull (javax.annotation.Nonnull)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 AtomicReference (java.util.concurrent.atomic.AtomicReference)1 Nullable (javax.annotation.Nullable)1 PProcessor (net.morimekta.providence.PProcessor)1 PService (net.morimekta.providence.descriptor.PService)1 BinaryFormatUtils.readMessage (net.morimekta.providence.serializer.binary.BinaryFormatUtils.readMessage)1 BinaryFormatUtils.writeMessage (net.morimekta.providence.serializer.binary.BinaryFormatUtils.writeMessage)1