diff options
-rw-r--r-- | compiler/cpp/src/generate/t_java_generator.cc | 92 | ||||
-rwxr-xr-x | lib/java/build.xml | 33 | ||||
-rw-r--r-- | lib/java/test/org/apache/thrift/TestReuse.java | 60 | ||||
-rw-r--r-- | test/ReuseObjects.thrift | 30 |
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:=" +${thrift.groupid}.protocol,${thrift.groupid}.transport,org.slf4j,${thrift.groupid}";version="${version}", +${thrift.groupid}.protocol;uses:="${thrift.groupid}.transport,${thrift.groupid},${thrift.groupid}.scheme" +;version="${version}",${thrift.groupid}.server;uses:="${thrift.groupid}.transport,${thrift.groupid}.protocol, +${thrift.groupid},org.slf4j,javax.servlet,javax.servlet.http";version="${version}",${thrift.groupid}.transport; +uses:="${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";version="${version}",${thrift.groupid};uses:="${thrift.groupid}.protocol, +${thrift.groupid}.async,${thrift.groupid}.server,${thrift.groupid}.transport,org.slf4j,org.apache.log4j, +${thrift.groupid}.scheme";version="${version}",${thrift.groupid}.meta_data;uses:="${thrift.groupid}" +;version="${version}",${thrift.groupid}.scheme;uses:="${thrift.groupid}.protocol, +${thrift.groupid}";version="${version}""/> + <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="[1.4,2)""/> </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; +} + |