summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/cpp/src/generate/t_java_generator.cc92
-rwxr-xr-xlib/java/build.xml33
-rw-r--r--lib/java/test/org/apache/thrift/TestReuse.java60
-rw-r--r--test/ReuseObjects.thrift30
4 files changed, 190 insertions, 25 deletions
diff --git a/compiler/cpp/src/generate/t_java_generator.cc b/compiler/cpp/src/generate/t_java_generator.cc
index 414c519ec..9019c48a5 100644
--- a/compiler/cpp/src/generate/t_java_generator.cc
+++ b/compiler/cpp/src/generate/t_java_generator.cc
@@ -78,6 +78,9 @@ public:
android_legacy_ = true;
}
+ iter = parsed_options.find("reuse-objects");
+ reuse_objects_ = (iter != parsed_options.end());
+
out_dir_base_ = (bean_style_ ? "gen-javabean" : "gen-java");
}
@@ -197,16 +200,19 @@ public:
void generate_deserialize_set_element (std::ofstream& out,
t_set* tset,
std::string prefix="",
+ std::string obj="",
bool has_metadata = true);
void generate_deserialize_map_element (std::ofstream& out,
t_map* tmap,
std::string prefix="",
+ std::string obj="",
bool has_metadata = true);
void generate_deserialize_list_element (std::ofstream& out,
t_list* tlist,
std::string prefix="",
+ std::string obj="",
bool has_metadata = true);
void generate_serialize_field (std::ofstream& out,
@@ -310,6 +316,7 @@ public:
bool android_legacy_;
bool java5_;
bool sorted_containers_;
+ bool reuse_objects_;
};
@@ -3079,9 +3086,17 @@ void t_java_generator::generate_deserialize_field(ofstream& out,
void t_java_generator::generate_deserialize_struct(ofstream& out,
t_struct* tstruct,
string prefix) {
- out <<
- indent() << prefix << " = new " << type_name(tstruct) << "();" << endl <<
- indent() << prefix << ".read(iprot);" << endl;
+
+ if (reuse_objects_) {
+ indent(out) << "if (" << prefix << " == null) {" << endl;
+ indent_up();
+ }
+ indent(out) << prefix << " = new " << type_name(tstruct) << "();" << endl;
+ if (reuse_objects_) {
+ indent_down();
+ indent(out) << "}" << endl;
+ }
+ indent(out) << prefix << ".read(iprot);" << endl;
}
/**
@@ -3126,7 +3141,14 @@ void t_java_generator::generate_deserialize_container(ofstream& out,
}
}
- indent(out) << prefix << " = new " << type_name(ttype, false, true);
+ if (reuse_objects_) {
+ indent(out) << "if (" << prefix << " == null) {" << endl;
+ indent_up();
+ }
+
+ out <<
+ indent() << prefix << " = new " << type_name(ttype, false, true);
+
// size the collection correctly
if (sorted_containers_ && (ttype->is_map() || ttype->is_set())) {
// TreeSet and TreeMap don't have any constructor which takes a capactity as an argument
@@ -3138,21 +3160,17 @@ void t_java_generator::generate_deserialize_container(ofstream& out,
<< ");" << endl;
}
- // For loop iterates over elements
- string i = tmp("_i");
- indent(out) <<
- "for (int " << i << " = 0; " <<
- i << " < " << obj << ".size" << "; " <<
- "++" << i << ")" << endl;
-
- scope_up(out);
+ if (reuse_objects_) {
+ indent_down();
+ indent(out) << "}" << endl;
+ }
if (ttype->is_map()) {
- generate_deserialize_map_element(out, (t_map*)ttype, prefix, has_metadata);
+ generate_deserialize_map_element(out, (t_map*)ttype, prefix, obj, has_metadata);
} else if (ttype->is_set()) {
- generate_deserialize_set_element(out, (t_set*)ttype, prefix, has_metadata);
+ generate_deserialize_set_element(out, (t_set*)ttype, prefix, obj, has_metadata);
} else if (ttype->is_list()) {
- generate_deserialize_list_element(out, (t_list*)ttype, prefix, has_metadata);
+ generate_deserialize_list_element(out, (t_list*)ttype, prefix, obj, has_metadata);
}
scope_down(out);
@@ -3176,14 +3194,24 @@ void t_java_generator::generate_deserialize_container(ofstream& out,
*/
void t_java_generator::generate_deserialize_map_element(ofstream& out,
t_map* tmap,
- string prefix, bool has_metadata) {
+ string prefix,
+ string obj, bool has_metadata) {
string key = tmp("_key");
string val = tmp("_val");
t_field fkey(tmap->get_key_type(), key);
t_field fval(tmap->get_val_type(), val);
- indent(out) << declare_field(&fkey) << endl;
- indent(out) << declare_field(&fval) << endl;
+ indent(out) << declare_field(&fkey, reuse_objects_, false) << endl;
+ indent(out) << declare_field(&fval, reuse_objects_, false) << endl;
+
+ // For loop iterates over elements
+ string i = tmp("_i");
+ indent(out) <<
+ "for (int " << i << " = 0; " <<
+ i << " < " << obj << ".size" << "; " <<
+ "++" << i << ")" << endl;
+
+ scope_up(out);
generate_deserialize_field(out, &fkey, "", has_metadata);
generate_deserialize_field(out, &fval, "", has_metadata);
@@ -3196,15 +3224,25 @@ void t_java_generator::generate_deserialize_map_element(ofstream& out,
*/
void t_java_generator::generate_deserialize_set_element(ofstream& out,
t_set* tset,
- string prefix, bool has_metadata) {
+ string prefix,
+ string obj, bool has_metadata) {
string elem = tmp("_elem");
t_field felem(tset->get_elem_type(), elem);
- indent(out) << declare_field(&felem) << endl;
+ indent(out) << declare_field(&felem, reuse_objects_, false) << endl;
+ // For loop iterates over elements
+ string i = tmp("_i");
+ indent(out) <<
+ "for (int " << i << " = 0; " <<
+ i << " < " << obj << ".size" << "; " <<
+ "++" << i << ")" << endl;
+ scope_up(out);
+
generate_deserialize_field(out, &felem, "", has_metadata);
indent(out) << prefix << ".add(" << elem << ");" << endl;
+
}
/**
@@ -3212,12 +3250,21 @@ void t_java_generator::generate_deserialize_set_element(ofstream& out,
*/
void t_java_generator::generate_deserialize_list_element(ofstream& out,
t_list* tlist,
- string prefix, bool has_metadata) {
+ string prefix,
+ string obj, bool has_metadata) {
string elem = tmp("_elem");
t_field felem(tlist->get_elem_type(), elem);
- indent(out) << declare_field(&felem) << endl;
+ indent(out) << declare_field(&felem, reuse_objects_, false) << endl;
+ // For loop iterates over elements
+ string i = tmp("_i");
+ indent(out) <<
+ "for (int " << i << " = 0; " <<
+ i << " < " << obj << ".size" << "; " <<
+ "++" << i << ")" << endl;
+ scope_up(out);
+
generate_deserialize_field(out, &felem, "", has_metadata);
indent(out) << prefix << ".add(" << elem << ");" << endl;
@@ -4529,6 +4576,7 @@ THRIFT_REGISTER_GENERATOR(java, "Java",
" nocamel: Do not use CamelCase field accessors with beans.\n"
" android_legacy: Do not use java.io.IOException(throwable) (available for Android 2.3 and above).\n"
" java5: Generate Java 1.5 compliant code (includes android_legacy flag).\n"
+" reuse-objects: Data objects will not be allocated, but existing instances will be used (read and write).\n"
" sorted_containers:\n"
" Use TreeSet/TreeMap instead of HashSet/HashMap as a implementation of set/map.\n"
)
diff --git a/lib/java/build.xml b/lib/java/build.xml
index 5545b8cae..66ffb1d24 100755
--- a/lib/java/build.xml
+++ b/lib/java/build.xml
@@ -47,6 +47,7 @@
<property name="gen" location="gen-java"/>
<property name="genbean" location="gen-javabean"/>
+ <property name="genreuse" location="gen-javareuse"/>
<property name="jar.file" location="${build.dir}/${final.name}.jar"/>
<property name="test.jar.file" location="${build.dir}/${final.name}-test.jar"/>
@@ -75,6 +76,7 @@
<pathelement location="${build.test.dir}"/>
<pathelement location="${jar.file}"/>
<pathelement location="${test.jar.file}"/>
+
</path>
<!-- Tasks -->
@@ -123,7 +125,21 @@
<attribute name="Bundle-Description" value="Apache Thrift library"/>
<attribute name="Bundle-License" value="${license}"/>
<attribute name="Bundle-ActivationPolicy" value="lazy"/>
- <attribute name="Export-Package" value="${thrift.groupid};version=${version}"/>
+ <attribute name="Export-Package" value="${thrift.groupid}.async;uses:=&quot;
+${thrift.groupid}.protocol,${thrift.groupid}.transport,org.slf4j,${thrift.groupid}&quot;;version=&quot;${version}&quot;,
+${thrift.groupid}.protocol;uses:=&quot;${thrift.groupid}.transport,${thrift.groupid},${thrift.groupid}.scheme&quot;
+;version=&quot;${version}&quot;,${thrift.groupid}.server;uses:=&quot;${thrift.groupid}.transport,${thrift.groupid}.protocol,
+${thrift.groupid},org.slf4j,javax.servlet,javax.servlet.http&quot;;version=&quot;${version}&quot;,${thrift.groupid}.transport;
+uses:=&quot;${thrift.groupid}.protocol,${thrift.groupid},org.apache.http.client,org.apache.http.params,org.apache.http.entity,
+org.apache.http.client.methods,org.apache.http,org.slf4j,javax.net.ssl,javax.net,javax.security.sasl,
+javax.security.auth.callback&quot;;version=&quot;${version}&quot;,${thrift.groupid};uses:=&quot;${thrift.groupid}.protocol,
+${thrift.groupid}.async,${thrift.groupid}.server,${thrift.groupid}.transport,org.slf4j,org.apache.log4j,
+${thrift.groupid}.scheme&quot;;version=&quot;${version}&quot;,${thrift.groupid}.meta_data;uses:=&quot;${thrift.groupid}&quot;
+;version=&quot;${version}&quot;,${thrift.groupid}.scheme;uses:=&quot;${thrift.groupid}.protocol,
+${thrift.groupid}&quot;;version=&quot;${version}&quot;"/>
+ <attribute name="Import-Package" value="javax.net,javax.net.ssl,javax.security.auth.callback,
+javax.security.sasl,javax.servlet;resolution:=optional,javax.servlet.http;resolution:=optional,
+resolution:=optional,org.slf4j;resolution:=optional;version=&quot;[1.4,2)&quot;"/>
</manifest>
<fileset dir="${build.dir}">
<include name="org/apache/thrift/**/*.class"/>
@@ -150,6 +166,7 @@
<delete dir="${build.dir}"/>
<delete dir="${gen}"/>
<delete dir="${genbean}"/>
+ <delete dir="${genreuse}"/>
</target>
<target name="optional-generate" unless="no-gen-thrift">
@@ -161,11 +178,15 @@
<javac debug="true" srcdir="${gen}" destdir="${build.test.dir}" classpathref="test.classpath" includeantruntime="false" encoding="UTF-8">
<compilerarg value="-Xlint:deprecation"/>
<!--<compilerarg value="-Xlint:unchecked"/>-->
- </javac>
+ </javac>
<javac debug="true" srcdir="${genbean}" destdir="${build.test.dir}" classpathref="test.classpath" includeantruntime="false" encoding="UTF-8">
<compilerarg value="-Xlint:deprecation"/>
<!--<compilerarg value="-Xlint:unchecked"/>-->
- </javac>
+ </javac>
+ <javac debug="true" srcdir="${genreuse}" destdir="${build.test.dir}" classpathref="test.classpath" includeantruntime="false" encoding="UTF-8">
+ <compilerarg value="-Xlint:deprecation"/>
+ <!--<compilerarg value="-Xlint:unchecked"/>-->
+ </javac>
<javac debug="true" srcdir="${src.test}" destdir="${build.test.dir}" classpathref="test.classpath" includeantruntime="false" encoding="UTF-8">
<compilerarg value="-Xlint:deprecation"/>
<!--<compilerarg value="-Xlint:unchecked"/>-->
@@ -254,6 +275,12 @@
<exec executable="../../compiler/cpp/thrift" failonerror="true">
<arg line="--gen java:hashcode ${test.thrift.home}/ManyOptionals.thrift"/>
</exec>
+ <exec executable="mkdir" failonerror="true">
+ <arg line="-p ${genreuse}"/>
+ </exec>
+ <exec executable="../../compiler/cpp/thrift" failonerror="true">
+ <arg line="--gen java:reuse-objects -out ${genreuse} ${test.thrift.home}/ReuseObjects.thrift"/>
+ </exec>
</target>
<target name="proxy" if="proxy.enabled">
diff --git a/lib/java/test/org/apache/thrift/TestReuse.java b/lib/java/test/org/apache/thrift/TestReuse.java
new file mode 100644
index 000000000..db16c74ab
--- /dev/null
+++ b/lib/java/test/org/apache/thrift/TestReuse.java
@@ -0,0 +1,60 @@
+/*
+ * 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 java.util.HashSet;
+
+import junit.framework.TestCase;
+
+import org.apache.thrift.protocol.TBinaryProtocol;
+import org.apache.thrift.protocol.TType;
+
+import thrift.test.Reuse;
+
+// Tests reusing objects for deserialization.
+//
+public class TestReuse extends TestStruct {
+
+ public void testReuseObject() throws Exception {
+ TSerializer binarySerializer = new TSerializer(new TBinaryProtocol.Factory());
+ TDeserializer binaryDeserializer = new TDeserializer(new TBinaryProtocol.Factory());
+
+ Reuse ru1 = new Reuse();
+ HashSet<String> hs1 = new HashSet<String>();
+ byte[] serBytes;
+ String st1 = new String("string1");
+ String st2 = new String("string2");
+
+ ru1.setVal1(11);
+ ru1.setVal2(hs1);
+ ru1.addToVal2(st1);
+
+ serBytes = binarySerializer.serialize(ru1);
+
+ // update hash set after serialization
+ hs1.add(st2);
+
+ binaryDeserializer.deserialize(ru1, serBytes);
+
+ assertTrue( ru1.getVal2() == hs1 );
+ assertTrue( hs1.size() == 2 );
+ }
+
+}
diff --git a/test/ReuseObjects.thrift b/test/ReuseObjects.thrift
new file mode 100644
index 000000000..2dd6c6ec3
--- /dev/null
+++ b/test/ReuseObjects.thrift
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ */
+
+// The java codegenerator has option to reuse objects for deserialization
+
+namespace java thrift.test
+
+include "ThriftTest.thrift"
+
+struct Reuse {
+ 1: i32 val1;
+ 2: set<string> val2;
+}
+