From a7420b6593998776871d55cbf415a0531c76a012 Mon Sep 17 00:00:00 2001 From: Bryan Duxbury Date: Mon, 13 Sep 2010 15:42:36 +0000 Subject: [PATCH] THRIFT-894. java: Make default accessors for binary fields return byte[]; provide new accessors to get ByteBuffer version This patch causes the underlying ByteBuffer that backs a binary field to be hidden behind a default accessor that provides a byte[] interface. This should allow users who skipped 0.4 to update their generated code without breaking any of their other code. A new accessor has been added that allows a way down to the underlying ByteBuffer for those experts who want to take advantage. git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@996579 13f79535-47bb-0310-9956-ffa450edef68 --- compiler/cpp/src/generate/t_java_generator.cc | 45 ++++++++++++++----- .../src/org/apache/thrift/TBaseHelper.java | 33 ++++++++++++++ .../org/apache/thrift/TestTBaseHelper.java | 11 +++++ .../org/apache/thrift/TestTDeserializer.java | 2 +- 4 files changed, 80 insertions(+), 11 deletions(-) diff --git a/compiler/cpp/src/generate/t_java_generator.cc b/compiler/cpp/src/generate/t_java_generator.cc index c1047f97..e136c336 100644 --- a/compiler/cpp/src/generate/t_java_generator.cc +++ b/compiler/cpp/src/generate/t_java_generator.cc @@ -1854,21 +1854,46 @@ void t_java_generator::generate_java_bean_boilerplate(ofstream& out, // Simple getter generate_java_doc(out, field); - indent(out) << "public " << type_name(type); - if (type->is_base_type() && - ((t_base_type*)type)->get_base() == t_base_type::TYPE_BOOL) { - out << " is"; + if (type->is_base_type() && ((t_base_type*)type)->is_binary()) { + indent(out) << "public byte[] get" << cap_name << "() {" << endl; + indent(out) << " set" << cap_name << "(TBaseHelper.rightSize(" << field_name << "));" << endl; + indent(out) << " return " << field_name << ".array();" << endl; + indent(out) << "}" << endl << endl; + + indent(out) << "public ByteBuffer " << get_cap_name("bufferFor") << cap_name << "() {" << endl; + indent(out) << " return " << field_name << ";" << endl; + indent(out) << "}" << endl << endl; } else { - out << " get"; + indent(out) << "public " << type_name(type); + if (type->is_base_type() && + ((t_base_type*)type)->get_base() == t_base_type::TYPE_BOOL) { + out << " is"; + } else { + out << " get"; + } + out << cap_name << "() {" << endl; + indent_up(); + indent(out) << "return this." << field_name << ";" << endl; + indent_down(); + indent(out) << "}" << endl << endl; } - out << cap_name << "() {" << endl; - indent_up(); - indent(out) << "return this." << field_name << ";" << endl; - indent_down(); - indent(out) << "}" << endl << endl; // Simple setter generate_java_doc(out, field); + if (type->is_base_type() && ((t_base_type*)type)->is_binary()) { + indent(out) << "public "; + if (bean_style_) { + out << "void"; + } else { + out << type_name(tstruct); + } + out << " set" << cap_name << "(byte[] " << field_name << ") {" << endl; + indent(out) << " set" << cap_name << "(ByteBuffer.wrap(" << field_name << "));" << endl; + if (!bean_style_) { + indent(out) << " return this;" << endl; + } + indent(out) << "}" << endl << endl; + } indent(out) << "public "; if (bean_style_) { out << "void"; diff --git a/lib/java/src/org/apache/thrift/TBaseHelper.java b/lib/java/src/org/apache/thrift/TBaseHelper.java index 9a7ee73f..46075d3e 100644 --- a/lib/java/src/org/apache/thrift/TBaseHelper.java +++ b/lib/java/src/org/apache/thrift/TBaseHelper.java @@ -240,4 +240,37 @@ public class TBaseHelper { int extended = (b | 0x100) & 0x1ff; return Integer.toHexString(extended).toUpperCase().substring(1); } + + public static byte[] byteBufferToByteArray(ByteBuffer byteBuffer) { + if (wrapsFullArray(byteBuffer)) { + return byteBuffer.array(); + } + byte[] target = new byte[byteBuffer.remaining()]; + byteBufferToByteArray(byteBuffer, target, 0); + return target; + } + + public static boolean wrapsFullArray(ByteBuffer byteBuffer) { + return byteBuffer.hasArray() + && byteBuffer.position() == 0 + && byteBuffer.arrayOffset() == 0 + && byteBuffer.remaining() == byteBuffer.capacity(); + } + + public static int byteBufferToByteArray(ByteBuffer byteBuffer, byte[] target, int offset) { + int remaining = byteBuffer.remaining(); + System.arraycopy(byteBuffer.array(), + byteBuffer.arrayOffset() + byteBuffer.position(), + target, + offset, + remaining); + return remaining; + } + + public static ByteBuffer rightSize(ByteBuffer in) { + if (wrapsFullArray(in)) { + return in; + } + return ByteBuffer.wrap(byteBufferToByteArray(in)); + } } diff --git a/lib/java/test/org/apache/thrift/TestTBaseHelper.java b/lib/java/test/org/apache/thrift/TestTBaseHelper.java index 6f24093f..2c8caac0 100644 --- a/lib/java/test/org/apache/thrift/TestTBaseHelper.java +++ b/lib/java/test/org/apache/thrift/TestTBaseHelper.java @@ -18,6 +18,7 @@ */ package org.apache.thrift; +import java.nio.ByteBuffer; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; @@ -139,4 +140,14 @@ public class TestTBaseHelper extends TestCase { b.add(new byte[]{'a','b', 'a'}); assertTrue(TBaseHelper.compareTo(a, b) > 0); } + + public void testByteBufferToByteArray() throws Exception { + byte[] b1 = {10,9,8,7,6,5,4,3,2,1,0}; + byte[] b2 = TBaseHelper.byteBufferToByteArray(ByteBuffer.wrap(b1)); + assertEquals("b1 and b2 should be the exact same array (identity) due to fast path", b1, b2); + + byte[] b3 = TBaseHelper.byteBufferToByteArray(ByteBuffer.wrap(b1, 1, 3)); + assertEquals(3, b3.length); + assertEquals(ByteBuffer.wrap(b1, 1, 3), ByteBuffer.wrap(b3)); + } } diff --git a/lib/java/test/org/apache/thrift/TestTDeserializer.java b/lib/java/test/org/apache/thrift/TestTDeserializer.java index 1f141bdc..a4a353d6 100644 --- a/lib/java/test/org/apache/thrift/TestTDeserializer.java +++ b/lib/java/test/org/apache/thrift/TestTDeserializer.java @@ -97,7 +97,7 @@ public class TestTDeserializer extends TestCase { String resultString = deserializer.partialDeserializeString(serialize(level1SWU, factory), StructWithAUnion._Fields.TEST_UNION, TestUnion._Fields.STRUCT_FIELD, OneOfEach._Fields.SOME_CHARACTERS); assertEquals(expectedString, resultString); - byte[] expectedBinary = level3OneOfEach.getBase64().array(); + byte[] expectedBinary = level3OneOfEach.getBase64(); ByteBuffer resultBinary = deserializer.partialDeserializeByteArray(serialize(level1SWU, factory), StructWithAUnion._Fields.TEST_UNION, TestUnion._Fields.STRUCT_FIELD, OneOfEach._Fields.BASE64); assertEquals(expectedBinary.length, resultBinary.limit() - resultBinary.position() - resultBinary.arrayOffset()); assertEquals(ByteBuffer.wrap(expectedBinary), resultBinary); -- 2.17.1