summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJiayu Liu <jiayu@hey.com>2022-02-21 13:36:44 +0100
committerJens Geyer <jensg@apache.org>2022-04-16 09:58:32 +0200
commit1eb361a89372b8676a5f48c2ee4038f6d2d8b4b7 (patch)
treedd63293e9d5ae5af5e57844fe4bd5bcbcbc7ed8a
parent2e0a80599897a57e05127b28640a1b5956ba744d (diff)
downloadthrift-1eb361a89372b8676a5f48c2ee4038f6d2d8b4b7.tar.gz
THRIFT-5521: [java gen] use jdk8 option type in java generator code
Client: Java Patch: Jiayu Liu This closes #2525
-rw-r--r--compiler/cpp/src/thrift/generate/t_java_generator.cc99
-rw-r--r--lib/java/gradle/functionalTests.gradle4
-rw-r--r--lib/java/gradle/generateTestThrift.gradle17
-rw-r--r--lib/java/gradle/sourceConfiguration.gradle2
-rw-r--r--lib/java/gradle/unitTests.gradle4
-rw-r--r--lib/java/test/org/apache/thrift/TestOptionType.java3
-rw-r--r--lib/java/test/org/apache/thrift/TestOptionals.java2
-rw-r--r--lib/java/test/org/apache/thrift/TestOptionalsWithJdk8.java63
-rw-r--r--lib/java/test/resources/.keystore (renamed from lib/java/test/.keystore)bin2429 -> 2429 bytes
-rw-r--r--lib/java/test/resources/.truststore (renamed from lib/java/test/.truststore)bin1149 -> 1149 bytes
-rw-r--r--lib/java/test/resources/JavaBeansTest.thrift (renamed from test/JavaBeansTest.thrift)0
-rw-r--r--lib/java/test/resources/JavaBinaryDefault.thrift (renamed from test/JavaBinaryDefault.thrift)0
-rw-r--r--lib/java/test/resources/JavaDeepCopyTest.thrift (renamed from test/JavaDeepCopyTest.thrift)0
-rw-r--r--lib/java/test/resources/JavaOptionTypeJdk8Test.thrift44
-rw-r--r--lib/java/test/resources/JavaTypes.thrift (renamed from test/JavaTypes.thrift)0
-rw-r--r--lib/java/test/resources/log4j.properties (renamed from lib/java/test/log4j.properties)0
-rwxr-xr-xtest/Makefile.am4
17 files changed, 214 insertions, 28 deletions
diff --git a/compiler/cpp/src/thrift/generate/t_java_generator.cc b/compiler/cpp/src/thrift/generate/t_java_generator.cc
index efcd7d304..6f4267512 100644
--- a/compiler/cpp/src/thrift/generate/t_java_generator.cc
+++ b/compiler/cpp/src/thrift/generate/t_java_generator.cc
@@ -46,6 +46,9 @@ using std::vector;
static const string endl = "\n"; // avoid ostream << std::endl flushes
+static const string thrift_option_class = "org.apache.thrift.Option";
+static const string jdk_option_class = "java.util.Optional";
+
/**
* Java code generator.
*
@@ -70,6 +73,7 @@ public:
reuse_objects_ = false;
use_option_type_ = false;
generate_future_iface_ = false;
+ use_jdk8_option_type_ = false;
undated_generated_annotations_ = false;
suppress_generated_annotations_ = false;
rethrow_unhandled_exceptions_ = false;
@@ -101,6 +105,13 @@ public:
reuse_objects_ = true;
} else if (iter->first.compare("option_type") == 0) {
use_option_type_ = true;
+ if (iter->second.compare("jdk8") == 0) {
+ use_jdk8_option_type_ = true;
+ } else if (iter->second.compare("thrift") == 0 || iter->second.compare("") == 0) {
+ use_jdk8_option_type_ = false;
+ } else {
+ throw "option_type must be 'jdk8' or 'thrift'";
+ }
} else if (iter->first.compare("rethrow_unhandled_exceptions") == 0) {
rethrow_unhandled_exceptions_ = true;
} else if (iter->first.compare("generated_annotations") == 0) {
@@ -423,6 +434,7 @@ private:
bool reuse_objects_;
bool generate_future_iface_;
bool use_option_type_;
+ bool use_jdk8_option_type_;
bool undated_generated_annotations_;
bool suppress_generated_annotations_;
bool rethrow_unhandled_exceptions_;
@@ -1287,7 +1299,7 @@ void t_java_generator::generate_tuple_scheme_read_value(ostream& out, t_struct*
indent_up();
indent(out) << "switch (setField) {" << endl;
indent_up();
-
+
const vector<t_field*>& members = tstruct->get_members();
vector<t_field*>::const_iterator m_iter;
@@ -2367,18 +2379,36 @@ void t_java_generator::generate_java_bean_boilerplate(ostream& out, t_struct* ts
if (is_deprecated) {
indent(out) << "@Deprecated" << endl;
}
- indent(out) << "public org.apache.thrift.Option<Integer> get" << cap_name;
+
+ if (use_jdk8_option_type_) {
+ indent(out) << "public " << jdk_option_class << "<Integer> get" << cap_name;
+ } else {
+ indent(out) << "public " << thrift_option_class << "<Integer> get" << cap_name;
+ }
+
out << get_cap_name("size() {") << endl;
indent_up();
indent(out) << "if (this." << field_name << " == null) {" << endl;
indent_up();
- indent(out) << "return org.apache.thrift.Option.none();" << endl;
+
+ if (use_jdk8_option_type_) {
+ indent(out) << "return " << jdk_option_class << ".empty();" << endl;
+ } else {
+ indent(out) << "return " << thrift_option_class << ".none();" << endl;
+ }
+
indent_down();
indent(out) << "} else {" << endl;
indent_up();
- indent(out) << "return org.apache.thrift.Option.some(this." << field_name << ".size());"
- << endl;
+
+ if (use_jdk8_option_type_) {
+ indent(out) << "return " << jdk_option_class << ".of(this.";
+ } else {
+ indent(out) << "return " << thrift_option_class << ".some(this.";
+ }
+ out << field_name << ".size());" << endl;
+
indent_down();
indent(out) << "}" << endl;
indent_down();
@@ -2411,19 +2441,38 @@ void t_java_generator::generate_java_bean_boilerplate(ostream& out, t_struct* ts
if (is_deprecated) {
indent(out) << "@Deprecated" << endl;
}
- indent(out) << "public org.apache.thrift.Option<java.util.Iterator<"
- << type_name(element_type, true, false) << ">> get" << cap_name;
+
+ if (use_jdk8_option_type_) {
+ indent(out) << "public " << jdk_option_class << "<";
+ } else {
+ indent(out) << "public " << thrift_option_class << "<";
+ }
+ out << "java.util.Iterator<" << type_name(element_type, true, false) << ">> get"
+ << cap_name;
+
out << get_cap_name("iterator() {") << endl;
indent_up();
indent(out) << "if (this." << field_name << " == null) {" << endl;
indent_up();
- indent(out) << "return org.apache.thrift.Option.none();" << endl;
+
+ if (use_jdk8_option_type_) {
+ indent(out) << "return " << jdk_option_class << ".empty();" << endl;
+ } else {
+ indent(out) << "return " << thrift_option_class << ".none();" << endl;
+ }
+
indent_down();
indent(out) << "} else {" << endl;
indent_up();
- indent(out) << "return org.apache.thrift.Option.some(this." << field_name << ".iterator());"
- << endl;
+
+ if (use_jdk8_option_type_) {
+ indent(out) << "return " << jdk_option_class << ".of(this.";
+ } else {
+ indent(out) << "return " << thrift_option_class << ".some(this.";
+ }
+ out << field_name << ".iterator());" << endl;
+
indent_down();
indent(out) << "}" << endl;
indent_down();
@@ -2521,7 +2570,13 @@ void t_java_generator::generate_java_bean_boilerplate(ostream& out, t_struct* ts
if (is_deprecated) {
indent(out) << "@Deprecated" << endl;
}
- indent(out) << "public org.apache.thrift.Option<" << type_name(type, true) << ">";
+
+ if (use_jdk8_option_type_) {
+ indent(out) << "public " << jdk_option_class << "<" << type_name(type, true) << ">";
+ } else {
+ indent(out) << "public " << thrift_option_class << "<" << type_name(type, true) << ">";
+ }
+
if (type->is_base_type() && ((t_base_type*)type)->get_base() == t_base_type::TYPE_BOOL) {
out << " is";
} else {
@@ -2532,11 +2587,24 @@ void t_java_generator::generate_java_bean_boilerplate(ostream& out, t_struct* ts
indent(out) << "if (this.isSet" << cap_name << "()) {" << endl;
indent_up();
- indent(out) << "return org.apache.thrift.Option.some(this." << field_name << ");" << endl;
+
+ if (use_jdk8_option_type_) {
+ indent(out) << "return " << jdk_option_class << ".of(this.";
+ } else {
+ indent(out) << "return " << thrift_option_class << ".some(this.";
+ }
+ out << field_name << ");" << endl;
+
indent_down();
indent(out) << "} else {" << endl;
indent_up();
- indent(out) << "return org.apache.thrift.Option.none();" << endl;
+
+ if (use_jdk8_option_type_) {
+ indent(out) << "return " << jdk_option_class << ".empty();" << endl;
+ } else {
+ indent(out) << "return " << thrift_option_class << ".none();" << endl;
+ }
+
indent_down();
indent(out) << "}" << endl;
indent_down();
@@ -5651,7 +5719,10 @@ THRIFT_REGISTER_GENERATOR(
" android: Generated structures are Parcelable.\n"
" android_legacy: Do not use java.io.IOException(throwable) (available for Android 2.3 and "
"above).\n"
- " option_type: Wrap optional fields in an Option type.\n"
+ " option_type=[thrift|jdk8]:\n"
+ " thrift: wrap optional fields in thrift Option type.\n"
+ " jdk8: Wrap optional fields in JDK8+ Option type.\n"
+ " If the Option type is not specified, 'thrift' is used.\n"
" rethrow_unhandled_exceptions:\n"
" Enable rethrow of unhandled exceptions and let them propagate further."
" (Default behavior is to catch and log it.)\n"
diff --git a/lib/java/gradle/functionalTests.gradle b/lib/java/gradle/functionalTests.gradle
index f00f74bf2..f1975202b 100644
--- a/lib/java/gradle/functionalTests.gradle
+++ b/lib/java/gradle/functionalTests.gradle
@@ -91,8 +91,8 @@ if (org.gradle.internal.os.OperatingSystem.current().windows) {
def javaExe = file("${System.getProperty('java.home')}/bin/java${execExt}").canonicalPath
// The common Uber jar path
def jarPath = shadowJar.archivePath.canonicalPath
-def trustStore = file('test/.truststore').canonicalPath
-def keyStore = file('test/.keystore').canonicalPath
+def trustStore = file('test/resources/.truststore').canonicalPath
+def keyStore = file('test/resources/.keystore').canonicalPath
task generateRunnerScriptForClient(group: 'Build') {
description = 'Generate a runner script for cross-check tests with TestClient'
diff --git a/lib/java/gradle/generateTestThrift.gradle b/lib/java/gradle/generateTestThrift.gradle
index d5bc3afaf..c48845e9d 100644
--- a/lib/java/gradle/generateTestThrift.gradle
+++ b/lib/java/gradle/generateTestThrift.gradle
@@ -24,11 +24,12 @@ ext.genSrc = file("$buildDir/gen-java")
ext.genBeanSrc = file("$buildDir/gen-javabean")
ext.genReuseSrc = file("$buildDir/gen-javareuse")
ext.genFullCamelSrc = file("$buildDir/gen-fullcamel")
+ext.genOptionTypeJdk8Src = file("$buildDir/gen-option-type-jdk8")
ext.genUnsafeSrc = file("$buildDir/gen-unsafe")
// Add the generated code directories to the test source set
sourceSets {
- test.java.srcDirs genSrc, genBeanSrc, genReuseSrc, genFullCamelSrc, genUnsafeSrc
+ test.java.srcDirs genSrc, genBeanSrc, genReuseSrc, genFullCamelSrc, genUnsafeSrc, genOptionTypeJdk8Src
}
// ----------------------------------------------------------------------------
@@ -37,7 +38,10 @@ sourceSets {
// A callable closure to make this easier
ext.thriftCompile = { Task task, String thriftFileName, String generator = 'java', File outputDir = genSrc ->
def thriftFile = file("$thriftRoot/test/$thriftFileName")
- assert thriftFile.exists()
+ if (!thriftFile.exists()) {
+ thriftFile = file("$projectDir/test/resources/$thriftFileName")
+ assert thriftFile.exists(), "can't find $thriftFile"
+ }
task.inputs.file thriftFile
task.outputs.dir outputDir
@@ -85,6 +89,15 @@ task generateJava(group: 'Build') {
thriftCompile(it, 'partial/thrift_test_schema.thrift')
}
+task generateOptionalTypeJava(group: 'Build') {
+ description = 'Generate the thrift gen-option-type-jdk8 source'
+ generate.dependsOn it
+
+ ext.outputBuffer = new ByteArrayOutputStream()
+
+ thriftCompile(it, 'JavaOptionTypeJdk8Test.thrift', 'java:option_type=jdk8', genOptionTypeJdk8Src)
+}
+
task generateBeanJava(group: 'Build') {
description = 'Generate the thrift gen-javabean source'
generate.dependsOn it
diff --git a/lib/java/gradle/sourceConfiguration.gradle b/lib/java/gradle/sourceConfiguration.gradle
index ce0db75d7..c510a40d5 100644
--- a/lib/java/gradle/sourceConfiguration.gradle
+++ b/lib/java/gradle/sourceConfiguration.gradle
@@ -37,7 +37,7 @@ sourceSets {
exclude '**/test/TestTServletServer.java'
}
resources {
- srcDir 'test'
+ srcDir 'test/resources'
include 'log4j.properties'
}
}
diff --git a/lib/java/gradle/unitTests.gradle b/lib/java/gradle/unitTests.gradle
index 61f2fbdeb..2bf1c039a 100644
--- a/lib/java/gradle/unitTests.gradle
+++ b/lib/java/gradle/unitTests.gradle
@@ -74,9 +74,9 @@ test {
systemProperties = [
'build.test': "${compileTestJava.destinationDir}",
'test.port': "${testPort}",
- 'javax.net.ssl.trustStore': "${projectDir}/test/.truststore",
+ 'javax.net.ssl.trustStore': "${projectDir}/test/resources/.truststore",
'javax.net.ssl.trustStorePassword': 'thrift',
- 'javax.net.ssl.keyStore': "${projectDir}/test/.keystore",
+ 'javax.net.ssl.keyStore': "${projectDir}/test/resources/.keystore",
'javax.net.ssl.keyStorePassword': 'thrift'
]
}
diff --git a/lib/java/test/org/apache/thrift/TestOptionType.java b/lib/java/test/org/apache/thrift/TestOptionType.java
index f70285ffa..ddde9d35f 100644
--- a/lib/java/test/org/apache/thrift/TestOptionType.java
+++ b/lib/java/test/org/apache/thrift/TestOptionType.java
@@ -20,11 +20,10 @@
package org.apache.thrift;
import junit.framework.TestCase;
-import org.apache.thrift.Option;
// Tests and documents behavior for the "Option<T>" type
public class TestOptionType extends TestCase {
- public void testSome() throws Exception {
+ public void testSome() {
String name = "Chuck Norris";
Option<String> option = Option.fromNullable(name);
diff --git a/lib/java/test/org/apache/thrift/TestOptionals.java b/lib/java/test/org/apache/thrift/TestOptionals.java
index f3d4cfcf6..b34e06dd3 100644
--- a/lib/java/test/org/apache/thrift/TestOptionals.java
+++ b/lib/java/test/org/apache/thrift/TestOptionals.java
@@ -26,7 +26,7 @@ import thrift.test.Opt30;
import thrift.test.Opt64;
import thrift.test.Opt80;
-// Exercises the isSet methods using structs from from ManyOptionals.thrift
+// Exercises the isSet methods using structs from ManyOptionals.thrift
public class TestOptionals extends TestCase {
public void testEncodingUtils() throws Exception {
assertEquals((short)0x8, EncodingUtils.setBit((short)0, 3, true));
diff --git a/lib/java/test/org/apache/thrift/TestOptionalsWithJdk8.java b/lib/java/test/org/apache/thrift/TestOptionalsWithJdk8.java
new file mode 100644
index 000000000..93dacedda
--- /dev/null
+++ b/lib/java/test/org/apache/thrift/TestOptionalsWithJdk8.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.thrift;
+
+import junit.framework.TestCase;
+import thrift.test.optiontypejdk8.Person;
+
+// Tests and documents behavior for the JDK8 "Option<T>" type
+public class TestOptionalsWithJdk8 extends TestCase {
+
+ public void testConstruction() {
+ Person person = new Person(1L, "name");
+ assertFalse(person.getAge().isPresent());
+ assertFalse(person.isSetAge());
+ assertFalse(person.getPhone().isPresent());
+ assertFalse(person.isSetPhone());
+ assertEquals(1L, person.getId());
+ assertTrue(person.isSetId());
+ assertEquals("name", person.getName());
+ assertTrue(person.isSetName());
+
+ assertFalse(person.getAddresses().isPresent());
+ assertEquals(Integer.valueOf(0), person.getAddressesSize().orElse(0));
+ assertFalse(person.getPets().isPresent());
+ assertEquals(Integer.valueOf(0), person.getPetsSize().orElse(0));
+ }
+
+ public void testEmpty() {
+ Person person = new Person();
+ person.setPhone("phone");
+ assertFalse(person.getAge().isPresent());
+ assertFalse(person.isSetAge());
+ assertTrue(person.getPhone().isPresent());
+ assertEquals("phone", person.getPhone().get());
+ assertTrue(person.isSetPhone());
+ assertEquals(0L, person.getId());
+ assertFalse(person.isSetId());
+ assertNull(person.getName());
+ assertFalse(person.isSetName());
+
+ assertFalse(person.getAddresses().isPresent());
+ assertEquals(Integer.valueOf(0), person.getAddressesSize().orElse(0));
+ assertFalse(person.getPets().isPresent());
+ assertEquals(Integer.valueOf(0), person.getPetsSize().orElse(0));
+ }
+}
diff --git a/lib/java/test/.keystore b/lib/java/test/resources/.keystore
index 4dd66ac07..4dd66ac07 100644
--- a/lib/java/test/.keystore
+++ b/lib/java/test/resources/.keystore
Binary files differ
diff --git a/lib/java/test/.truststore b/lib/java/test/resources/.truststore
index 26fbd195f..26fbd195f 100644
--- a/lib/java/test/.truststore
+++ b/lib/java/test/resources/.truststore
Binary files differ
diff --git a/test/JavaBeansTest.thrift b/lib/java/test/resources/JavaBeansTest.thrift
index b6c3ea861..b6c3ea861 100644
--- a/test/JavaBeansTest.thrift
+++ b/lib/java/test/resources/JavaBeansTest.thrift
diff --git a/test/JavaBinaryDefault.thrift b/lib/java/test/resources/JavaBinaryDefault.thrift
index 5517802c7..5517802c7 100644
--- a/test/JavaBinaryDefault.thrift
+++ b/lib/java/test/resources/JavaBinaryDefault.thrift
diff --git a/test/JavaDeepCopyTest.thrift b/lib/java/test/resources/JavaDeepCopyTest.thrift
index fc974aefd..fc974aefd 100644
--- a/test/JavaDeepCopyTest.thrift
+++ b/lib/java/test/resources/JavaDeepCopyTest.thrift
diff --git a/lib/java/test/resources/JavaOptionTypeJdk8Test.thrift b/lib/java/test/resources/JavaOptionTypeJdk8Test.thrift
new file mode 100644
index 000000000..193e079d0
--- /dev/null
+++ b/lib/java/test/resources/JavaOptionTypeJdk8Test.thrift
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ * Contains some contributions under the Thrift Software License.
+ * Please see doc/old-thrift-license.txt in the Thrift distribution for
+ * details.
+ */
+
+namespace java thrift.test.optiontypejdk8
+
+struct Person {
+ 1: required i64 id;
+ 2: required string name;
+ 3: optional i64 age;
+ 4: optional string phone;
+ 5: optional list<string> addresses;
+ 6: optional map<string, Pet> pets;
+}
+
+enum PetType {
+ Cat = 1
+ Dog = 2
+ Bunny = 3
+}
+
+struct Pet {
+ 1: required string name;
+ 2: optional PetType type;
+}
diff --git a/test/JavaTypes.thrift b/lib/java/test/resources/JavaTypes.thrift
index 555334082..555334082 100644
--- a/test/JavaTypes.thrift
+++ b/lib/java/test/resources/JavaTypes.thrift
diff --git a/lib/java/test/log4j.properties b/lib/java/test/resources/log4j.properties
index ab9bebafe..ab9bebafe 100644
--- a/lib/java/test/log4j.properties
+++ b/lib/java/test/resources/log4j.properties
diff --git a/test/Makefile.am b/test/Makefile.am
index 58482f2d2..d428086bd 100755
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -142,10 +142,6 @@ EXTRA_DIST = \
Include.thrift \
Identifiers.thrift \
Int64Test.thrift \
- JavaBeansTest.thrift \
- JavaBinaryDefault.thrift \
- JavaDeepCopyTest.thrift \
- JavaTypes.thrift \
JsDeepConstructorTest.thrift \
ManyOptionals.thrift \
ManyTypedefs.thrift \