Author: cutting
Date: Thu Jul 3 18:35:42 2014
New Revision: 1607711
URL: http://svn.apache.org/r1607711
Log:
AVRO-1498. Java: Fix custom encodings to work in reflect without Unsafe access.
Contributed by Christopher Mann.
Modified:
avro/trunk/CHANGES.txt
avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/FieldAccessReflect.java
avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/ReflectData.java
avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/ReflectionUtil.java
avro/trunk/lang/java/avro/src/test/java/org/apache/avro/reflect/TestReflect.java
Modified: avro/trunk/CHANGES.txt
URL:
http://svn.apache.org/viewvc/avro/trunk/CHANGES.txt?rev=1607711&r1=1607710&r2=1607711&view=diff
==============================================================================
--- avro/trunk/CHANGES.txt (original)
+++ avro/trunk/CHANGES.txt Thu Jul 3 18:35:42 2014
@@ -110,6 +110,9 @@ Trunk (not yet released)
AVRO-1499. Ruby: Fix encoding issue that caused corrupted data files
to be written under Ruby 2.0+. (Willem van Bergen and martinkl)
+ AVRO-1498. Java: Fix custom encodings to work in reflect without
+ Unsafe access. (Christopher Mann via cutting)
+
Avro 1.7.6 (15 January 2014)
NEW FEATURES
Modified:
avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/FieldAccessReflect.java
URL:
http://svn.apache.org/viewvc/avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/FieldAccessReflect.java?rev=1607711&r1=1607710&r2=1607711&view=diff
==============================================================================
---
avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/FieldAccessReflect.java
(original)
+++
avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/FieldAccessReflect.java
Thu Jul 3 18:35:42 2014
@@ -17,6 +17,10 @@
*/
package org.apache.avro.reflect;
+import org.apache.avro.AvroRuntimeException;
+import org.apache.avro.io.Decoder;
+import org.apache.avro.io.Encoder;
+
import java.io.IOException;
import java.lang.reflect.Field;
@@ -24,11 +28,18 @@ class FieldAccessReflect extends FieldAc
@Override
protected FieldAccessor getAccessor(Field field) {
+ AvroEncode enc = field.getAnnotation(AvroEncode.class);
+ if (enc != null)
+ try {
+ return new ReflectionBasesAccessorCustomEncoded(field,
enc.using().newInstance());
+ } catch (Exception e) {
+ throw new AvroRuntimeException("Could not instantiate custom
Encoding");
+ }
return new ReflectionBasedAccessor(field);
}
- private final class ReflectionBasedAccessor extends FieldAccessor {
- private final Field field;
+ private class ReflectionBasedAccessor extends FieldAccessor {
+ protected final Field field;
private boolean isStringable;
private boolean isCustomEncoded;
@@ -69,6 +80,42 @@ class FieldAccessReflect extends FieldAc
protected boolean isCustomEncoded() {
return isCustomEncoded;
}
+ }
+
+ private final class ReflectionBasesAccessorCustomEncoded extends
ReflectionBasedAccessor {
+
+ private CustomEncoding<?> encoding;
+
+ public ReflectionBasesAccessorCustomEncoded(Field f, CustomEncoding<?>
encoding) {
+ super(f);
+ this.encoding = encoding;
+ }
+
+ @Override
+ protected void read(Object object, Decoder in) throws IOException {
+ try {
+ field.set(object, encoding.read(in));
+ } catch (IllegalAccessException e) {
+ throw new AvroRuntimeException(e);
+}
+ }
+ @Override
+ protected void write(Object object, Encoder out) throws IOException {
+ try {
+ encoding.write(field.get(object), out);
+ } catch (IllegalAccessException e) {
+ throw new AvroRuntimeException(e);
+ }
+ }
+
+ protected boolean isCustomEncoded() {
+ return true;
+ }
+
+ @Override
+ protected boolean supportsIO() {
+ return true;
+ }
}
}
Modified:
avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/ReflectData.java
URL:
http://svn.apache.org/viewvc/avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/ReflectData.java?rev=1607711&r1=1607710&r2=1607711&view=diff
==============================================================================
---
avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/ReflectData.java
(original)
+++
avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/ReflectData.java
Thu Jul 3 18:35:42 2014
@@ -206,7 +206,7 @@ public class ReflectData extends Specifi
}
}
- private static final ConcurrentHashMap<Class<?>, ClassAccessorData>
+ static final ConcurrentHashMap<Class<?>, ClassAccessorData>
ACCESSOR_CACHE = new ConcurrentHashMap<Class<?>, ClassAccessorData>();
private static class ClassAccessorData {
Modified:
avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/ReflectionUtil.java
URL:
http://svn.apache.org/viewvc/avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/ReflectionUtil.java?rev=1607711&r1=1607710&r2=1607711&view=diff
==============================================================================
---
avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/ReflectionUtil.java
(original)
+++
avro/trunk/lang/java/avro/src/main/java/org/apache/avro/reflect/ReflectionUtil.java
Thu Jul 3 18:35:42 2014
@@ -33,8 +33,11 @@ class ReflectionUtil {
private ReflectionUtil() {
}
- private static final FieldAccess FIELD_ACCESS;
+ private static FieldAccess fieldAccess;
static {
+ resetFieldAccess();
+ }
+ static void resetFieldAccess() {
// load only one implementation of FieldAccess
// so it is monomorphic and the JIT can inline
FieldAccess access = null;
@@ -60,7 +63,7 @@ class ReflectionUtil {
"Unable to load a functional FieldAccess class!");
}
}
- FIELD_ACCESS = access;
+ fieldAccess = access;
}
private static <T> T load(String name, Class<T> type) throws Exception {
@@ -69,7 +72,7 @@ class ReflectionUtil {
}
public static FieldAccess getFieldAccess() {
- return FIELD_ACCESS;
+ return fieldAccess;
}
private static boolean validate(FieldAccess access) throws Exception {
Modified:
avro/trunk/lang/java/avro/src/test/java/org/apache/avro/reflect/TestReflect.java
URL:
http://svn.apache.org/viewvc/avro/trunk/lang/java/avro/src/test/java/org/apache/avro/reflect/TestReflect.java?rev=1607711&r1=1607710&r2=1607711&view=diff
==============================================================================
---
avro/trunk/lang/java/avro/src/test/java/org/apache/avro/reflect/TestReflect.java
(original)
+++
avro/trunk/lang/java/avro/src/test/java/org/apache/avro/reflect/TestReflect.java
Thu Jul 3 18:35:42 2014
@@ -719,6 +719,24 @@ public class TestReflect {
assertEquals(b, decoded);
}
+ @Test public void testDisableUnsafe() throws Exception {
+ String saved = System.getProperty("avro.disable.unsafe");
+ try {
+ System.setProperty("avro.disable.unsafe", "true");
+ ReflectData.ACCESSOR_CACHE.clear();
+ ReflectionUtil.resetFieldAccess();
+ testMultipleAnnotations();
+ testRecordWithNullIO();
+ } finally {
+ if (saved == null)
+ System.clearProperty("avro.disable.unsafe");
+ else
+ System.setProperty("avro.disable.unsafe", saved);
+ ReflectData.ACCESSOR_CACHE.clear();
+ ReflectionUtil.resetFieldAccess();
+ }
+ }
+
public static class SampleRecord {
public int x = 1;
private int y = 2;