From 2860959d5f9526aa84ef5f66b34d68bb0e197194 Mon Sep 17 00:00:00 2001 From: Naveen Reddy Chedeti Date: Thu, 28 Jul 2016 08:48:27 -0700 Subject: [PATCH] Support Thrift Messages --- RELEASING.md | 6 +- all/build.gradle | 1 + build.gradle | 2 +- .../main/java/io/grpc/internal/IoUtils.java | 57 + .../java/io/grpc/internal/IoUtilsTest.java | 68 ++ examples/settings.gradle | 1 + examples/thrift/build.gradle | 55 + .../thrift/helloworld/GreeterGrpc.java | 1007 +++++++++++++++++ .../thrift/helloworld/HelloRequest.java | 395 +++++++ .../thrift/helloworld/HelloResponse.java | 395 +++++++ .../thrift/helloworld/HelloWorldClient.java | 89 ++ .../thrift/helloworld/HelloWorldServer.java | 93 ++ .../thrift/src/main/thrift/helloworld.thrift | 13 + settings.gradle | 2 + thrift/build.gradle | 29 + .../test/java/io/grpc/thrift/Message.java | 744 ++++++++++++ .../java/io/grpc/thrift/MessageFactory.java | 41 + .../io/grpc/thrift/ThriftInputStream.java | 122 ++ .../main/java/io/grpc/thrift/ThriftUtils.java | 111 ++ .../java/io/grpc/thrift/ThriftUtilsTest.java | 183 +++ thrift/src/test/thrift/messages.thrift | 37 + 21 files changed, 3447 insertions(+), 4 deletions(-) create mode 100644 core/src/main/java/io/grpc/internal/IoUtils.java create mode 100644 core/src/test/java/io/grpc/internal/IoUtilsTest.java create mode 100644 examples/thrift/build.gradle create mode 100644 examples/thrift/src/generated/main/grpc/io/grpc/examples/thrift/helloworld/GreeterGrpc.java create mode 100644 examples/thrift/src/generated/main/java/io/grpc/examples/thrift/helloworld/HelloRequest.java create mode 100644 examples/thrift/src/generated/main/java/io/grpc/examples/thrift/helloworld/HelloResponse.java create mode 100644 examples/thrift/src/main/java/io/grpc/examples/thrift/helloworld/HelloWorldClient.java create mode 100644 examples/thrift/src/main/java/io/grpc/examples/thrift/helloworld/HelloWorldServer.java create mode 100644 examples/thrift/src/main/thrift/helloworld.thrift create mode 100644 thrift/build.gradle create mode 100644 thrift/src/generated/test/java/io/grpc/thrift/Message.java create mode 100644 thrift/src/main/java/io/grpc/thrift/MessageFactory.java create mode 100644 thrift/src/main/java/io/grpc/thrift/ThriftInputStream.java create mode 100644 thrift/src/main/java/io/grpc/thrift/ThriftUtils.java create mode 100644 thrift/src/test/java/io/grpc/thrift/ThriftUtilsTest.java create mode 100644 thrift/src/test/thrift/messages.thrift diff --git a/RELEASING.md b/RELEASING.md index 7b362e4475..0334621612 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -78,7 +78,7 @@ would be used to create all `v0.7` tags (e.g. `v0.7.0`, `v0.7.1`). $ sed -i 's/[0-9]\+\.[0-9]\+\.[0-9]\+\(.*CURRENT_GRPC_VERSION\)/'$MAJOR.$((MINOR+1)).0'\1/' \ build.gradle android-interop-testing/app/build.gradle \ examples/build.gradle examples/pom.xml \ - examples/android/app/build.gradle + examples/android/app/build.gradle examples/thrift/build.gradle $ ./gradlew build $ git commit -a -m "Start $MAJOR.$((MINOR+1)).0 development cycle" ``` @@ -98,7 +98,7 @@ would be used to create all `v0.7` tags (e.g. `v0.7.0`, `v0.7.1`). $ sed -i 's/-SNAPSHOT\(.*CURRENT_GRPC_VERSION\)/\1/' \ build.gradle android-interop-testing/app/build.gradle \ examples/build.gradle examples/pom.xml \ - examples/android/app/build.gradle + examples/android/app/build.gradle examples/thrift/build.gradle $ ./gradlew build $ git commit -a -m "Bump version to $MAJOR.$MINOR.$PATCH" $ git tag -a v$MAJOR.$MINOR.$PATCH -m "Version $MAJOR.$MINOR.$PATCH" @@ -111,7 +111,7 @@ would be used to create all `v0.7` tags (e.g. `v0.7.0`, `v0.7.1`). $ sed -i 's/[0-9]\+\.[0-9]\+\.[0-9]\+\(.*CURRENT_GRPC_VERSION\)/'$MAJOR.$MINOR.$((PATCH+1))-SNAPSHOT'\1/' \ build.gradle android-interop-testing/app/build.gradle \ examples/build.gradle examples/pom.xml \ - examples/android/app/build.gradle + examples/android/app/build.gradle examples/thrift/build.gradle $ ./gradlew build $ git commit -a -m "Bump version to $MAJOR.$MINOR.$((PATCH+1))-SNAPSHOT" ``` diff --git a/all/build.gradle b/all/build.gradle index a84d9eeda5..a78d440ecf 100644 --- a/all/build.gradle +++ b/all/build.gradle @@ -20,6 +20,7 @@ def subprojects = [ project(':grpc-protobuf-lite'), project(':grpc-protobuf-nano'), project(':grpc-stub'), + project(':grpc-thrift'), ] for (subproject in rootProject.subprojects) { diff --git a/build.gradle b/build.gradle index a6fce8b591..3e2df8ec22 100644 --- a/build.gradle +++ b/build.gradle @@ -289,7 +289,7 @@ subprojects { } } if (!(project.name in - ["grpc-stub", "grpc-protobuf", "grpc-protobuf-lite", "grpc-protobuf-nano"])) { + ["grpc-stub", "grpc-protobuf", "grpc-protobuf-lite", "grpc-protobuf-nano", "grpc-thrift"])) { def core = pom.dependencies.find {dep -> dep.artifactId == 'grpc-core'} if (core != null) { // Depend on specific version of grpc-core because internal package is unstable diff --git a/core/src/main/java/io/grpc/internal/IoUtils.java b/core/src/main/java/io/grpc/internal/IoUtils.java new file mode 100644 index 0000000000..5178c2f4b8 --- /dev/null +++ b/core/src/main/java/io/grpc/internal/IoUtils.java @@ -0,0 +1,57 @@ +/* + * Copyright 2016, Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package io.grpc.internal; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; + +/** Common IoUtils for thrift and nanopb to convert inputstream to bytes. */ +public final class IoUtils { + + /** maximum buffer to be read is 16 KB. */ + private static final int MAX_BUFFER_LENGTH = 16384; + + /** Returns the byte array. */ + public static byte[] toByteArray(InputStream is) throws IOException { + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + int nRead; + byte[] bytes = new byte[MAX_BUFFER_LENGTH]; + + while ((nRead = is.read(bytes, 0, bytes.length)) != -1) { + buffer.write(bytes, 0, nRead); + } + + buffer.flush(); + return buffer.toByteArray(); + } +} \ No newline at end of file diff --git a/core/src/test/java/io/grpc/internal/IoUtilsTest.java b/core/src/test/java/io/grpc/internal/IoUtilsTest.java new file mode 100644 index 0000000000..43b3bd746f --- /dev/null +++ b/core/src/test/java/io/grpc/internal/IoUtilsTest.java @@ -0,0 +1,68 @@ +/* + * Copyright 2016, Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package io.grpc.internal; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotSame; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; + +/** Unit test for IoUtils. */ +@RunWith(JUnit4.class) +public class IoUtilsTest { + + @Test + public void testRoundTrip() throws Exception { + byte[] bytes = { 1, 2, 3, -127, 100, 127}; + InputStream is = new ByteArrayInputStream(bytes); + byte[] bytes2 = IoUtils.toByteArray(is); + + assertNotSame(bytes2, bytes); + assertEquals(bytes.length, bytes2.length); + for (int i = 0; i < bytes.length; ++i) { + assertEquals(bytes[i], bytes2[i]); + } + } + + @Test + public void testEmpty() throws Exception { + InputStream is = new ByteArrayInputStream(new byte[0]); + byte[] bytes = IoUtils.toByteArray(is); + + assertEquals(0, bytes.length); + } +} \ No newline at end of file diff --git a/examples/settings.gradle b/examples/settings.gradle index 9512a19f3b..091fcf2a34 100644 --- a/examples/settings.gradle +++ b/examples/settings.gradle @@ -1 +1,2 @@ rootProject.name = 'examples' +include 'thrift' diff --git a/examples/thrift/build.gradle b/examples/thrift/build.gradle new file mode 100644 index 0000000000..4c1760e184 --- /dev/null +++ b/examples/thrift/build.gradle @@ -0,0 +1,55 @@ +apply plugin: 'application' + +description = "Thrift Examples" + +startScripts.enabled = false + +def grpcVersion = '1.1.0-SNAPSHOT' // CURRENT_GRPC_VERSION + +repositories { + mavenCentral() + mavenLocal() +} + +dependencies { + compile "io.grpc:grpc-stub:${grpcVersion}" + compile "io.grpc:grpc-thrift:${grpcVersion}" + compile "io.grpc:grpc-netty:${grpcVersion}" +} + +String generatedSourcePath = "${projectDir}/src/generated" +project.sourceSets { + main { + java { + srcDir "${generatedSourcePath}/main/java" + srcDir "${generatedSourcePath}/main/grpc" + } + } +} + +task thriftHelloWorldServer(type: CreateStartScripts) { + mainClassName = "io.grpc.examples.thrift.helloworld.HelloWorldServer" + applicationName = "thrift-hello-world-server" + outputDir = new File(project.buildDir, 'tmp') + classpath = jar.outputs.files + project.configurations.runtime +} + +task thriftHelloWorldClient(type: CreateStartScripts) { + mainClassName = "io.grpc.examples.thrift.helloworld.HelloWorldClient" + applicationName = "thrift-hello-world-client" + outputDir = new File(project.buildDir, 'tmp') + classpath = jar.outputs.files + project.configurations.runtime +} + +applicationDistribution.into("bin") { + from(thriftHelloWorldServer) + from(thriftHelloWorldClient) + fileMode = 0755 +} + +idea { + module { + sourceDirs += file("${projectDir}/src/generated/main/java"); + sourceDirs += file("${projectDir}/src/generated/main/grpc"); + } +} diff --git a/examples/thrift/src/generated/main/grpc/io/grpc/examples/thrift/helloworld/GreeterGrpc.java b/examples/thrift/src/generated/main/grpc/io/grpc/examples/thrift/helloworld/GreeterGrpc.java new file mode 100644 index 0000000000..b4bdeee008 --- /dev/null +++ b/examples/thrift/src/generated/main/grpc/io/grpc/examples/thrift/helloworld/GreeterGrpc.java @@ -0,0 +1,1007 @@ +/** + * Autogenerated by Thrift Compiler (1.0.0-dev) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +package io.grpc.examples.thrift.helloworld; + +import org.apache.thrift.scheme.IScheme; +import org.apache.thrift.scheme.SchemeFactory; +import org.apache.thrift.scheme.StandardScheme; + +import org.apache.thrift.scheme.TupleScheme; +import org.apache.thrift.protocol.TTupleProtocol; +import org.apache.thrift.protocol.TProtocolException; +import org.apache.thrift.EncodingUtils; +import org.apache.thrift.server.AbstractNonblockingServer.*; +import java.util.List; +import java.util.ArrayList; +import java.util.Map; +import java.util.HashMap; +import java.util.EnumMap; +import java.util.Set; +import java.util.HashSet; +import java.util.EnumSet; +import java.util.Collections; +import java.util.BitSet; +import java.nio.ByteBuffer; +import java.util.Arrays; +import javax.annotation.Generated; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static io.grpc.stub.ClientCalls.asyncUnaryCall; +import static io.grpc.stub.ClientCalls.asyncServerStreamingCall; +import static io.grpc.stub.ClientCalls.asyncClientStreamingCall; +import static io.grpc.stub.ClientCalls.asyncBidiStreamingCall; +import static io.grpc.stub.ClientCalls.blockingUnaryCall; +import static io.grpc.stub.ClientCalls.blockingServerStreamingCall; +import static io.grpc.stub.ClientCalls.futureUnaryCall; +import static io.grpc.MethodDescriptor.generateFullMethodName; +import static io.grpc.stub.ServerCalls.asyncUnaryCall; +import static io.grpc.stub.ServerCalls.asyncServerStreamingCall; +import static io.grpc.stub.ServerCalls.asyncClientStreamingCall; +import static io.grpc.stub.ServerCalls.asyncBidiStreamingCall; +import static io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall; +import static io.grpc.stub.ServerCalls.asyncUnimplementedStreamingCall; +import io.grpc.thrift.ThriftUtils; + +public class GreeterGrpc { + + private GreeterGrpc() {} + + public static final String SERVICE_NAME = "io.grpc.examples.thrift.helloworld.Greeter"; + + @java.lang.Deprecated public static interface Greeter { + public void sayHello(sayHello_args request, + io.grpc.stub.StreamObserver responseObserver); + + } + + private static final int ARG_IN_METHOD_sayHello = 1; + private static final int ARG_OUT_METHOD_sayHello = 2; + + private static final class ThriftMessageFactory> + implements io.grpc.thrift.MessageFactory { + private final int id; + + + ThriftMessageFactory(int id) { + this.id = id; + } + @java.lang.Override + public T newInstance() { + Object o; + switch (id) { + case ARG_IN_METHOD_sayHello: + o = new sayHello_args(); + break; + case ARG_OUT_METHOD_sayHello: + o = new sayHello_result(); + break; + default: + throw new AssertionError(); +} + @java.lang.SuppressWarnings("unchecked") + T t = (T) o; +return t; + } + } + public static abstract class GreeterImplBase implements Greeter, io.grpc.BindableService { + @java.lang.Override + public void sayHello(sayHello_args request, + io.grpc.stub.StreamObserver responseObserver) { + asyncUnimplementedUnaryCall(METHOD_sayHello, responseObserver); + } + + @java.lang.Override public io.grpc.ServerServiceDefinition bindService() { + return GreeterGrpc.bindService(this); + } + + } + + @java.lang.Deprecated public static abstract class AbstractGreeter extends GreeterImplBase {} + + public static class sayHello_args implements org.apache.thrift.TBase, java.io.Serializable, Cloneable, Comparable { + private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("sayHello_args"); + + private static final org.apache.thrift.protocol.TField REQUEST_FIELD_DESC = new org.apache.thrift.protocol.TField("request", org.apache.thrift.protocol.TType.STRUCT, (short)1); + + private static final SchemeFactory STANDARD_SCHEME_FACTORY = new sayHello_argsStandardSchemeFactory(); + private static final SchemeFactory TUPLE_SCHEME_FACTORY = new sayHello_argsTupleSchemeFactory(); + + public HelloRequest request; // required + + /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ + public enum _Fields implements org.apache.thrift.TFieldIdEnum { + REQUEST((short)1, "request"); + + private static final Map byName = new HashMap(); + + static { + for (_Fields field : EnumSet.allOf(_Fields.class)) { + byName.put(field.getFieldName(), field); + } + } + + /** + * Find the _Fields constant that matches fieldId, or null if its not found. + */ + public static _Fields findByThriftId(int fieldId) { + switch(fieldId) { + case 1: // REQUEST + return REQUEST; + default: + return null; + } + } + + /** + * Find the _Fields constant that matches fieldId, throwing an exception + * if it is not found. + */ + public static _Fields findByThriftIdOrThrow(int fieldId) { + _Fields fields = findByThriftId(fieldId); + if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!"); + return fields; + } + + /** + * Find the _Fields constant that matches name, or null if its not found. + */ + public static _Fields findByName(String name) { + return byName.get(name); + } + + private final short _thriftId; + private final String _fieldName; + + _Fields(short thriftId, String fieldName) { + _thriftId = thriftId; + _fieldName = fieldName; + } + + public short getThriftFieldId() { + return _thriftId; + } + + public String getFieldName() { + return _fieldName; + } + } + + // isset id assignments + public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap; + static { + Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class); + tmpMap.put(_Fields.REQUEST, new org.apache.thrift.meta_data.FieldMetaData("request", org.apache.thrift.TFieldRequirementType.DEFAULT, + new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, HelloRequest.class))); + metaDataMap = Collections.unmodifiableMap(tmpMap); + org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(sayHello_args.class, metaDataMap); + } + + public sayHello_args() { + } + + public sayHello_args( + HelloRequest request) + { + this(); + this.request = request; + } + + /** + * Performs a deep copy on other. + */ + public sayHello_args(sayHello_args other) { + if (other.isSetRequest()) { + this.request = new HelloRequest(other.request); + } + } + + public sayHello_args deepCopy() { + return new sayHello_args(this); + } + + @Override + public void clear() { + this.request = null; + } + + public HelloRequest getRequest() { + return this.request; + } + + public sayHello_args setRequest(HelloRequest request) { + this.request = request; + return this; + } + + public void unsetRequest() { + this.request = null; + } + + /** Returns true if field request is set (has been assigned a value) and false otherwise */ + public boolean isSetRequest() { + return this.request != null; + } + + public void setRequestIsSet(boolean value) { + if (!value) { + this.request = null; + } + } + + public void setFieldValue(_Fields field, Object value) { + switch (field) { + case REQUEST: + if (value == null) { + unsetRequest(); + } else { + setRequest((HelloRequest)value); + } + break; + + } + } + + public Object getFieldValue(_Fields field) { + switch (field) { + case REQUEST: + return getRequest(); + + } + throw new IllegalStateException(); + } + + /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */ + public boolean isSet(_Fields field) { + if (field == null) { + throw new IllegalArgumentException(); + } + + switch (field) { + case REQUEST: + return isSetRequest(); + } + throw new IllegalStateException(); + } + + @Override + public boolean equals(Object that) { + if (that == null) + return false; + if (that instanceof sayHello_args) + return this.equals((sayHello_args)that); + return false; + } + + public boolean equals(sayHello_args that) { + if (that == null) + return false; + + boolean this_present_request = true && this.isSetRequest(); + boolean that_present_request = true && that.isSetRequest(); + if (this_present_request || that_present_request) { + if (!(this_present_request && that_present_request)) + return false; + if (!this.request.equals(that.request)) + return false; + } + + return true; + } + + @Override + public int hashCode() { + int hashCode = 1; + + hashCode = hashCode * 8191 + ((isSetRequest()) ? 131071 : 524287); + if (isSetRequest()) + hashCode = hashCode * 8191 + request.hashCode(); + + return hashCode; + } + + @Override + public int compareTo(sayHello_args other) { + if (!getClass().equals(other.getClass())) { + return getClass().getName().compareTo(other.getClass().getName()); + } + + int lastComparison = 0; + + lastComparison = Boolean.valueOf(isSetRequest()).compareTo(other.isSetRequest()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetRequest()) { + lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.request, other.request); + if (lastComparison != 0) { + return lastComparison; + } + } + return 0; + } + + public _Fields fieldForId(int fieldId) { + return _Fields.findByThriftId(fieldId); + } + + public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException { + scheme(iprot).read(iprot, this); + } + + public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException { + scheme(oprot).write(oprot, this); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder("sayHello_args("); + boolean first = true; + + sb.append("request:"); + if (this.request == null) { + sb.append("null"); + } else { + sb.append(this.request); + } + first = false; + sb.append(")"); + return sb.toString(); + } + + public void validate() throws org.apache.thrift.TException { + // check for required fields + // check for sub-struct validity + if (request != null) { + request.validate(); + } + } + + private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException { + try { + write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out))); + } catch (org.apache.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException { + try { + read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in))); + } catch (org.apache.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private static class sayHello_argsStandardSchemeFactory implements SchemeFactory { + public sayHello_argsStandardScheme getScheme() { + return new sayHello_argsStandardScheme(); + } + } + + private static class sayHello_argsStandardScheme extends StandardScheme { + + public void read(org.apache.thrift.protocol.TProtocol iprot, sayHello_args struct) throws org.apache.thrift.TException { + org.apache.thrift.protocol.TField schemeField; + iprot.readStructBegin(); + while (true) + { + schemeField = iprot.readFieldBegin(); + if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { + break; + } + switch (schemeField.id) { + case 1: // REQUEST + if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) { + struct.request = new HelloRequest(); + struct.request.read(iprot); + struct.setRequestIsSet(true); + } else { + org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + default: + org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + + // check for required fields of primitive type, which can't be checked in the validate method + struct.validate(); + } + + public void write(org.apache.thrift.protocol.TProtocol oprot, sayHello_args struct) throws org.apache.thrift.TException { + struct.validate(); + + oprot.writeStructBegin(STRUCT_DESC); + if (struct.request != null) { + oprot.writeFieldBegin(REQUEST_FIELD_DESC); + struct.request.write(oprot); + oprot.writeFieldEnd(); + } + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + } + + private static class sayHello_argsTupleSchemeFactory implements SchemeFactory { + public sayHello_argsTupleScheme getScheme() { + return new sayHello_argsTupleScheme(); + } + } + + private static class sayHello_argsTupleScheme extends TupleScheme { + + @Override + public void write(org.apache.thrift.protocol.TProtocol prot, sayHello_args struct) throws org.apache.thrift.TException { + TTupleProtocol oprot = (TTupleProtocol) prot; + BitSet optionals = new BitSet(); + if (struct.isSetRequest()) { + optionals.set(0); + } + oprot.writeBitSet(optionals, 1); + if (struct.isSetRequest()) { + struct.request.write(oprot); + } + } + + @Override + public void read(org.apache.thrift.protocol.TProtocol prot, sayHello_args struct) throws org.apache.thrift.TException { + TTupleProtocol iprot = (TTupleProtocol) prot; + BitSet incoming = iprot.readBitSet(1); + if (incoming.get(0)) { + struct.request = new HelloRequest(); + struct.request.read(iprot); + struct.setRequestIsSet(true); + } + } + } + + private static S scheme(org.apache.thrift.protocol.TProtocol proto) { + return (StandardScheme.class.equals(proto.getScheme()) ? STANDARD_SCHEME_FACTORY : TUPLE_SCHEME_FACTORY).getScheme(); + } + } + + public static class sayHello_result implements org.apache.thrift.TBase, java.io.Serializable, Cloneable, Comparable { + private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("sayHello_result"); + + private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.STRUCT, (short)0); + + private static final SchemeFactory STANDARD_SCHEME_FACTORY = new sayHello_resultStandardSchemeFactory(); + private static final SchemeFactory TUPLE_SCHEME_FACTORY = new sayHello_resultTupleSchemeFactory(); + + public HelloResponse success; // required + + /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ + public enum _Fields implements org.apache.thrift.TFieldIdEnum { + SUCCESS((short)0, "success"); + + private static final Map byName = new HashMap(); + + static { + for (_Fields field : EnumSet.allOf(_Fields.class)) { + byName.put(field.getFieldName(), field); + } + } + + /** + * Find the _Fields constant that matches fieldId, or null if its not found. + */ + public static _Fields findByThriftId(int fieldId) { + switch(fieldId) { + case 0: // SUCCESS + return SUCCESS; + default: + return null; + } + } + + /** + * Find the _Fields constant that matches fieldId, throwing an exception + * if it is not found. + */ + public static _Fields findByThriftIdOrThrow(int fieldId) { + _Fields fields = findByThriftId(fieldId); + if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!"); + return fields; + } + + /** + * Find the _Fields constant that matches name, or null if its not found. + */ + public static _Fields findByName(String name) { + return byName.get(name); + } + + private final short _thriftId; + private final String _fieldName; + + _Fields(short thriftId, String fieldName) { + _thriftId = thriftId; + _fieldName = fieldName; + } + + public short getThriftFieldId() { + return _thriftId; + } + + public String getFieldName() { + return _fieldName; + } + } + + // isset id assignments + public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap; + static { + Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class); + tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, + new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, HelloResponse.class))); + metaDataMap = Collections.unmodifiableMap(tmpMap); + org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(sayHello_result.class, metaDataMap); + } + + public sayHello_result() { + } + + public sayHello_result( + HelloResponse success) + { + this(); + this.success = success; + } + + /** + * Performs a deep copy on other. + */ + public sayHello_result(sayHello_result other) { + if (other.isSetSuccess()) { + this.success = new HelloResponse(other.success); + } + } + + public sayHello_result deepCopy() { + return new sayHello_result(this); + } + + @Override + public void clear() { + this.success = null; + } + + public HelloResponse getSuccess() { + return this.success; + } + + public sayHello_result setSuccess(HelloResponse success) { + this.success = success; + return this; + } + + public void unsetSuccess() { + this.success = null; + } + + /** Returns true if field success is set (has been assigned a value) and false otherwise */ + public boolean isSetSuccess() { + return this.success != null; + } + + public void setSuccessIsSet(boolean value) { + if (!value) { + this.success = null; + } + } + + public void setFieldValue(_Fields field, Object value) { + switch (field) { + case SUCCESS: + if (value == null) { + unsetSuccess(); + } else { + setSuccess((HelloResponse)value); + } + break; + + } + } + + public Object getFieldValue(_Fields field) { + switch (field) { + case SUCCESS: + return getSuccess(); + + } + throw new IllegalStateException(); + } + + /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */ + public boolean isSet(_Fields field) { + if (field == null) { + throw new IllegalArgumentException(); + } + + switch (field) { + case SUCCESS: + return isSetSuccess(); + } + throw new IllegalStateException(); + } + + @Override + public boolean equals(Object that) { + if (that == null) + return false; + if (that instanceof sayHello_result) + return this.equals((sayHello_result)that); + return false; + } + + public boolean equals(sayHello_result that) { + if (that == null) + return false; + + boolean this_present_success = true && this.isSetSuccess(); + boolean that_present_success = true && that.isSetSuccess(); + if (this_present_success || that_present_success) { + if (!(this_present_success && that_present_success)) + return false; + if (!this.success.equals(that.success)) + return false; + } + + return true; + } + + @Override + public int hashCode() { + int hashCode = 1; + + hashCode = hashCode * 8191 + ((isSetSuccess()) ? 131071 : 524287); + if (isSetSuccess()) + hashCode = hashCode * 8191 + success.hashCode(); + + return hashCode; + } + + @Override + public int compareTo(sayHello_result other) { + if (!getClass().equals(other.getClass())) { + return getClass().getName().compareTo(other.getClass().getName()); + } + + int lastComparison = 0; + + lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetSuccess()) { + lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success); + if (lastComparison != 0) { + return lastComparison; + } + } + return 0; + } + + public _Fields fieldForId(int fieldId) { + return _Fields.findByThriftId(fieldId); + } + + public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException { + scheme(iprot).read(iprot, this); + } + + public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException { + scheme(oprot).write(oprot, this); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder("sayHello_result("); + boolean first = true; + + sb.append("success:"); + if (this.success == null) { + sb.append("null"); + } else { + sb.append(this.success); + } + first = false; + sb.append(")"); + return sb.toString(); + } + + public void validate() throws org.apache.thrift.TException { + // check for required fields + // check for sub-struct validity + if (success != null) { + success.validate(); + } + } + + private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException { + try { + write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out))); + } catch (org.apache.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException { + try { + read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in))); + } catch (org.apache.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private static class sayHello_resultStandardSchemeFactory implements SchemeFactory { + public sayHello_resultStandardScheme getScheme() { + return new sayHello_resultStandardScheme(); + } + } + + private static class sayHello_resultStandardScheme extends StandardScheme { + + public void read(org.apache.thrift.protocol.TProtocol iprot, sayHello_result struct) throws org.apache.thrift.TException { + org.apache.thrift.protocol.TField schemeField; + iprot.readStructBegin(); + while (true) + { + schemeField = iprot.readFieldBegin(); + if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { + break; + } + switch (schemeField.id) { + case 0: // SUCCESS + if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) { + struct.success = new HelloResponse(); + struct.success.read(iprot); + struct.setSuccessIsSet(true); + } else { + org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + default: + org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + + // check for required fields of primitive type, which can't be checked in the validate method + struct.validate(); + } + + public void write(org.apache.thrift.protocol.TProtocol oprot, sayHello_result struct) throws org.apache.thrift.TException { + struct.validate(); + + oprot.writeStructBegin(STRUCT_DESC); + if (struct.success != null) { + oprot.writeFieldBegin(SUCCESS_FIELD_DESC); + struct.success.write(oprot); + oprot.writeFieldEnd(); + } + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + } + + private static class sayHello_resultTupleSchemeFactory implements SchemeFactory { + public sayHello_resultTupleScheme getScheme() { + return new sayHello_resultTupleScheme(); + } + } + + private static class sayHello_resultTupleScheme extends TupleScheme { + + @Override + public void write(org.apache.thrift.protocol.TProtocol prot, sayHello_result struct) throws org.apache.thrift.TException { + TTupleProtocol oprot = (TTupleProtocol) prot; + BitSet optionals = new BitSet(); + if (struct.isSetSuccess()) { + optionals.set(0); + } + oprot.writeBitSet(optionals, 1); + if (struct.isSetSuccess()) { + struct.success.write(oprot); + } + } + + @Override + public void read(org.apache.thrift.protocol.TProtocol prot, sayHello_result struct) throws org.apache.thrift.TException { + TTupleProtocol iprot = (TTupleProtocol) prot; + BitSet incoming = iprot.readBitSet(1); + if (incoming.get(0)) { + struct.success = new HelloResponse(); + struct.success.read(iprot); + struct.setSuccessIsSet(true); + } + } + } + + private static S scheme(org.apache.thrift.protocol.TProtocol proto) { + return (StandardScheme.class.equals(proto.getScheme()) ? STANDARD_SCHEME_FACTORY : TUPLE_SCHEME_FACTORY).getScheme(); + } + } + + public static final io.grpc.MethodDescriptor METHOD_sayHello = + io.grpc.MethodDescriptor.create( + io.grpc.MethodDescriptor.MethodType.UNARY, + generateFullMethodName("io.grpc.examples.thrift.helloworld.Greeter" , "sayHello"), + io.grpc.thrift.ThriftUtils.marshaller( + new ThriftMessageFactory( ARG_IN_METHOD_sayHello)), + io.grpc.thrift.ThriftUtils.marshaller( + new ThriftMessageFactory( ARG_OUT_METHOD_sayHello))); + + public static GreeterStub newStub(io.grpc.Channel channel) { + return new GreeterStub(channel); + } + + public static class GreeterStub extends io.grpc.stub.AbstractStub + implements Greeter{ + private GreeterStub(io.grpc.Channel channel) { + super(channel); + } + + private GreeterStub(io.grpc.Channel channel, + io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected GreeterStub build(io.grpc.Channel channel, + io.grpc.CallOptions callOptions) { + return new GreeterStub(channel, callOptions); + } + + @java.lang.Override + public void sayHello(sayHello_args request, + io.grpc.stub.StreamObserver responseObserver) { + asyncUnaryCall( + getChannel().newCall(METHOD_sayHello, getCallOptions()), request, responseObserver); + } + + } + + public static GreeterBlockingStub newBlockingStub( + io.grpc.Channel channel) { + return new GreeterBlockingStub(channel); + } + + @java.lang.Deprecated public static interface GreeterBlockingClient { + public sayHello_result sayHello(sayHello_args request); + + } + + public static class GreeterBlockingStub extends io.grpc.stub.AbstractStub + implements GreeterBlockingClient { + private GreeterBlockingStub(io.grpc.Channel channel) { + super(channel); + } + + private GreeterBlockingStub(io.grpc.Channel channel, + io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected GreeterBlockingStub build(io.grpc.Channel channel, + io.grpc.CallOptions callOptions) { + return new GreeterBlockingStub(channel, callOptions); + } + + @java.lang.Override + public sayHello_result sayHello(sayHello_args request) { + return blockingUnaryCall( + getChannel(), METHOD_sayHello, getCallOptions(), request); + } + + } + + public static GreeterFutureStub newFutureStub( + io.grpc.Channel channel) { + return new GreeterFutureStub(channel); + } + + @java.lang.Deprecated public static interface GreeterFutureClient { + public com.google.common.util.concurrent.ListenableFuture sayHello( + sayHello_args request); + + } + + public static class GreeterFutureStub extends io.grpc.stub.AbstractStub + implements GreeterFutureClient { + private GreeterFutureStub(io.grpc.Channel channel) { + super(channel); + } + + private GreeterFutureStub(io.grpc.Channel channel, + io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected GreeterFutureStub build(io.grpc.Channel channel, + io.grpc.CallOptions callOptions) { + return new GreeterFutureStub(channel, callOptions); + } + + @java.lang.Override + public com.google.common.util.concurrent.ListenableFuture sayHello( + sayHello_args request) { + return futureUnaryCall( + getChannel().newCall(METHOD_sayHello, getCallOptions()), request); + } + + } + + private static final int METHODID_sayHello = 0; + + private static class MethodHandlers implements + io.grpc.stub.ServerCalls.UnaryMethod, + io.grpc.stub.ServerCalls.ServerStreamingMethod, + io.grpc.stub.ServerCalls.ClientStreamingMethod, + io.grpc.stub.ServerCalls.BidiStreamingMethod { + private final Greeter serviceImpl; + private final int methodId; + + public MethodHandlers(Greeter serviceImpl, int methodId) { + this.serviceImpl = serviceImpl; + this.methodId = methodId; + } + + @java.lang.Override + @java.lang.SuppressWarnings("unchecked") + public void invoke(Req request, io.grpc.stub.StreamObserver responseObserver) { + switch (methodId) { + case METHODID_sayHello: + serviceImpl.sayHello((sayHello_args) request, + (io.grpc.stub.StreamObserver) responseObserver); + break; + + default: + throw new AssertionError(); + } + } + + @java.lang.Override + @java.lang.SuppressWarnings("unchecked") + public io.grpc.stub.StreamObserver invoke( + io.grpc.stub.StreamObserver responseObserver) { + switch (methodId) { + default: + throw new AssertionError(); + } + } + + } + + public static io.grpc.ServiceDescriptor getServiceDescriptor() { + return new io.grpc.ServiceDescriptor(SERVICE_NAME , + METHOD_sayHello); + } + + @java.lang.Deprecated public static io.grpc.ServerServiceDefinition bindService( + final Greeter serviceImpl) { + return io.grpc.ServerServiceDefinition.builder(getServiceDescriptor()) + .addMethod( + METHOD_sayHello, + asyncUnaryCall( + new MethodHandlers< + sayHello_args, + sayHello_result>( + serviceImpl, METHODID_sayHello))) + .build(); + } + +} diff --git a/examples/thrift/src/generated/main/java/io/grpc/examples/thrift/helloworld/HelloRequest.java b/examples/thrift/src/generated/main/java/io/grpc/examples/thrift/helloworld/HelloRequest.java new file mode 100644 index 0000000000..8c4646586f --- /dev/null +++ b/examples/thrift/src/generated/main/java/io/grpc/examples/thrift/helloworld/HelloRequest.java @@ -0,0 +1,395 @@ +/** + * Autogenerated by Thrift Compiler (1.0.0-dev) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +package io.grpc.examples.thrift.helloworld; + +import org.apache.thrift.scheme.IScheme; +import org.apache.thrift.scheme.SchemeFactory; +import org.apache.thrift.scheme.StandardScheme; + +import org.apache.thrift.scheme.TupleScheme; +import org.apache.thrift.protocol.TTupleProtocol; +import org.apache.thrift.protocol.TProtocolException; +import org.apache.thrift.EncodingUtils; +import org.apache.thrift.server.AbstractNonblockingServer.*; +import java.util.List; +import java.util.ArrayList; +import java.util.Map; +import java.util.HashMap; +import java.util.EnumMap; +import java.util.Set; +import java.util.HashSet; +import java.util.EnumSet; +import java.util.Collections; +import java.util.BitSet; +import java.nio.ByteBuffer; +import java.util.Arrays; +import javax.annotation.Generated; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@SuppressWarnings({"cast", "rawtypes", "serial", "unchecked", "unused"}) +@Generated(value = "Autogenerated by Thrift Compiler (1.0.0-dev)", date = "2016-07-21") +public class HelloRequest implements org.apache.thrift.TBase, java.io.Serializable, Cloneable, Comparable { + private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("HelloRequest"); + + private static final org.apache.thrift.protocol.TField NAME_FIELD_DESC = new org.apache.thrift.protocol.TField("name", org.apache.thrift.protocol.TType.STRING, (short)1); + + private static final SchemeFactory STANDARD_SCHEME_FACTORY = new HelloRequestStandardSchemeFactory(); + private static final SchemeFactory TUPLE_SCHEME_FACTORY = new HelloRequestTupleSchemeFactory(); + + public String name; // required + + /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ + public enum _Fields implements org.apache.thrift.TFieldIdEnum { + NAME((short)1, "name"); + + private static final Map byName = new HashMap(); + + static { + for (_Fields field : EnumSet.allOf(_Fields.class)) { + byName.put(field.getFieldName(), field); + } + } + + /** + * Find the _Fields constant that matches fieldId, or null if its not found. + */ + public static _Fields findByThriftId(int fieldId) { + switch(fieldId) { + case 1: // NAME + return NAME; + default: + return null; + } + } + + /** + * Find the _Fields constant that matches fieldId, throwing an exception + * if it is not found. + */ + public static _Fields findByThriftIdOrThrow(int fieldId) { + _Fields fields = findByThriftId(fieldId); + if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!"); + return fields; + } + + /** + * Find the _Fields constant that matches name, or null if its not found. + */ + public static _Fields findByName(String name) { + return byName.get(name); + } + + private final short _thriftId; + private final String _fieldName; + + _Fields(short thriftId, String fieldName) { + _thriftId = thriftId; + _fieldName = fieldName; + } + + public short getThriftFieldId() { + return _thriftId; + } + + public String getFieldName() { + return _fieldName; + } + } + + // isset id assignments + public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap; + static { + Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class); + tmpMap.put(_Fields.NAME, new org.apache.thrift.meta_data.FieldMetaData("name", org.apache.thrift.TFieldRequirementType.DEFAULT, + new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING))); + metaDataMap = Collections.unmodifiableMap(tmpMap); + org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(HelloRequest.class, metaDataMap); + } + + public HelloRequest() { + } + + public HelloRequest( + String name) + { + this(); + this.name = name; + } + + /** + * Performs a deep copy on other. + */ + public HelloRequest(HelloRequest other) { + if (other.isSetName()) { + this.name = other.name; + } + } + + public HelloRequest deepCopy() { + return new HelloRequest(this); + } + + @Override + public void clear() { + this.name = null; + } + + public String getName() { + return this.name; + } + + public HelloRequest setName(String name) { + this.name = name; + return this; + } + + public void unsetName() { + this.name = null; + } + + /** Returns true if field name is set (has been assigned a value) and false otherwise */ + public boolean isSetName() { + return this.name != null; + } + + public void setNameIsSet(boolean value) { + if (!value) { + this.name = null; + } + } + + public void setFieldValue(_Fields field, Object value) { + switch (field) { + case NAME: + if (value == null) { + unsetName(); + } else { + setName((String)value); + } + break; + + } + } + + public Object getFieldValue(_Fields field) { + switch (field) { + case NAME: + return getName(); + + } + throw new IllegalStateException(); + } + + /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */ + public boolean isSet(_Fields field) { + if (field == null) { + throw new IllegalArgumentException(); + } + + switch (field) { + case NAME: + return isSetName(); + } + throw new IllegalStateException(); + } + + @Override + public boolean equals(Object that) { + if (that == null) + return false; + if (that instanceof HelloRequest) + return this.equals((HelloRequest)that); + return false; + } + + public boolean equals(HelloRequest that) { + if (that == null) + return false; + + boolean this_present_name = true && this.isSetName(); + boolean that_present_name = true && that.isSetName(); + if (this_present_name || that_present_name) { + if (!(this_present_name && that_present_name)) + return false; + if (!this.name.equals(that.name)) + return false; + } + + return true; + } + + @Override + public int hashCode() { + int hashCode = 1; + + hashCode = hashCode * 8191 + ((isSetName()) ? 131071 : 524287); + if (isSetName()) + hashCode = hashCode * 8191 + name.hashCode(); + + return hashCode; + } + + @Override + public int compareTo(HelloRequest other) { + if (!getClass().equals(other.getClass())) { + return getClass().getName().compareTo(other.getClass().getName()); + } + + int lastComparison = 0; + + lastComparison = Boolean.valueOf(isSetName()).compareTo(other.isSetName()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetName()) { + lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.name, other.name); + if (lastComparison != 0) { + return lastComparison; + } + } + return 0; + } + + public _Fields fieldForId(int fieldId) { + return _Fields.findByThriftId(fieldId); + } + + public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException { + scheme(iprot).read(iprot, this); + } + + public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException { + scheme(oprot).write(oprot, this); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder("HelloRequest("); + boolean first = true; + + sb.append("name:"); + if (this.name == null) { + sb.append("null"); + } else { + sb.append(this.name); + } + first = false; + sb.append(")"); + return sb.toString(); + } + + public void validate() throws org.apache.thrift.TException { + // check for required fields + // check for sub-struct validity + } + + private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException { + try { + write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out))); + } catch (org.apache.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException { + try { + read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in))); + } catch (org.apache.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private static class HelloRequestStandardSchemeFactory implements SchemeFactory { + public HelloRequestStandardScheme getScheme() { + return new HelloRequestStandardScheme(); + } + } + + private static class HelloRequestStandardScheme extends StandardScheme { + + public void read(org.apache.thrift.protocol.TProtocol iprot, HelloRequest struct) throws org.apache.thrift.TException { + org.apache.thrift.protocol.TField schemeField; + iprot.readStructBegin(); + while (true) + { + schemeField = iprot.readFieldBegin(); + if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { + break; + } + switch (schemeField.id) { + case 1: // NAME + if (schemeField.type == org.apache.thrift.protocol.TType.STRING) { + struct.name = iprot.readString(); + struct.setNameIsSet(true); + } else { + org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + default: + org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + + // check for required fields of primitive type, which can't be checked in the validate method + struct.validate(); + } + + public void write(org.apache.thrift.protocol.TProtocol oprot, HelloRequest struct) throws org.apache.thrift.TException { + struct.validate(); + + oprot.writeStructBegin(STRUCT_DESC); + if (struct.name != null) { + oprot.writeFieldBegin(NAME_FIELD_DESC); + oprot.writeString(struct.name); + oprot.writeFieldEnd(); + } + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + } + + private static class HelloRequestTupleSchemeFactory implements SchemeFactory { + public HelloRequestTupleScheme getScheme() { + return new HelloRequestTupleScheme(); + } + } + + private static class HelloRequestTupleScheme extends TupleScheme { + + @Override + public void write(org.apache.thrift.protocol.TProtocol prot, HelloRequest struct) throws org.apache.thrift.TException { + TTupleProtocol oprot = (TTupleProtocol) prot; + BitSet optionals = new BitSet(); + if (struct.isSetName()) { + optionals.set(0); + } + oprot.writeBitSet(optionals, 1); + if (struct.isSetName()) { + oprot.writeString(struct.name); + } + } + + @Override + public void read(org.apache.thrift.protocol.TProtocol prot, HelloRequest struct) throws org.apache.thrift.TException { + TTupleProtocol iprot = (TTupleProtocol) prot; + BitSet incoming = iprot.readBitSet(1); + if (incoming.get(0)) { + struct.name = iprot.readString(); + struct.setNameIsSet(true); + } + } + } + + private static S scheme(org.apache.thrift.protocol.TProtocol proto) { + return (StandardScheme.class.equals(proto.getScheme()) ? STANDARD_SCHEME_FACTORY : TUPLE_SCHEME_FACTORY).getScheme(); + } +} + diff --git a/examples/thrift/src/generated/main/java/io/grpc/examples/thrift/helloworld/HelloResponse.java b/examples/thrift/src/generated/main/java/io/grpc/examples/thrift/helloworld/HelloResponse.java new file mode 100644 index 0000000000..17c295f3a0 --- /dev/null +++ b/examples/thrift/src/generated/main/java/io/grpc/examples/thrift/helloworld/HelloResponse.java @@ -0,0 +1,395 @@ +/** + * Autogenerated by Thrift Compiler (1.0.0-dev) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +package io.grpc.examples.thrift.helloworld; + +import org.apache.thrift.scheme.IScheme; +import org.apache.thrift.scheme.SchemeFactory; +import org.apache.thrift.scheme.StandardScheme; + +import org.apache.thrift.scheme.TupleScheme; +import org.apache.thrift.protocol.TTupleProtocol; +import org.apache.thrift.protocol.TProtocolException; +import org.apache.thrift.EncodingUtils; +import org.apache.thrift.server.AbstractNonblockingServer.*; +import java.util.List; +import java.util.ArrayList; +import java.util.Map; +import java.util.HashMap; +import java.util.EnumMap; +import java.util.Set; +import java.util.HashSet; +import java.util.EnumSet; +import java.util.Collections; +import java.util.BitSet; +import java.nio.ByteBuffer; +import java.util.Arrays; +import javax.annotation.Generated; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@SuppressWarnings({"cast", "rawtypes", "serial", "unchecked", "unused"}) +@Generated(value = "Autogenerated by Thrift Compiler (1.0.0-dev)", date = "2016-07-21") +public class HelloResponse implements org.apache.thrift.TBase, java.io.Serializable, Cloneable, Comparable { + private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("HelloResponse"); + + private static final org.apache.thrift.protocol.TField MESSAGE_FIELD_DESC = new org.apache.thrift.protocol.TField("message", org.apache.thrift.protocol.TType.STRING, (short)1); + + private static final SchemeFactory STANDARD_SCHEME_FACTORY = new HelloResponseStandardSchemeFactory(); + private static final SchemeFactory TUPLE_SCHEME_FACTORY = new HelloResponseTupleSchemeFactory(); + + public String message; // required + + /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ + public enum _Fields implements org.apache.thrift.TFieldIdEnum { + MESSAGE((short)1, "message"); + + private static final Map byName = new HashMap(); + + static { + for (_Fields field : EnumSet.allOf(_Fields.class)) { + byName.put(field.getFieldName(), field); + } + } + + /** + * Find the _Fields constant that matches fieldId, or null if its not found. + */ + public static _Fields findByThriftId(int fieldId) { + switch(fieldId) { + case 1: // MESSAGE + return MESSAGE; + default: + return null; + } + } + + /** + * Find the _Fields constant that matches fieldId, throwing an exception + * if it is not found. + */ + public static _Fields findByThriftIdOrThrow(int fieldId) { + _Fields fields = findByThriftId(fieldId); + if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!"); + return fields; + } + + /** + * Find the _Fields constant that matches name, or null if its not found. + */ + public static _Fields findByName(String name) { + return byName.get(name); + } + + private final short _thriftId; + private final String _fieldName; + + _Fields(short thriftId, String fieldName) { + _thriftId = thriftId; + _fieldName = fieldName; + } + + public short getThriftFieldId() { + return _thriftId; + } + + public String getFieldName() { + return _fieldName; + } + } + + // isset id assignments + public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap; + static { + Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class); + tmpMap.put(_Fields.MESSAGE, new org.apache.thrift.meta_data.FieldMetaData("message", org.apache.thrift.TFieldRequirementType.DEFAULT, + new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING))); + metaDataMap = Collections.unmodifiableMap(tmpMap); + org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(HelloResponse.class, metaDataMap); + } + + public HelloResponse() { + } + + public HelloResponse( + String message) + { + this(); + this.message = message; + } + + /** + * Performs a deep copy on other. + */ + public HelloResponse(HelloResponse other) { + if (other.isSetMessage()) { + this.message = other.message; + } + } + + public HelloResponse deepCopy() { + return new HelloResponse(this); + } + + @Override + public void clear() { + this.message = null; + } + + public String getMessage() { + return this.message; + } + + public HelloResponse setMessage(String message) { + this.message = message; + return this; + } + + public void unsetMessage() { + this.message = null; + } + + /** Returns true if field message is set (has been assigned a value) and false otherwise */ + public boolean isSetMessage() { + return this.message != null; + } + + public void setMessageIsSet(boolean value) { + if (!value) { + this.message = null; + } + } + + public void setFieldValue(_Fields field, Object value) { + switch (field) { + case MESSAGE: + if (value == null) { + unsetMessage(); + } else { + setMessage((String)value); + } + break; + + } + } + + public Object getFieldValue(_Fields field) { + switch (field) { + case MESSAGE: + return getMessage(); + + } + throw new IllegalStateException(); + } + + /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */ + public boolean isSet(_Fields field) { + if (field == null) { + throw new IllegalArgumentException(); + } + + switch (field) { + case MESSAGE: + return isSetMessage(); + } + throw new IllegalStateException(); + } + + @Override + public boolean equals(Object that) { + if (that == null) + return false; + if (that instanceof HelloResponse) + return this.equals((HelloResponse)that); + return false; + } + + public boolean equals(HelloResponse that) { + if (that == null) + return false; + + boolean this_present_message = true && this.isSetMessage(); + boolean that_present_message = true && that.isSetMessage(); + if (this_present_message || that_present_message) { + if (!(this_present_message && that_present_message)) + return false; + if (!this.message.equals(that.message)) + return false; + } + + return true; + } + + @Override + public int hashCode() { + int hashCode = 1; + + hashCode = hashCode * 8191 + ((isSetMessage()) ? 131071 : 524287); + if (isSetMessage()) + hashCode = hashCode * 8191 + message.hashCode(); + + return hashCode; + } + + @Override + public int compareTo(HelloResponse other) { + if (!getClass().equals(other.getClass())) { + return getClass().getName().compareTo(other.getClass().getName()); + } + + int lastComparison = 0; + + lastComparison = Boolean.valueOf(isSetMessage()).compareTo(other.isSetMessage()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetMessage()) { + lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.message, other.message); + if (lastComparison != 0) { + return lastComparison; + } + } + return 0; + } + + public _Fields fieldForId(int fieldId) { + return _Fields.findByThriftId(fieldId); + } + + public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException { + scheme(iprot).read(iprot, this); + } + + public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException { + scheme(oprot).write(oprot, this); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder("HelloResponse("); + boolean first = true; + + sb.append("message:"); + if (this.message == null) { + sb.append("null"); + } else { + sb.append(this.message); + } + first = false; + sb.append(")"); + return sb.toString(); + } + + public void validate() throws org.apache.thrift.TException { + // check for required fields + // check for sub-struct validity + } + + private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException { + try { + write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out))); + } catch (org.apache.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException { + try { + read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in))); + } catch (org.apache.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private static class HelloResponseStandardSchemeFactory implements SchemeFactory { + public HelloResponseStandardScheme getScheme() { + return new HelloResponseStandardScheme(); + } + } + + private static class HelloResponseStandardScheme extends StandardScheme { + + public void read(org.apache.thrift.protocol.TProtocol iprot, HelloResponse struct) throws org.apache.thrift.TException { + org.apache.thrift.protocol.TField schemeField; + iprot.readStructBegin(); + while (true) + { + schemeField = iprot.readFieldBegin(); + if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { + break; + } + switch (schemeField.id) { + case 1: // MESSAGE + if (schemeField.type == org.apache.thrift.protocol.TType.STRING) { + struct.message = iprot.readString(); + struct.setMessageIsSet(true); + } else { + org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + default: + org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + + // check for required fields of primitive type, which can't be checked in the validate method + struct.validate(); + } + + public void write(org.apache.thrift.protocol.TProtocol oprot, HelloResponse struct) throws org.apache.thrift.TException { + struct.validate(); + + oprot.writeStructBegin(STRUCT_DESC); + if (struct.message != null) { + oprot.writeFieldBegin(MESSAGE_FIELD_DESC); + oprot.writeString(struct.message); + oprot.writeFieldEnd(); + } + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + } + + private static class HelloResponseTupleSchemeFactory implements SchemeFactory { + public HelloResponseTupleScheme getScheme() { + return new HelloResponseTupleScheme(); + } + } + + private static class HelloResponseTupleScheme extends TupleScheme { + + @Override + public void write(org.apache.thrift.protocol.TProtocol prot, HelloResponse struct) throws org.apache.thrift.TException { + TTupleProtocol oprot = (TTupleProtocol) prot; + BitSet optionals = new BitSet(); + if (struct.isSetMessage()) { + optionals.set(0); + } + oprot.writeBitSet(optionals, 1); + if (struct.isSetMessage()) { + oprot.writeString(struct.message); + } + } + + @Override + public void read(org.apache.thrift.protocol.TProtocol prot, HelloResponse struct) throws org.apache.thrift.TException { + TTupleProtocol iprot = (TTupleProtocol) prot; + BitSet incoming = iprot.readBitSet(1); + if (incoming.get(0)) { + struct.message = iprot.readString(); + struct.setMessageIsSet(true); + } + } + } + + private static S scheme(org.apache.thrift.protocol.TProtocol proto) { + return (StandardScheme.class.equals(proto.getScheme()) ? STANDARD_SCHEME_FACTORY : TUPLE_SCHEME_FACTORY).getScheme(); + } +} + diff --git a/examples/thrift/src/main/java/io/grpc/examples/thrift/helloworld/HelloWorldClient.java b/examples/thrift/src/main/java/io/grpc/examples/thrift/helloworld/HelloWorldClient.java new file mode 100644 index 0000000000..5d89c43a78 --- /dev/null +++ b/examples/thrift/src/main/java/io/grpc/examples/thrift/helloworld/HelloWorldClient.java @@ -0,0 +1,89 @@ +/* + * Copyright 2016, Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package io.grpc.examples.thrift.helloworld; + +import io.grpc.ManagedChannel; +import io.grpc.ManagedChannelBuilder; +import io.grpc.StatusRuntimeException; + +import java.util.concurrent.TimeUnit; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** Simple client that requests a greeting from {@link HelloWorldServer}. */ +public class HelloWorldClient { + private static final Logger logger = Logger.getLogger(HelloWorldClient.class.getName()); + + private final ManagedChannel channel; + private final GreeterGrpc.GreeterBlockingStub blockingStub; + + public HelloWorldClient(String host, int port) { + channel = ManagedChannelBuilder.forAddress(host, port) + .usePlaintext(true) + .build(); + blockingStub = GreeterGrpc.newBlockingStub(channel); + } + + public void shutdown() throws InterruptedException { + channel.shutdown().awaitTermination(5, TimeUnit.SECONDS); + } + + /** Say Hello to Server. */ + public void greet(String name) { + logger.info("Will try to greet " + name + " ..."); + HelloRequest hellorequest = new HelloRequest(name); + GreeterGrpc.sayHello_args request = new GreeterGrpc.sayHello_args(hellorequest); + + GreeterGrpc.sayHello_result response; + try { + response = blockingStub.sayHello(request); + } catch (StatusRuntimeException e) { + logger.log(Level.WARNING, "RPC failed: {0}", e.getStatus()); + return; + } + logger.info("Greeting: " + response.success.message); + } + + /** Greet Server. */ + public static void main(String[] args) throws Exception { + HelloWorldClient client = new HelloWorldClient("localhost" , 50051); + try { + String user = "world"; + if (args.length > 0) { + user = args[0]; + } + client.greet(user); + } finally { + client.shutdown(); + } + } +} \ No newline at end of file diff --git a/examples/thrift/src/main/java/io/grpc/examples/thrift/helloworld/HelloWorldServer.java b/examples/thrift/src/main/java/io/grpc/examples/thrift/helloworld/HelloWorldServer.java new file mode 100644 index 0000000000..48da768ae5 --- /dev/null +++ b/examples/thrift/src/main/java/io/grpc/examples/thrift/helloworld/HelloWorldServer.java @@ -0,0 +1,93 @@ +/* + * Copyright 2016, Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package io.grpc.examples.thrift.helloworld; + +import io.grpc.Server; +import io.grpc.ServerBuilder; +import io.grpc.stub.StreamObserver; + +import java.io.IOException; +import java.util.logging.Logger; + +/** Server that manages startup/ shutdown of a Greeter server. */ +public class HelloWorldServer { + private static final Logger logger = Logger.getLogger(HelloWorldServer.class.getName()); + + /** Port on which the server should run. */ + private int port = 50051; + private Server server; + + private void start() throws IOException { + server = ServerBuilder.forPort(port) + .addService(new GreeterImpl()) + .build() + .start(); + logger.info("Server started, listening on "+ port); + Runtime.getRuntime().addShutdownHook(new Thread() { + @Override + public void run() { + System.err.println("*** Shutting down gRPC server since JVM is shutting down"); + HelloWorldServer.this.stop(); + System.err.println("*** Server shut down"); + } + }); + } + + private void stop() { + if (server != null) { + server.shutdown(); + } + } + + private void blockUntilShutdown() throws InterruptedException { + if (server != null) { + server.awaitTermination(); + } + } + + /** Main function to launch server from cmd. */ + public static void main(String[] args) throws IOException, InterruptedException { + final HelloWorldServer server = new HelloWorldServer(); + server.start(); + server.blockUntilShutdown(); + } + + private class GreeterImpl extends GreeterGrpc.GreeterImplBase { + @Override + public void sayHello(GreeterGrpc.sayHello_args req, StreamObserver responseObserver) { + GreeterGrpc.sayHello_result reply = new GreeterGrpc.sayHello_result(); + reply.success = new HelloResponse("Hello " + req.request.name); + responseObserver.onNext(reply); + responseObserver.onCompleted(); + } + } +} \ No newline at end of file diff --git a/examples/thrift/src/main/thrift/helloworld.thrift b/examples/thrift/src/main/thrift/helloworld.thrift new file mode 100644 index 0000000000..a042e563ea --- /dev/null +++ b/examples/thrift/src/main/thrift/helloworld.thrift @@ -0,0 +1,13 @@ +namespace java io.grpc.examples.thrift.helloworld + +struct HelloRequest { + 1:string name +} + +struct HelloResponse { + 1:string message +} + +service Greeter { + HelloResponse sayHello(1:HelloRequest request); +} diff --git a/settings.gradle b/settings.gradle index 42496c2eeb..6c7034ae17 100644 --- a/settings.gradle +++ b/settings.gradle @@ -13,6 +13,7 @@ include ":grpc-interop-testing" include ":grpc-all" include ":grpc-benchmarks" include ":grpc-services" +include ":grpc-thrift" project(':grpc-core').projectDir = "$rootDir/core" as File project(':grpc-stub').projectDir = "$rootDir/stub" as File @@ -28,6 +29,7 @@ project(':grpc-interop-testing').projectDir = "$rootDir/interop-testing" as File project(':grpc-all').projectDir = "$rootDir/all" as File project(':grpc-benchmarks').projectDir = "$rootDir/benchmarks" as File project(':grpc-services').projectDir = "$rootDir/services" as File +project(':grpc-thrift').projectDir = "$rootDir/thrift" as File if (settings.hasProperty('skipCodegen') && skipCodegen.toBoolean()) { println '*** Skipping the build of codegen and compilation of proto files because skipCodegen=true' diff --git a/thrift/build.gradle b/thrift/build.gradle new file mode 100644 index 0000000000..33e509ea91 --- /dev/null +++ b/thrift/build.gradle @@ -0,0 +1,29 @@ +description = 'gRPC: Thrift' + +dependencies { + compile project(':grpc-core'), + 'org.apache.thrift:libthrift:0.9.3' +} + + +String generatedSourcePath = "${projectDir}/src/generated" +project.sourceSets { + main { + java { + srcDir "${generatedSourcePath}/main/java" + srcDir "${generatedSourcePath}/main/grpc" + } + } + test { + java { + srcDir "${generatedSourcePath}/test/java" + srcDir "${generatedSourcePath}/test/grpc" + } + } +} + +idea { + module { + sourceDirs += file("${projectDir}/src/generated/test/java"); + } +} \ No newline at end of file diff --git a/thrift/src/generated/test/java/io/grpc/thrift/Message.java b/thrift/src/generated/test/java/io/grpc/thrift/Message.java new file mode 100644 index 0000000000..44c7908bd1 --- /dev/null +++ b/thrift/src/generated/test/java/io/grpc/thrift/Message.java @@ -0,0 +1,744 @@ +/** + * Autogenerated by Thrift Compiler (1.0.0-dev) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +package io.grpc.thrift; + +import org.apache.thrift.scheme.IScheme; +import org.apache.thrift.scheme.SchemeFactory; +import org.apache.thrift.scheme.StandardScheme; + +import org.apache.thrift.scheme.TupleScheme; +import org.apache.thrift.protocol.TTupleProtocol; +import org.apache.thrift.protocol.TProtocolException; +import org.apache.thrift.EncodingUtils; +import org.apache.thrift.server.AbstractNonblockingServer.*; +import java.util.List; +import java.util.ArrayList; +import java.util.Map; +import java.util.HashMap; +import java.util.EnumMap; +import java.util.Set; +import java.util.HashSet; +import java.util.EnumSet; +import java.util.Collections; +import java.util.BitSet; +import java.nio.ByteBuffer; +import java.util.Arrays; +import javax.annotation.Generated; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@SuppressWarnings({"cast", "rawtypes", "serial", "unchecked", "unused"}) +@Generated(value = "Autogenerated by Thrift Compiler (1.0.0-dev)", date = "2016-07-11") +public class Message implements org.apache.thrift.TBase, java.io.Serializable, Cloneable, Comparable { + private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("Message"); + + private static final org.apache.thrift.protocol.TField I_FIELD_DESC = new org.apache.thrift.protocol.TField("i", org.apache.thrift.protocol.TType.I32, (short)1); + private static final org.apache.thrift.protocol.TField B_FIELD_DESC = new org.apache.thrift.protocol.TField("b", org.apache.thrift.protocol.TType.BOOL, (short)2); + private static final org.apache.thrift.protocol.TField S_FIELD_DESC = new org.apache.thrift.protocol.TField("s", org.apache.thrift.protocol.TType.STRING, (short)3); + private static final org.apache.thrift.protocol.TField L_FIELD_DESC = new org.apache.thrift.protocol.TField("l", org.apache.thrift.protocol.TType.LIST, (short)4); + + private static final SchemeFactory STANDARD_SCHEME_FACTORY = new MessageStandardSchemeFactory(); + private static final SchemeFactory TUPLE_SCHEME_FACTORY = new MessageTupleSchemeFactory(); + + public int i; // required + public boolean b; // required + public String s; // required + public List l; // required + + /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ + public enum _Fields implements org.apache.thrift.TFieldIdEnum { + I((short)1, "i"), + B((short)2, "b"), + S((short)3, "s"), + L((short)4, "l"); + + private static final Map byName = new HashMap(); + + static { + for (_Fields field : EnumSet.allOf(_Fields.class)) { + byName.put(field.getFieldName(), field); + } + } + + /** + * Find the _Fields constant that matches fieldId, or null if its not found. + */ + public static _Fields findByThriftId(int fieldId) { + switch(fieldId) { + case 1: // I + return I; + case 2: // B + return B; + case 3: // S + return S; + case 4: // L + return L; + default: + return null; + } + } + + /** + * Find the _Fields constant that matches fieldId, throwing an exception + * if it is not found. + */ + public static _Fields findByThriftIdOrThrow(int fieldId) { + _Fields fields = findByThriftId(fieldId); + if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!"); + return fields; + } + + /** + * Find the _Fields constant that matches name, or null if its not found. + */ + public static _Fields findByName(String name) { + return byName.get(name); + } + + private final short _thriftId; + private final String _fieldName; + + _Fields(short thriftId, String fieldName) { + _thriftId = thriftId; + _fieldName = fieldName; + } + + public short getThriftFieldId() { + return _thriftId; + } + + public String getFieldName() { + return _fieldName; + } + } + + // isset id assignments + private static final int __I_ISSET_ID = 0; + private static final int __B_ISSET_ID = 1; + private byte __isset_bitfield = 0; + public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap; + static { + Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class); + tmpMap.put(_Fields.I, new org.apache.thrift.meta_data.FieldMetaData("i", org.apache.thrift.TFieldRequirementType.DEFAULT, + new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32))); + tmpMap.put(_Fields.B, new org.apache.thrift.meta_data.FieldMetaData("b", org.apache.thrift.TFieldRequirementType.DEFAULT, + new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.BOOL))); + tmpMap.put(_Fields.S, new org.apache.thrift.meta_data.FieldMetaData("s", org.apache.thrift.TFieldRequirementType.DEFAULT, + new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING))); + tmpMap.put(_Fields.L, new org.apache.thrift.meta_data.FieldMetaData("l", org.apache.thrift.TFieldRequirementType.DEFAULT, + new org.apache.thrift.meta_data.ListMetaData(org.apache.thrift.protocol.TType.LIST, + new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)))); + metaDataMap = Collections.unmodifiableMap(tmpMap); + org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(Message.class, metaDataMap); + } + + public Message() { + } + + public Message( + int i, + boolean b, + String s, + List l) + { + this(); + this.i = i; + setIIsSet(true); + this.b = b; + setBIsSet(true); + this.s = s; + this.l = l; + } + + /** + * Performs a deep copy on other. + */ + public Message(Message other) { + __isset_bitfield = other.__isset_bitfield; + this.i = other.i; + this.b = other.b; + if (other.isSetS()) { + this.s = other.s; + } + if (other.isSetL()) { + List __this__l = new ArrayList(other.l); + this.l = __this__l; + } + } + + public Message deepCopy() { + return new Message(this); + } + + @Override + public void clear() { + setIIsSet(false); + this.i = 0; + setBIsSet(false); + this.b = false; + this.s = null; + this.l = null; + } + + public int getI() { + return this.i; + } + + public Message setI(int i) { + this.i = i; + setIIsSet(true); + return this; + } + + public void unsetI() { + __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __I_ISSET_ID); + } + + /** Returns true if field i is set (has been assigned a value) and false otherwise */ + public boolean isSetI() { + return EncodingUtils.testBit(__isset_bitfield, __I_ISSET_ID); + } + + public void setIIsSet(boolean value) { + __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __I_ISSET_ID, value); + } + + public boolean isB() { + return this.b; + } + + public Message setB(boolean b) { + this.b = b; + setBIsSet(true); + return this; + } + + public void unsetB() { + __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __B_ISSET_ID); + } + + /** Returns true if field b is set (has been assigned a value) and false otherwise */ + public boolean isSetB() { + return EncodingUtils.testBit(__isset_bitfield, __B_ISSET_ID); + } + + public void setBIsSet(boolean value) { + __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __B_ISSET_ID, value); + } + + public String getS() { + return this.s; + } + + public Message setS(String s) { + this.s = s; + return this; + } + + public void unsetS() { + this.s = null; + } + + /** Returns true if field s is set (has been assigned a value) and false otherwise */ + public boolean isSetS() { + return this.s != null; + } + + public void setSIsSet(boolean value) { + if (!value) { + this.s = null; + } + } + + public int getLSize() { + return (this.l == null) ? 0 : this.l.size(); + } + + public java.util.Iterator getLIterator() { + return (this.l == null) ? null : this.l.iterator(); + } + + public void addToL(int elem) { + if (this.l == null) { + this.l = new ArrayList(); + } + this.l.add(elem); + } + + public List getL() { + return this.l; + } + + public Message setL(List l) { + this.l = l; + return this; + } + + public void unsetL() { + this.l = null; + } + + /** Returns true if field l is set (has been assigned a value) and false otherwise */ + public boolean isSetL() { + return this.l != null; + } + + public void setLIsSet(boolean value) { + if (!value) { + this.l = null; + } + } + + public void setFieldValue(_Fields field, Object value) { + switch (field) { + case I: + if (value == null) { + unsetI(); + } else { + setI((Integer)value); + } + break; + + case B: + if (value == null) { + unsetB(); + } else { + setB((Boolean)value); + } + break; + + case S: + if (value == null) { + unsetS(); + } else { + setS((String)value); + } + break; + + case L: + if (value == null) { + unsetL(); + } else { + setL((List)value); + } + break; + + } + } + + public Object getFieldValue(_Fields field) { + switch (field) { + case I: + return getI(); + + case B: + return isB(); + + case S: + return getS(); + + case L: + return getL(); + + } + throw new IllegalStateException(); + } + + /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */ + public boolean isSet(_Fields field) { + if (field == null) { + throw new IllegalArgumentException(); + } + + switch (field) { + case I: + return isSetI(); + case B: + return isSetB(); + case S: + return isSetS(); + case L: + return isSetL(); + } + throw new IllegalStateException(); + } + + @Override + public boolean equals(Object that) { + if (that == null) + return false; + if (that instanceof Message) + return this.equals((Message)that); + return false; + } + + public boolean equals(Message that) { + if (that == null) + return false; + + boolean this_present_i = true; + boolean that_present_i = true; + if (this_present_i || that_present_i) { + if (!(this_present_i && that_present_i)) + return false; + if (this.i != that.i) + return false; + } + + boolean this_present_b = true; + boolean that_present_b = true; + if (this_present_b || that_present_b) { + if (!(this_present_b && that_present_b)) + return false; + if (this.b != that.b) + return false; + } + + boolean this_present_s = true && this.isSetS(); + boolean that_present_s = true && that.isSetS(); + if (this_present_s || that_present_s) { + if (!(this_present_s && that_present_s)) + return false; + if (!this.s.equals(that.s)) + return false; + } + + boolean this_present_l = true && this.isSetL(); + boolean that_present_l = true && that.isSetL(); + if (this_present_l || that_present_l) { + if (!(this_present_l && that_present_l)) + return false; + if (!this.l.equals(that.l)) + return false; + } + + return true; + } + + @Override + public int hashCode() { + int hashCode = 1; + + hashCode = hashCode * 8191 + i; + + hashCode = hashCode * 8191 + ((b) ? 131071 : 524287); + + hashCode = hashCode * 8191 + ((isSetS()) ? 131071 : 524287); + if (isSetS()) + hashCode = hashCode * 8191 + s.hashCode(); + + hashCode = hashCode * 8191 + ((isSetL()) ? 131071 : 524287); + if (isSetL()) + hashCode = hashCode * 8191 + l.hashCode(); + + return hashCode; + } + + @Override + public int compareTo(Message other) { + if (!getClass().equals(other.getClass())) { + return getClass().getName().compareTo(other.getClass().getName()); + } + + int lastComparison = 0; + + lastComparison = Boolean.valueOf(isSetI()).compareTo(other.isSetI()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetI()) { + lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.i, other.i); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = Boolean.valueOf(isSetB()).compareTo(other.isSetB()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetB()) { + lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.b, other.b); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = Boolean.valueOf(isSetS()).compareTo(other.isSetS()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetS()) { + lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.s, other.s); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = Boolean.valueOf(isSetL()).compareTo(other.isSetL()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetL()) { + lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.l, other.l); + if (lastComparison != 0) { + return lastComparison; + } + } + return 0; + } + + public _Fields fieldForId(int fieldId) { + return _Fields.findByThriftId(fieldId); + } + + public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException { + scheme(iprot).read(iprot, this); + } + + public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException { + scheme(oprot).write(oprot, this); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder("Message("); + boolean first = true; + + sb.append("i:"); + sb.append(this.i); + first = false; + if (!first) sb.append(", "); + sb.append("b:"); + sb.append(this.b); + first = false; + if (!first) sb.append(", "); + sb.append("s:"); + if (this.s == null) { + sb.append("null"); + } else { + sb.append(this.s); + } + first = false; + if (!first) sb.append(", "); + sb.append("l:"); + if (this.l == null) { + sb.append("null"); + } else { + sb.append(this.l); + } + first = false; + sb.append(")"); + return sb.toString(); + } + + public void validate() throws org.apache.thrift.TException { + // check for required fields + // check for sub-struct validity + } + + private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException { + try { + write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out))); + } catch (org.apache.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException { + try { + // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor. + __isset_bitfield = 0; + read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in))); + } catch (org.apache.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private static class MessageStandardSchemeFactory implements SchemeFactory { + public MessageStandardScheme getScheme() { + return new MessageStandardScheme(); + } + } + + private static class MessageStandardScheme extends StandardScheme { + + public void read(org.apache.thrift.protocol.TProtocol iprot, Message struct) throws org.apache.thrift.TException { + org.apache.thrift.protocol.TField schemeField; + iprot.readStructBegin(); + while (true) + { + schemeField = iprot.readFieldBegin(); + if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { + break; + } + switch (schemeField.id) { + case 1: // I + if (schemeField.type == org.apache.thrift.protocol.TType.I32) { + struct.i = iprot.readI32(); + struct.setIIsSet(true); + } else { + org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 2: // B + if (schemeField.type == org.apache.thrift.protocol.TType.BOOL) { + struct.b = iprot.readBool(); + struct.setBIsSet(true); + } else { + org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 3: // S + if (schemeField.type == org.apache.thrift.protocol.TType.STRING) { + struct.s = iprot.readString(); + struct.setSIsSet(true); + } else { + org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 4: // L + if (schemeField.type == org.apache.thrift.protocol.TType.LIST) { + { + org.apache.thrift.protocol.TList _list0 = iprot.readListBegin(); + struct.l = new ArrayList(_list0.size); + int _elem1; + for (int _i2 = 0; _i2 < _list0.size; ++_i2) + { + _elem1 = iprot.readI32(); + struct.l.add(_elem1); + } + iprot.readListEnd(); + } + struct.setLIsSet(true); + } else { + org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + default: + org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + + // check for required fields of primitive type, which can't be checked in the validate method + struct.validate(); + } + + public void write(org.apache.thrift.protocol.TProtocol oprot, Message struct) throws org.apache.thrift.TException { + struct.validate(); + + oprot.writeStructBegin(STRUCT_DESC); + oprot.writeFieldBegin(I_FIELD_DESC); + oprot.writeI32(struct.i); + oprot.writeFieldEnd(); + oprot.writeFieldBegin(B_FIELD_DESC); + oprot.writeBool(struct.b); + oprot.writeFieldEnd(); + if (struct.s != null) { + oprot.writeFieldBegin(S_FIELD_DESC); + oprot.writeString(struct.s); + oprot.writeFieldEnd(); + } + if (struct.l != null) { + oprot.writeFieldBegin(L_FIELD_DESC); + { + oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.I32, struct.l.size())); + for (int _iter3 : struct.l) + { + oprot.writeI32(_iter3); + } + oprot.writeListEnd(); + } + oprot.writeFieldEnd(); + } + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + } + + private static class MessageTupleSchemeFactory implements SchemeFactory { + public MessageTupleScheme getScheme() { + return new MessageTupleScheme(); + } + } + + private static class MessageTupleScheme extends TupleScheme { + + @Override + public void write(org.apache.thrift.protocol.TProtocol prot, Message struct) throws org.apache.thrift.TException { + TTupleProtocol oprot = (TTupleProtocol) prot; + BitSet optionals = new BitSet(); + if (struct.isSetI()) { + optionals.set(0); + } + if (struct.isSetB()) { + optionals.set(1); + } + if (struct.isSetS()) { + optionals.set(2); + } + if (struct.isSetL()) { + optionals.set(3); + } + oprot.writeBitSet(optionals, 4); + if (struct.isSetI()) { + oprot.writeI32(struct.i); + } + if (struct.isSetB()) { + oprot.writeBool(struct.b); + } + if (struct.isSetS()) { + oprot.writeString(struct.s); + } + if (struct.isSetL()) { + { + oprot.writeI32(struct.l.size()); + for (int _iter4 : struct.l) + { + oprot.writeI32(_iter4); + } + } + } + } + + @Override + public void read(org.apache.thrift.protocol.TProtocol prot, Message struct) throws org.apache.thrift.TException { + TTupleProtocol iprot = (TTupleProtocol) prot; + BitSet incoming = iprot.readBitSet(4); + if (incoming.get(0)) { + struct.i = iprot.readI32(); + struct.setIIsSet(true); + } + if (incoming.get(1)) { + struct.b = iprot.readBool(); + struct.setBIsSet(true); + } + if (incoming.get(2)) { + struct.s = iprot.readString(); + struct.setSIsSet(true); + } + if (incoming.get(3)) { + { + org.apache.thrift.protocol.TList _list5 = new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.I32, iprot.readI32()); + struct.l = new ArrayList(_list5.size); + int _elem6; + for (int _i7 = 0; _i7 < _list5.size; ++_i7) + { + _elem6 = iprot.readI32(); + struct.l.add(_elem6); + } + } + struct.setLIsSet(true); + } + } + } + + private static S scheme(org.apache.thrift.protocol.TProtocol proto) { + return (StandardScheme.class.equals(proto.getScheme()) ? STANDARD_SCHEME_FACTORY : TUPLE_SCHEME_FACTORY).getScheme(); + } +} + diff --git a/thrift/src/main/java/io/grpc/thrift/MessageFactory.java b/thrift/src/main/java/io/grpc/thrift/MessageFactory.java new file mode 100644 index 0000000000..13c0935709 --- /dev/null +++ b/thrift/src/main/java/io/grpc/thrift/MessageFactory.java @@ -0,0 +1,41 @@ +/* + * Copyright 2016, Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package io.grpc.thrift; + +import org.apache.thrift.TBase; + +/** + * Produce new Message Instances. Used by Marshaller to deserialize incoming messages. + */ +public interface MessageFactory> { + T newInstance(); +} diff --git a/thrift/src/main/java/io/grpc/thrift/ThriftInputStream.java b/thrift/src/main/java/io/grpc/thrift/ThriftInputStream.java new file mode 100644 index 0000000000..bbf8b54a7e --- /dev/null +++ b/thrift/src/main/java/io/grpc/thrift/ThriftInputStream.java @@ -0,0 +1,122 @@ +/* + * Copyright 2016, Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package io.grpc.thrift; + +import com.google.common.io.ByteStreams; + +import io.grpc.Drainable; +import io.grpc.KnownLength; +import io.grpc.Status; +import org.apache.thrift.TBase; +import org.apache.thrift.TException; +import org.apache.thrift.TSerializer; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import javax.annotation.Nullable; + +/** InputStream for Thrift. */ +final class ThriftInputStream extends InputStream implements Drainable, KnownLength { + + /** + * ThriftInput stream is initialized with a *message* , *serializer* + * *partial* is initially null. + */ + @Nullable private TBase message; + @Nullable private ByteArrayInputStream partial; + private final TSerializer serializer = new TSerializer(); + + /** Initialize message with @param message. */ + public ThriftInputStream(TBase message) { + this.message = message; + } + + @Override + public int drainTo(OutputStream target) throws IOException { + int written = 0; + if (message != null) { + try { + byte[] bytes = serializer.serialize(message); + written = bytes.length; + target.write(bytes); + message = null; + } catch (TException e) { + throw Status.INTERNAL.withDescription("failed to serialize thrift message") + .withCause(e).asRuntimeException(); + } + } else if (partial != null) { + written = (int) ByteStreams.copy(partial, target); + partial = null; + } else { + written = 0; + } + return written; + } + + @Override + public int read() throws IOException { + if (message != null) { + try { + partial = new ByteArrayInputStream(serializer.serialize(message)); + message = null; + } catch (TException e) { + throw Status.INTERNAL.withDescription("failed to serialize thrift message") + .withCause(e).asRuntimeException(); + } + } + if (partial != null) { + return partial.read(); + } + return -1; + } + + @Override + public int available() throws IOException { + if (message != null) { + try { + partial = new ByteArrayInputStream(serializer.serialize(message)); + message = null; + return partial.available(); + } catch (TException e) { + throw Status.INTERNAL.withDescription("failed to serialize thrift message") + .withCause(e).asRuntimeException(); + } + } else if (partial != null) { + return partial.available(); + } + return 0; + } + +} diff --git a/thrift/src/main/java/io/grpc/thrift/ThriftUtils.java b/thrift/src/main/java/io/grpc/thrift/ThriftUtils.java new file mode 100644 index 0000000000..e1a94949e5 --- /dev/null +++ b/thrift/src/main/java/io/grpc/thrift/ThriftUtils.java @@ -0,0 +1,111 @@ +/* + * Copyright 2016, Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package io.grpc.thrift; + +import io.grpc.Metadata; +import io.grpc.MethodDescriptor.Marshaller; +import io.grpc.Status; +import io.grpc.internal.IoUtils; +import org.apache.thrift.TBase; +import org.apache.thrift.TDeserializer; +import org.apache.thrift.TException; +import org.apache.thrift.TSerializer; + +import java.io.IOException; +import java.io.InputStream; + +public final class ThriftUtils { + + /** Create a {@code Marshaller} for thrift messages. */ + public static > Marshaller marshaller(final MessageFactory factory) { + + return new Marshaller() { + + @Override + public InputStream stream(T value) { + return new ThriftInputStream(value); + } + + @Override + public T parse(InputStream stream) { + try { + byte[] bytes = IoUtils.toByteArray(stream); + TDeserializer deserializer = new TDeserializer(); + T message = factory.newInstance(); + deserializer.deserialize(message, bytes); + return message; + } catch (TException e) { + throw Status.INTERNAL.withDescription("Invalid Stream") + .withCause(e).asRuntimeException(); + } catch (IOException e) { + throw Status.INTERNAL.withDescription("failed to read stream") + .withCause(e).asRuntimeException(); + } + } + }; + } + + /** Produce a metadata marshaller. */ + public static > Metadata.BinaryMarshaller metadataMarshaller( + final MessageFactory factory) { + return new Metadata.BinaryMarshaller() { + + @Override + public byte[] toBytes(T value) { + try { + TSerializer serializer = new TSerializer(); + return serializer.serialize(value); + } catch (TException e) { + throw Status.INTERNAL.withDescription("Error in serializing Thrift Message") + .withCause(e).asRuntimeException(); + } + } + + @Override + public T parseBytes(byte[] serialized) { + try { + TDeserializer deserializer = new TDeserializer(); + T message = factory.newInstance(); + deserializer.deserialize(message, serialized); + return message; + } catch (TException e) { + throw Status.INTERNAL.withDescription("Invalid thrift Byte Sequence") + .withCause(e).asRuntimeException(); + } + } + }; + } + + private ThriftUtils() { + } + +} diff --git a/thrift/src/test/java/io/grpc/thrift/ThriftUtilsTest.java b/thrift/src/test/java/io/grpc/thrift/ThriftUtilsTest.java new file mode 100644 index 0000000000..7b992ae4db --- /dev/null +++ b/thrift/src/test/java/io/grpc/thrift/ThriftUtilsTest.java @@ -0,0 +1,183 @@ +/* + * Copyright 2016, Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package io.grpc.thrift; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotSame; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import io.grpc.Drainable; +import io.grpc.Metadata; +import io.grpc.MethodDescriptor.Marshaller; +import io.grpc.Status; +import io.grpc.StatusRuntimeException; +import io.grpc.internal.IoUtils; +import org.apache.thrift.TException; +import org.apache.thrift.TSerializer; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Collections; + +/** Unit tests for {@link ThriftUtils}. */ +@RunWith(JUnit4.class) +public class ThriftUtilsTest { + private Marshaller marshaller = ThriftUtils.marshaller(new MessageFactory() { + @Override + public Message newInstance() { + return new Message(); + } + }); + + private Metadata.BinaryMarshaller metadataMarshaller = ThriftUtils.metadataMarshaller( + new MessageFactory() { + @Override + public Message newInstance() { + return new Message(); + } + }); + + @Test + public void testRoundTrip() { + Message m = new Message(); + m.i = 2; + m.b = true; + m.s = "string"; + Message m2 = marshaller.parse(marshaller.stream(m)); + assertNotSame(m, m2); + assertTrue(m.equals( m2 )); + } + + @Test + public void parseInvalid() throws Exception { + InputStream is = new ByteArrayInputStream(new byte[] {-127}); + try { + marshaller.parse(is); + fail("Expected exception"); + } catch (StatusRuntimeException ex) { + assertEquals(Status.Code.INTERNAL, ex.getStatus().getCode()); + assertTrue(ex.getCause() instanceof TException); + } + } + + @Test + public void testLarge() throws Exception { + Message m = new Message(); + // list size 80 MB + m.l = new ArrayList(Collections.nCopies(20 * 1024 * 1024, 1000000007)); + Message m2 = marshaller.parse(marshaller.stream(m)); + assertNotSame(m, m2); + assertEquals(m.l.size(), m2.l.size()); + } + + @Test + public void metadataMarshaller_roundtrip() { + Message m = new Message(); + m.i = 2; + assertEquals(m, metadataMarshaller.parseBytes(metadataMarshaller.toBytes(m))); + } + + @Test + public void metadataMarshaller_invalid() { + try { + metadataMarshaller.parseBytes(new byte[] {-127}); + fail("Expected exception"); + } catch (Exception ex) { + assertTrue(ex.getCause() instanceof TException); + } + } + + @Test + public void testAvailable() throws Exception { + Message m = new Message(); + m.i = 10; + InputStream is = marshaller.stream(m); + assertEquals(is.available(), new TSerializer().serialize(m).length); + is.read(); + assertEquals(is.available(), new TSerializer().serialize(m).length - 1); + while (is.read() != -1) {} + assertEquals(-1, is.read()); + assertEquals(0, is.available()); + } + + @Test + public void testDrainTo_all() throws Exception { + Message m = new Message(); + byte[] bytes = IoUtils.toByteArray(marshaller.stream(m)); + InputStream is = marshaller.stream(m); + Drainable d = (Drainable) is; + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + int drained = d.drainTo(baos); + assertEquals(baos.size(), drained); + assertArrayEquals(bytes, baos.toByteArray()); + assertEquals(0, is.available()); + } + + @Test + public void testDrainTo_partial() throws Exception { + Message m = new Message(); + final byte[] bytes; + { + InputStream is = marshaller.stream(m); + is.read(); + bytes = IoUtils.toByteArray(is); + } + InputStream is = marshaller.stream(m); + is.read(); + Drainable d = (Drainable) is; + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + int drained = d.drainTo(baos); + assertEquals(baos.size(), drained); + assertArrayEquals(bytes, baos.toByteArray()); + assertEquals(0, is.available()); + } + + @Test + public void testDrainTo_none() throws Exception { + Message m = new Message(); + byte[] bytes = IoUtils.toByteArray(marshaller.stream(m)); + InputStream is = marshaller.stream(m); + byte[] unused = IoUtils.toByteArray(is); + Drainable d = (Drainable) is; + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + assertEquals(0, d.drainTo(baos)); + assertArrayEquals(new byte[0], baos.toByteArray()); + assertEquals(0, is.available()); + } +} \ No newline at end of file diff --git a/thrift/src/test/thrift/messages.thrift b/thrift/src/test/thrift/messages.thrift new file mode 100644 index 0000000000..0f2f4323d3 --- /dev/null +++ b/thrift/src/test/thrift/messages.thrift @@ -0,0 +1,37 @@ +// Copyright 2016, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +namespace java io.grpc.thrift + +struct Message { + 1:i32 i, + 2:bool b, + 3:string s, + 4:list l +}