Log Message
Support Java runtime with limited support for sun.misc.Unsafe (XSTR-751). Renamed Sun14ReflectionProvider to SunUnsafeReflectionProvider and factored out SunLimitedUnsafeReflectionProvider. Support new ReflectionProvider in JVM's detection code.
Modified Paths
- trunk/xstream/src/java/com/thoughtworks/xstream/converters/reflection/Sun14ReflectionProvider.java
- trunk/xstream/src/java/com/thoughtworks/xstream/core/JVM.java
- trunk/xstream/src/test/com/thoughtworks/xstream/converters/extended/ToAttributedValueConverterTest.java
- trunk/xstream-distribution/src/content/changes.html
- trunk/xstream-distribution/src/content/faq.html
Added Paths
- trunk/xstream/src/java/com/thoughtworks/xstream/converters/reflection/SunLimitedUnsafeReflectionProvider.java
- trunk/xstream/src/java/com/thoughtworks/xstream/converters/reflection/SunUnsafeReflectionProvider.java
- trunk/xstream/src/test/com/thoughtworks/xstream/converters/reflection/SunLimitedUnsafeReflectionProviderTest.java
- trunk/xstream/src/test/com/thoughtworks/xstream/converters/reflection/SunUnsafeReflectionProviderTest.java
Removed Paths
Diff
Modified: trunk/xstream/src/java/com/thoughtworks/xstream/converters/reflection/Sun14ReflectionProvider.java (2205 => 2206)
--- trunk/xstream/src/java/com/thoughtworks/xstream/converters/reflection/Sun14ReflectionProvider.java 2013-12-27 18:42:46 UTC (rev 2205)
+++ trunk/xstream/src/java/com/thoughtworks/xstream/converters/reflection/Sun14ReflectionProvider.java 2014-01-08 16:10:50 UTC (rev 2206)
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2004, 2005 Joe Walnes.
- * Copyright (C) 2006, 2007, 2008, 2011, 2013 XStream Committers.
+ * Copyright (C) 2006, 2007, 2008, 2011, 2013, 2014 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -11,134 +11,32 @@
*/
package com.thoughtworks.xstream.converters.reflection;
-import sun.misc.Unsafe;
-
-import java.lang.reflect.Field;
-import java.util.Map;
-import java.util.WeakHashMap;
-
/**
- * Instantiates a new object on the Sun JVM by bypassing the constructor (meaning code in the constructor
- * will never be executed and parameters do not have to be known). This is the same method used by the internals of
- * standard Java serialization, but relies on internal Sun code that may not be present on all JVMs.
- *
+ * Instantiates a new object on the Sun JVM by bypassing the constructor (meaning code in the constructor will never be
+ * executed and parameters do not have to be known). This is the same method used by the internals of standard Java
+ * serialization, but relies on internal Sun code that may not be present on all JVMs.
+ *
* @author Joe Walnes
* @author Brian Slesinsky
+ * @deprecated As of upcoming use {@link SunUnsafeReflectionProvider}
*/
-public class Sun14ReflectionProvider extends PureJavaReflectionProvider {
-
- private final static Unsafe unsafe;
- private final static Exception exception;
- // references to the Field key are kept in the FieldDictionary
- private transient Map fieldOffsetCache;
- static {
- Unsafe u = null;
- Exception ex = null;
- try {
- Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
- unsafeField.setAccessible(true);
- u = (Unsafe) unsafeField.get(null);
- } catch (SecurityException e) {
- ex = e;
- } catch (NoSuchFieldException e) {
- ex = e;
- } catch (IllegalArgumentException e) {
- ex = e;
- } catch (IllegalAccessException e) {
- ex = e;
- }
- exception = ex;
- unsafe = u;
- }
-
+public class Sun14ReflectionProvider extends SunUnsafeReflectionProvider {
+ /**
+ * @deprecated As of upcoming use {@link SunUnsafeReflectionProvider#SunUnsafeReflectionProvider()}
+ */
public Sun14ReflectionProvider() {
super();
}
+ /**
+ * @deprecated As of upcoming use {@link SunUnsafeReflectionProvider#SunUnsafeReflectionProvider(FieldDictionary)}
+ */
public Sun14ReflectionProvider(FieldDictionary dic) {
super(dic);
}
-
- public Object newInstance(Class type) {
- if (exception != null) {
- throw new ObjectAccessException("Cannot construct " + type.getName(), exception);
- }
- try {
- return unsafe.allocateInstance(type);
- } catch (SecurityException e) {
- throw new ObjectAccessException("Cannot construct " + type.getName(), e);
- } catch (InstantiationException e) {
- throw new ObjectAccessException("Cannot construct " + type.getName(), e);
- } catch (IllegalArgumentException e) {
- throw new ObjectAccessException("Cannot construct " + type.getName(), e);
- }
- }
-
- public void writeField(Object object, String fieldName, Object value, Class definedIn) {
- write(fieldDictionary.field(object.getClass(), fieldName, definedIn), object, value);
- }
-
- private void write(Field field, Object object, Object value) {
- if (exception != null) {
- throw new ObjectAccessException("Could not set field " + object.getClass() + "." + field.getName(), exception);
- }
- try {
- long offset = getFieldOffset(field);
- Class type = field.getType();
- if (type.isPrimitive()) {
- if (type.equals(Integer.TYPE)) {
- unsafe.putInt(object, offset, ((Integer) value).intValue());
- } else if (type.equals(Long.TYPE)) {
- unsafe.putLong(object, offset, ((Long) value).longValue());
- } else if (type.equals(Short.TYPE)) {
- unsafe.putShort(object, offset, ((Short) value).shortValue());
- } else if (type.equals(Character.TYPE)) {
- unsafe.putChar(object, offset, ((Character) value).charValue());
- } else if (type.equals(Byte.TYPE)) {
- unsafe.putByte(object, offset, ((Byte) value).byteValue());
- } else if (type.equals(Float.TYPE)) {
- unsafe.putFloat(object, offset, ((Float) value).floatValue());
- } else if (type.equals(Double.TYPE)) {
- unsafe.putDouble(object, offset, ((Double) value).doubleValue());
- } else if (type.equals(Boolean.TYPE)) {
- unsafe.putBoolean(object, offset, ((Boolean) value).booleanValue());
- } else {
- throw new ObjectAccessException("Could not set field " +
- object.getClass() + "." + field.getName() +
- ": Unknown type " + type);
- }
- } else {
- unsafe.putObject(object, offset, value);
- }
-
- } catch (IllegalArgumentException e) {
- throw new ObjectAccessException("Could not set field " + object.getClass() + "." + field.getName(), e);
- }
- }
- private synchronized long getFieldOffset(Field f)
- {
- Long l = (Long)fieldOffsetCache.get(f);
- if (l == null)
- {
- l = new Long(unsafe.objectFieldOffset(f));
- fieldOffsetCache.put(f, l);
- }
-
- return l.longValue();
- }
-
- protected void validateFieldAccess(Field field) {
- // (overriden) don't mind final fields.
- }
-
private Object readResolve() {
init();
return this;
}
-
- protected void init() {
- super.init();
- fieldOffsetCache = new WeakHashMap();
- }
}
Added: trunk/xstream/src/java/com/thoughtworks/xstream/converters/reflection/SunLimitedUnsafeReflectionProvider.java (0 => 2206)
--- trunk/xstream/src/java/com/thoughtworks/xstream/converters/reflection/SunLimitedUnsafeReflectionProvider.java (rev 0)
+++ trunk/xstream/src/java/com/thoughtworks/xstream/converters/reflection/SunLimitedUnsafeReflectionProvider.java 2014-01-08 16:10:50 UTC (rev 2206)
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2004, 2005 Joe Walnes.
+ * Copyright (C) 2006, 2007, 2008, 2011, 2013, 2014 XStream Committers.
+ * All rights reserved.
+ *
+ * Created on 08. January 2014 by Joerg Schaible, factored out from SunUnsafeReflectionProvider
+ */
+package com.thoughtworks.xstream.converters.reflection;
+
+import java.lang.reflect.Field;
+
+import sun.misc.Unsafe;
+
+
+/**
+ * Instantiates a new object bypassing the constructor using undocumented internal JDK features.
+ * <p>
+ * The code in the constructor will never be executed and parameters do not have to be known. This is the same method
+ * used by the internals of standard Java serialization, but relies on internal code (sun.misc.Unsafe) that may not be
+ * present on all JVMs.
+ * <p>
+ * <p>
+ * The implementation will use standard Java functionality to write any fields. This requires Java 5 as minimum runtime
+ * and is used as fallback on platforms that do not provide the complete implementation level for the internals (like
+ * Dalvik).
+ * <p>
+ *
+ * @author Jörg Schaible
+ * @author Joe Walnes
+ * @author Brian Slesinsky
+ * @since upcoming
+ */
+public class SunLimitedUnsafeReflectionProvider extends PureJavaReflectionProvider {
+
+ protected static final Unsafe unsafe;
+ protected static final Exception exception;
+ static {
+ Unsafe u = null;
+ Exception ex = null;
+ try {
+ Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
+ unsafeField.setAccessible(true);
+ u = (Unsafe)unsafeField.get(null);
+ } catch (SecurityException e) {
+ ex = e;
+ } catch (NoSuchFieldException e) {
+ ex = e;
+ } catch (IllegalArgumentException e) {
+ ex = e;
+ } catch (IllegalAccessException e) {
+ ex = e;
+ }
+ exception = ex;
+ unsafe = u;
+ }
+
+ /**
+ * @since upcoming
+ */
+ public SunLimitedUnsafeReflectionProvider() {
+ super();
+ }
+
+ /**
+ * @since upcoming
+ */
+ public SunLimitedUnsafeReflectionProvider(FieldDictionary fieldDictionary) {
+ super(fieldDictionary);
+ }
+
+ public Object newInstance(Class type) {
+ if (exception != null) {
+ throw new ObjectAccessException("Cannot construct " + type.getName(), exception);
+ }
+ try {
+ return unsafe.allocateInstance(type);
+ } catch (SecurityException e) {
+ throw new ObjectAccessException("Cannot construct " + type.getName(), e);
+ } catch (InstantiationException e) {
+ throw new ObjectAccessException("Cannot construct " + type.getName(), e);
+ } catch (IllegalArgumentException e) {
+ throw new ObjectAccessException("Cannot construct " + type.getName(), e);
+ }
+ }
+
+ protected void validateFieldAccess(Field field) {
+ // (overriden) don't mind final fields.
+ }
+
+ private Object readResolve() {
+ init();
+ return this;
+ }
+}
Property changes on: trunk/xstream/src/java/com/thoughtworks/xstream/converters/reflection/SunLimitedUnsafeReflectionProvider.java
___________________________________________________________________
Added: svn:keywords
Added: svn:eol-style
Copied: trunk/xstream/src/java/com/thoughtworks/xstream/converters/reflection/SunUnsafeReflectionProvider.java (from rev 2203, trunk/xstream/src/java/com/thoughtworks/xstream/converters/reflection/Sun14ReflectionProvider.java) (0 => 2206)
--- trunk/xstream/src/java/com/thoughtworks/xstream/converters/reflection/SunUnsafeReflectionProvider.java (rev 0)
+++ trunk/xstream/src/java/com/thoughtworks/xstream/converters/reflection/SunUnsafeReflectionProvider.java 2014-01-08 16:10:50 UTC (rev 2206)
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2004, 2005 Joe Walnes.
+ * Copyright (C) 2006, 2007, 2008, 2011, 2013, 2014 XStream Committers.
+ * All rights reserved.
+ *
+ * The software in this package is published under the terms of the BSD
+ * style license a copy of which has been included with this distribution in
+ * the LICENSE.txt file.
+ *
+ * Created on 08. January 2014 by Joerg Schaible, renamed from Sun14ReflectionProvider
+ */
+package com.thoughtworks.xstream.converters.reflection;
+
+import java.lang.reflect.Field;
+import java.util.Map;
+import java.util.WeakHashMap;
+
+
+/**
+ * Instantiates a new object bypassing the constructor using undocumented internal JDK features.
+ * <p>
+ * The code in the constructor will never be executed and parameters do not have to be known. This is the same method
+ * used by the internals of standard Java serialization, but relies on internal code (sun.misc.Unsafe) that may not be
+ * present on all JVMs.
+ * <p>
+ * <p>
+ * The implementation will use the same internals to write into fields. This is a lot faster and was additionally the
+ * only possibility to set final fields prior to Java 5.
+ * <p>
+ *
+ * @author Joe Walnes
+ * @author Brian Slesinsky
+ * @author Jörg Schaible
+ * @since upcoming
+ */
+public class SunUnsafeReflectionProvider extends SunLimitedUnsafeReflectionProvider {
+
+ // references to the Field key are kept in the FieldDictionary
+ private transient Map fieldOffsetCache;
+
+ /**
+ * @since upcoming
+ */
+ public SunUnsafeReflectionProvider() {
+ super();
+ }
+
+ /**
+ * @since upcoming
+ */
+ public SunUnsafeReflectionProvider(FieldDictionary dic) {
+ super(dic);
+ }
+
+ public void writeField(Object object, String fieldName, Object value, Class definedIn) {
+ write(fieldDictionary.field(object.getClass(), fieldName, definedIn), object, value);
+ }
+
+ private void write(Field field, Object object, Object value) {
+ if (exception != null) {
+ throw new ObjectAccessException("Could not set field " + object.getClass() + "." + field.getName(),
+ exception);
+ }
+ try {
+ long offset = getFieldOffset(field);
+ Class type = field.getType();
+ if (type.isPrimitive()) {
+ if (type.equals(Integer.TYPE)) {
+ unsafe.putInt(object, offset, ((Integer)value).intValue());
+ } else if (type.equals(Long.TYPE)) {
+ unsafe.putLong(object, offset, ((Long)value).longValue());
+ } else if (type.equals(Short.TYPE)) {
+ unsafe.putShort(object, offset, ((Short)value).shortValue());
+ } else if (type.equals(Character.TYPE)) {
+ unsafe.putChar(object, offset, ((Character)value).charValue());
+ } else if (type.equals(Byte.TYPE)) {
+ unsafe.putByte(object, offset, ((Byte)value).byteValue());
+ } else if (type.equals(Float.TYPE)) {
+ unsafe.putFloat(object, offset, ((Float)value).floatValue());
+ } else if (type.equals(Double.TYPE)) {
+ unsafe.putDouble(object, offset, ((Double)value).doubleValue());
+ } else if (type.equals(Boolean.TYPE)) {
+ unsafe.putBoolean(object, offset, ((Boolean)value).booleanValue());
+ } else {
+ throw new ObjectAccessException("Could not set field "
+ + object.getClass()
+ + "."
+ + field.getName()
+ + ": Unknown type "
+ + type);
+ }
+ } else {
+ unsafe.putObject(object, offset, value);
+ }
+
+ } catch (IllegalArgumentException e) {
+ throw new ObjectAccessException("Could not set field " + object.getClass() + "." + field.getName(), e);
+ }
+ }
+
+ private synchronized long getFieldOffset(Field f) {
+ Long l = (Long)fieldOffsetCache.get(f);
+ if (l == null) {
+ l = new Long(unsafe.objectFieldOffset(f));
+ fieldOffsetCache.put(f, l);
+ }
+
+ return l.longValue();
+ }
+
+ private Object readResolve() {
+ init();
+ return this;
+ }
+
+ protected void init() {
+ super.init();
+ fieldOffsetCache = new WeakHashMap();
+ }
+}
Modified: trunk/xstream/src/java/com/thoughtworks/xstream/core/JVM.java (2205 => 2206)
--- trunk/xstream/src/java/com/thoughtworks/xstream/core/JVM.java 2013-12-27 18:42:46 UTC (rev 2205)
+++ trunk/xstream/src/java/com/thoughtworks/xstream/core/JVM.java 2014-01-08 16:10:50 UTC (rev 2206)
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2004, 2005, 2006 Joe Walnes.
- * Copyright (C) 2006, 2007, 2008, 2010, 2011, 2012, 2013 XStream Committers.
+ * Copyright (C) 2006, 2007, 2008, 2010, 2011, 2012, 2013, 2014 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -41,6 +41,7 @@
private static final boolean isSwingAvailable;
private static final boolean isSQLAvailable;
private static final boolean canAllocateWithUnsafe;
+ private static final boolean canWriteWithUnsafe;
private static final boolean optimizedTreeSetAddAll;
private static final boolean optimizedTreeMapPutAll;
private static final boolean canParseUTCDateFormat;
@@ -52,28 +53,72 @@
private static final boolean reverseFieldOrder = false;
private static final Class reflectionProviderType;
- static class Broken {
- Broken() {
+ static class Test {
+ private Object o;
+ private char c;
+ private byte b;
+ private short s;
+ private int i;
+ private long l;
+ private float f;
+ private double d;
+ private boolean bool;
+ Test() {
throw new UnsupportedOperationException();
}
}
-
+
static {
boolean test = true;
+ Object unsafe = null;
try {
Class unsafeClass = Class.forName("sun.misc.Unsafe");
Field unsafeField = unsafeClass.getDeclaredField("theUnsafe");
unsafeField.setAccessible(true);
- Object unsafe = unsafeField.get(null);
+ unsafe = unsafeField.get(null);
Method allocateInstance = unsafeClass.getDeclaredMethod("allocateInstance", new Class[]{Class.class});
allocateInstance.setAccessible(true);
- test = allocateInstance.invoke(unsafe, new Object[]{Broken.class}) != null;
+ test = allocateInstance.invoke(unsafe, new Object[]{Test.class}) != null;
} catch (Exception e) {
test = false;
} catch (Error e) {
test = false;
}
canAllocateWithUnsafe = test;
+ test = false;
+ Class type = PureJavaReflectionProvider.class;
+ if (canUseSunUnsafeReflectionProvider()) {
+ Class cls = loadClassForName("com.thoughtworks.xstream.converters.reflection.SunUnsafeReflectionProvider");
+ if (cls != null) {
+ try {
+ ReflectionProvider provider = (ReflectionProvider)DependencyInjectionFactory.newInstance(cls, null);
+ Test t = (Test)provider.newInstance(Test.class);
+ try {
+ provider.writeField(t, "o", "object", Test.class);
+ provider.writeField(t, "c", new Character('c'), Test.class);
+ provider.writeField(t, "b", new Byte((byte)1), Test.class);
+ provider.writeField(t, "s", new Short((short)1), Test.class);
+ provider.writeField(t, "i", new Integer(1), Test.class);
+ provider.writeField(t, "l", new Long(1), Test.class);
+ provider.writeField(t, "f", new Float(1), Test.class);
+ provider.writeField(t, "d", new Double(1), Test.class);
+ provider.writeField(t, "bool", Boolean.TRUE, Test.class);
+ test = true;
+ } catch(IncompatibleClassChangeError e) {
+ cls = null;
+ } catch (ObjectAccessException e) {
+ cls = null;
+ }
+ if (cls == null) {
+ cls = loadClassForName("com.thoughtworks.xstream.converters.reflection.SunLimitedUnsafeReflectionProvider");
+ }
+ type = cls;
+ } catch (ObjectAccessException e) {
+ }
+ }
+ }
+ reflectionProviderType = type;
+ canWriteWithUnsafe = test;
Comparator comparator = new Comparator() {
public int compare(Object o1, Object o2) {
throw new RuntimeException();
@@ -117,20 +162,6 @@
isAWTAvailable = loadClassForName("java.awt.Color", false) != null;
isSwingAvailable = loadClassForName("javax.swing.LookAndFeel", false) != null;
isSQLAvailable = loadClassForName("java.sql.Date") != null;
-
- Class type = PureJavaReflectionProvider.class;
- if (canUseSun14ReflectionProvider()) {
- Class cls = loadClassForName("com.thoughtworks.xstream.converters.reflection.Sun14ReflectionProvider");
- if (cls != null) {
- try {
- ReflectionProvider provider = (ReflectionProvider)DependencyInjectionFactory.newInstance(cls, null);
- provider.newInstance(JVM.class);
- type = cls;
- } catch (ObjectAccessException e) {
- }
- }
- }
- reflectionProviderType = type;
}
/**
@@ -322,33 +353,19 @@
*/
public synchronized ReflectionProvider bestReflectionProvider() {
if (reflectionProvider == null) {
- try {
- String className = null;
- if (canUseSun14ReflectionProvider()) {
- className = "com.thoughtworks.xstream.converters.reflection.Sun14ReflectionProvider";
- }
- if (className != null) {
- Class cls = loadClassForName(className);
- if (cls != null) {
- reflectionProvider = (ReflectionProvider) cls.newInstance();
- }
- }
- } catch (InstantiationException e) {
- } catch (IllegalAccessException e) {
- } catch (AccessControlException e) {
- // thrown when trying to access sun.misc package in Applet context
- }
- if (reflectionProvider == null) {
- reflectionProvider = new PureJavaReflectionProvider();
- }
+ reflectionProvider = newReflectionProvider();
}
return reflectionProvider;
}
- private static boolean canUseSun14ReflectionProvider() {
+ private static boolean canUseSunUnsafeReflectionProvider() {
return canAllocateWithUnsafe && is14();
}
+ private static boolean canUseSunLimitedUnsafeReflectionProvider() {
+ return canWriteWithUnsafe;
+ }
+
/**
* @deprecated As of 1.4.5
*/
@@ -440,27 +457,21 @@
}
public static void main(String[] args) {
- boolean reverse = false;
+ boolean reverseJDK = false;
Field[] fields = AttributedString.class.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
if (fields[i].getName().equals("text")) {
- reverse = i > 3;
+ reverseJDK = i > 3;
break;
}
}
- class Test {
- String first;
- String second;
- String third;
- String fourth;
- }
- if (reverse) {
- fields = Test.class.getDeclaredFields();
- for (int i = 0; i < fields.length; i++) {
- if (fields[i].getName().equals("first")) {
- reverse = i > 3;
- break;
- }
+
+ boolean reverseLocal = false;
+ fields = Test.class.getDeclaredFields();
+ for (int i = 0; i < fields.length; i++) {
+ if (fields[i].getName().equals("o")) {
+ reverseLocal = i > 3;
+ break;
}
}
@@ -488,7 +499,8 @@
System.out.println("java.vendor: " + System.getProperty("java.vendor"));
System.out.println("java.vm.name: " + System.getProperty("java.vm.name"));
System.out.println("Version: " + majorJavaVersion);
- System.out.println("XStream support for enhanced Mode: " + canUseSun14ReflectionProvider());
+ System.out.println("XStream support for enhanced Mode: " + canUseSunUnsafeReflectionProvider());
+ System.out.println("XStream support for reduced Mode: " + canUseSunLimitedUnsafeReflectionProvider());
System.out.println("Supports AWT: " + isAWTAvailable());
System.out.println("Supports Swing: " + isSwingAvailable());
System.out.println("Supports SQL: " + isSQLAvailable());
@@ -498,6 +510,7 @@
System.out.println("Optimized TreeMap.putAll: " + hasOptimizedTreeMapPutAll());
System.out.println("Can parse UTC date format: " + canParseUTCDateFormat());
System.out.println("Can create derive ObjectOutputStream: " + canCreateDerivedObjectOutputStream());
- System.out.println("Reverse field order detected (only if JVM class itself has been compiled): " + reverse);
+ System.out.println("Reverse field order detected for JDK: " + reverseJDK);
+ System.out.println("Reverse field order detected (only if JVM class itself has been compiled): " + reverseLocal);
}
}
Modified: trunk/xstream/src/test/com/thoughtworks/xstream/converters/extended/ToAttributedValueConverterTest.java (2205 => 2206)
--- trunk/xstream/src/test/com/thoughtworks/xstream/converters/extended/ToAttributedValueConverterTest.java 2013-12-27 18:42:46 UTC (rev 2205)
+++ trunk/xstream/src/test/com/thoughtworks/xstream/converters/extended/ToAttributedValueConverterTest.java 2014-01-08 16:10:50 UTC (rev 2206)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011, 2013 XStream Committers.
+ * Copyright (C) 2011, 2013, 2014 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -25,7 +25,7 @@
import com.thoughtworks.xstream.converters.collections.ArrayConverter;
import com.thoughtworks.xstream.converters.reflection.ReflectionConverter;
import com.thoughtworks.xstream.converters.reflection.ReflectionProvider;
-import com.thoughtworks.xstream.converters.reflection.Sun14ReflectionProvider;
+import com.thoughtworks.xstream.converters.reflection.SunUnsafeReflectionProvider;
import com.thoughtworks.xstream.core.ClassLoaderReference;
import com.thoughtworks.xstream.core.DefaultConverterLookup;
import com.thoughtworks.xstream.core.TreeMarshaller;
@@ -35,7 +35,6 @@
import com.thoughtworks.xstream.io.xml.CompactWriter;
import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
import com.thoughtworks.xstream.io.xml.XppDriver;
-import com.thoughtworks.xstream.io.xml.XppReader;
import com.thoughtworks.xstream.mapper.ArrayMapper;
import com.thoughtworks.xstream.mapper.ClassAliasingMapper;
import com.thoughtworks.xstream.mapper.DefaultImplementationsMapper;
@@ -66,7 +65,7 @@
classAliasingMapper.addClassAlias("open-source", OpenSourceSoftware.class);
mapper = new DefaultImplementationsMapper(new ArrayMapper(classAliasingMapper));
- reflectionProvider = new Sun14ReflectionProvider();
+ reflectionProvider = new SunUnsafeReflectionProvider();
driver = new XppDriver();
converterLookup = new DefaultConverterLookup();
Deleted: trunk/xstream/src/test/com/thoughtworks/xstream/converters/reflection/Sun14ReflectionProviderTest.java (2205 => 2206)
--- trunk/xstream/src/test/com/thoughtworks/xstream/converters/reflection/Sun14ReflectionProviderTest.java 2013-12-27 18:42:46 UTC (rev 2205)
+++ trunk/xstream/src/test/com/thoughtworks/xstream/converters/reflection/Sun14ReflectionProviderTest.java 2014-01-08 16:10:50 UTC (rev 2206)
@@ -1,99 +0,0 @@
-/*
- * Copyright (C) 2004 Joe Walnes.
- * Copyright (C) 2006, 2007, 2013 XStream Committers.
- * All rights reserved.
- *
- * The software in this package is published under the terms of the BSD
- * style license a copy of which has been included with this distribution in
- * the LICENSE.txt file.
- *
- * Created on 08. March 2004 by Joe Walnes
- */
-package com.thoughtworks.xstream.converters.reflection;
-
-public class Sun14ReflectionProviderTest extends AbstractReflectionProviderTest {
-
- // inherits tests from superclass
-
- public ReflectionProvider createReflectionProvider() {
- return new Sun14ReflectionProvider();
- }
-
- public void testCanWriteFinalFields() {
- WithFinalFields thingy = new WithFinalFields();
- reflectionProvider.writeField(thingy, "finalField", "zero", WithFinalFields.class);
- assertEquals("zero", thingy.finalField);
-
- reflectionProvider.writeField(thingy, "finalInt", new Integer(1), WithFinalFields.class);
- assertEquals(1, thingy.finalInt);
-
- reflectionProvider.writeField(thingy, "finalLong", new Long(2), WithFinalFields.class);
- assertEquals(2, thingy.finalLong);
-
- reflectionProvider.writeField(thingy, "finalShort", new Short((short) 3), WithFinalFields.class);
- assertEquals(3, thingy.finalShort);
-
- reflectionProvider.writeField(thingy, "finalChar", new Character('4'), WithFinalFields.class);
- assertEquals('4', thingy.finalChar);
-
- reflectionProvider.writeField(thingy, "finalByte", new Byte((byte) 5), WithFinalFields.class);
- assertEquals(5, thingy.finalByte);
-
- reflectionProvider.writeField(thingy, "finalFloat", new Float(0.6), WithFinalFields.class);
- assertEquals(0.6f, thingy.finalFloat, 0.0);
-
- reflectionProvider.writeField(thingy, "finalDouble", new Double(0.7), WithFinalFields.class);
- assertEquals(0.7, thingy.finalDouble, 0.0);
-
- reflectionProvider.writeField(thingy, "finalBoolean", new Boolean(true), WithFinalFields.class);
- assertEquals(true, thingy.finalBoolean);
-
- reflectionProvider.writeField(thingy, "finalBoolean", new Boolean(false), null);
- assertEquals(false, thingy.finalBoolean);
- }
-
- private static class WithFinalFields {
- final String finalField;
- final int finalInt;
- final long finalLong;
- final short finalShort;
- final char finalChar;
- final byte finalByte;
- final float finalFloat;
- final double finalDouble;
- final boolean finalBoolean;
-
- private WithFinalFields() {
- finalField = null;
- finalChar = '\0';
- finalInt = 0;
- finalLong = 0;
- finalShort = 0;
- finalByte = 0;
- finalFloat = 0.0f;
- finalDouble = 0.0;
- finalBoolean = false;
- }
-
- }
-
- public void testCanInstantiateWithoutInitializer() {
- assertCanCreate(Unistantiatable.class);
- }
-
- static class Unistantiatable {
- {
- if (true) {
- throw new IllegalStateException("<init>");
- }
- }
-
- public Unistantiatable() {
- throw new IllegalStateException("ctor");
- }
-
- public Unistantiatable(String s) {
- throw new IllegalStateException("ctor(String)");
- }
- }
-}
\ No newline at end of file
Added: trunk/xstream/src/test/com/thoughtworks/xstream/converters/reflection/SunLimitedUnsafeReflectionProviderTest.java (0 => 2206)
--- trunk/xstream/src/test/com/thoughtworks/xstream/converters/reflection/SunLimitedUnsafeReflectionProviderTest.java (rev 0)
+++ trunk/xstream/src/test/com/thoughtworks/xstream/converters/reflection/SunLimitedUnsafeReflectionProviderTest.java 2014-01-08 16:10:50 UTC (rev 2206)
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2004 Joe Walnes.
+ * Copyright (C) 2006, 2007, 2013, 2014 XStream Committers.
+ * All rights reserved.
+ *
+ * Created on 08. January 2014 by Joerg Schaible, factored out from SunUnsafeReflectionProviderTest
+ */
+package com.thoughtworks.xstream.converters.reflection;
+
+public class SunLimitedUnsafeReflectionProviderTest extends AbstractReflectionProviderTest {
+
+ // inherits tests from superclass
+
+ public ReflectionProvider createReflectionProvider() {
+ return new SunLimitedUnsafeReflectionProvider();
+ }
+
+ protected static class WithFinalFields {
+ final String finalField;
+ final int finalInt;
+ final long finalLong;
+ final short finalShort;
+ final char finalChar;
+ final byte finalByte;
+ final float finalFloat;
+ final double finalDouble;
+ final boolean finalBoolean;
+
+ private WithFinalFields() {
+ finalField = null;
+ finalChar = '\0';
+ finalInt = 0;
+ finalLong = 0;
+ finalShort = 0;
+ finalByte = 0;
+ finalFloat = 0.0f;
+ finalDouble = 0.0;
+ finalBoolean = false;
+ }
+
+ }
+
+ public void testCanWriteFinalFields() {
+ WithFinalFields thingy = new WithFinalFields();
+ reflectionProvider.writeField(thingy, "finalField", "zero", WithFinalFields.class);
+ assertEquals("zero", thingy.finalField);
+
+ reflectionProvider.writeField(thingy, "finalInt", new Integer(1), WithFinalFields.class);
+ assertEquals(1, thingy.finalInt);
+
+ reflectionProvider.writeField(thingy, "finalLong", new Long(2), WithFinalFields.class);
+ assertEquals(2, thingy.finalLong);
+
+ reflectionProvider.writeField(thingy, "finalShort", new Short((short)3), WithFinalFields.class);
+ assertEquals(3, thingy.finalShort);
+
+ reflectionProvider.writeField(thingy, "finalChar", new Character('4'), WithFinalFields.class);
+ assertEquals('4', thingy.finalChar);
+
+ reflectionProvider.writeField(thingy, "finalByte", new Byte((byte)5), WithFinalFields.class);
+ assertEquals(5, thingy.finalByte);
+
+ reflectionProvider.writeField(thingy, "finalFloat", new Float(0.6), WithFinalFields.class);
+ assertEquals(0.6f, thingy.finalFloat, 0.0);
+
+ reflectionProvider.writeField(thingy, "finalDouble", new Double(0.7), WithFinalFields.class);
+ assertEquals(0.7, thingy.finalDouble, 0.0);
+
+ reflectionProvider.writeField(thingy, "finalBoolean", new Boolean(true), WithFinalFields.class);
+ assertEquals(true, thingy.finalBoolean);
+
+ reflectionProvider.writeField(thingy, "finalBoolean", new Boolean(false), null);
+ assertEquals(false, thingy.finalBoolean);
+ }
+
+ protected static class Unistantiatable {
+ {
+ if (true) {
+ throw new IllegalStateException("<init>");
+ }
+ }
+
+ public Unistantiatable() {
+ throw new IllegalStateException("ctor");
+ }
+
+ public Unistantiatable(String s) {
+ throw new IllegalStateException("ctor(String)");
+ }
+ }
+
+ public void testCanInstantiateWithoutInitializer() {
+ assertCanCreate(Unistantiatable.class);
+ }
+}
Property changes on: trunk/xstream/src/test/com/thoughtworks/xstream/converters/reflection/SunLimitedUnsafeReflectionProviderTest.java
___________________________________________________________________
Added: svn:keywords
Added: svn:eol-style
Copied: trunk/xstream/src/test/com/thoughtworks/xstream/converters/reflection/SunUnsafeReflectionProviderTest.java (from rev 2203, trunk/xstream/src/test/com/thoughtworks/xstream/converters/reflection/Sun14ReflectionProviderTest.java) (0 => 2206)
--- trunk/xstream/src/test/com/thoughtworks/xstream/converters/reflection/SunUnsafeReflectionProviderTest.java (rev 0)
+++ trunk/xstream/src/test/com/thoughtworks/xstream/converters/reflection/SunUnsafeReflectionProviderTest.java 2014-01-08 16:10:50 UTC (rev 2206)
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2004 Joe Walnes.
+ * Copyright (C) 2006, 2007, 2013, 2014 XStream Committers.
+ * All rights reserved.
+ *
+ * The software in this package is published under the terms of the BSD
+ * style license a copy of which has been included with this distribution in
+ * the LICENSE.txt file.
+ *
+ * Created on 08. January 2014 by Joerg Schaible, renamed from Sun14RelfectrionProviderTest.
+ */
+package com.thoughtworks.xstream.converters.reflection;
+
+public class SunUnsafeReflectionProviderTest extends SunLimitedUnsafeReflectionProviderTest {
+
+ // inherits tests from superclass
+
+ public ReflectionProvider createReflectionProvider() {
+ return new SunUnsafeReflectionProvider();
+ }
+}
\ No newline at end of file
Modified: trunk/xstream-distribution/src/content/changes.html (2205 => 2206)
--- trunk/xstream-distribution/src/content/changes.html 2013-12-27 18:42:46 UTC (rev 2205)
+++ trunk/xstream-distribution/src/content/changes.html 2014-01-08 16:10:50 UTC (rev 2206)
@@ -1,7 +1,7 @@
<html>
<!--
Copyright (C) 2005, 2006 Joe Walnes.
- Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 XStream committers.
+ Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 XStream committers.
All rights reserved.
The software in this package is published under the terms of the BSD
@@ -64,6 +64,8 @@
<ul>
<li>java.bean.EventHandler no longer handled automatically because of severe security vulnerability.</li>
+ <li>JIRA:XSTR-751: New SunLimitedUnsafeReflectionProvider that uses undocumented features only to allocate new
+ instances as required on Dalvik.</li>
<li>Fix instantiation of AnnotationMapper that requires ConverterLookup and ConverterRegistry to be the same
instance.</li>
</ul>
@@ -80,6 +82,9 @@
<h2>API changes</h2>
<ul>
+ <li>Added c.t.x.converters.reflection.SunLimitedUnsafeReflectionProvider.</li>
+ <li>Deprecated c.t.x.converters.reflection.Sun14ReflectionProvider in favor of new
+ c.t.x.converters.reflection.SunUnsafeReflectionProvider.</li>
<li>Added c.t.x.converters.reflection.ReflectionConverter(Mapper,ReflectionProvider,Class).</li>
</ul>
Modified: trunk/xstream-distribution/src/content/faq.html (2205 => 2206)
--- trunk/xstream-distribution/src/content/faq.html 2013-12-27 18:42:46 UTC (rev 2205)
+++ trunk/xstream-distribution/src/content/faq.html 2014-01-08 16:10:50 UTC (rev 2206)
@@ -1,7 +1,7 @@
<html>
<!--
Copyright (C) 2005, 2006 Joe Walnes.
- Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 XStream committers.
+ Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 XStream committers.
All rights reserved.
The software in this package is published under the terms of the BSD
@@ -52,10 +52,12 @@
<!-- ...................................................... -->
<h2 id="Compatibility_enhanced_mode_jvm">Which JVMs allow XStream to operate in enhanced mode?</h2>
- <p>XStream will check since version 1.4.5 a working enhanced mode dynamically if it is available based on internal
- Sun classes. This enhanced mode is known to be working on the Oracle/Sun, Apple, HP, IBM and Blackdown 1.4 JVMs and
- onwards, for Hitachi, SAP and Diablo from 1.5 and onwards, for BEA JRockit starting with R25.1.0 and for OpenJDK.
- Note, that an active SecurityManager might prevent the usage of the enhanced mode also.</p>
+ <p>XStream will check since version 1.4.5 a working enhanced mode dynamically if it is available based on
+ undocumented internal Java runtime classes. This enhanced mode is known to be working on the Oracle/Sun, Apple, HP,
+ IBM and Blackdown 1.4 JVMs and onwards, for IcedTea 6 and onwards, for Hitachi, SAP and Diablo from 1.5 and
+ onwards, for BEA JRockit starting with R25.1.0. Generally it works for all modern Java runtimes based on OpenJDK.
+ Android basically supports the enhanced mode, but its security model limits the types that can be handled. Note,
+ that an active SecurityManager might prevent the usage of the enhanced mode also.</p>
<!-- ...................................................... -->
<h2 id="Compatibility_enhanced_mode_advantage">What are the advantages of using enhanced mode over pure Java mode?</h2>
@@ -88,7 +90,7 @@
<h2 id="Compatibility_Android">Can I use XStream in an Android application?</h2>
<p>XStream does work in Android 1.0, but is reported to have limited capabilities. Since XStream 1.4 Android is
- treated at least as JD 5 platform, but it e.g. does not include the java.beans package. Therefore you cannot use
+ treated at least as JDK 5 platform, but it e.g. does not include the java.beans package. Therefore you cannot use
the JavaBeanConverter. Note, that Android provides an XML Pull Parser, therefore XStream can work without
additional dependencies.</p>
To unsubscribe from this list please visit:
