Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Defer reflective access to Java core modules (1.4) #218

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions xstream-distribution/src/content/changes.html
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,16 @@
filter for the appropriate milestone.
</p>

<h1 id="upcoming">Upcoming</h1>

<p>Not yet released.</p>

<h2>Major changes</h2>

<ul>
<li>GHPR:#216: Defer reflective access to Java core modules.</li>
</ul>

<h1 id="1.4.12">1.4.12</h1>

<p>Released April 12, 2020.</p>
Expand Down
3 changes: 2 additions & 1 deletion xstream-distribution/src/content/team.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<html>
<!--
Copyright (C) 2005, 2006 Joe Walnes.
Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2013, 2014, 2015, 2016, 2017, 2019 XStream committers.
Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2013, 2014, 2015, 2016, 2017, 2019, 2020 XStream committers.
All rights reserved.

The software in this package is published under the terms of the BSD
Expand Down Expand Up @@ -126,6 +126,7 @@ <h2 id="contributors">Contributors</h2>
<li>Matej Cimbora</li>
<li>Baptiste Mesta</li>
<li>Wes Wannemacher</li>
<li>Falko Modler</li>
</ul>

<p>Please direct all correspondence about XStream to the <a href="mailing-lists.html">mailing list</a>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2004, 2005 Joe Walnes.
* Copyright (C) 2006, 2007, 2008, 2009, 2013 XStream Committers.
* Copyright (C) 2006, 2007, 2008, 2009, 2013, 2020 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
Expand Down Expand Up @@ -44,7 +44,6 @@
*/
public class PropertiesConverter implements Converter {

private final static Field defaultsField = Fields.locate(Properties.class, Properties.class, false);
private final boolean sort;

public PropertiesConverter() {
Expand All @@ -69,8 +68,8 @@ public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingC
writer.addAttribute("value", entry.getValue().toString());
writer.endNode();
}
if (defaultsField != null) {
Properties defaults = (Properties)Fields.read(defaultsField, properties);
if (Reflections.defaultsField != null) {
Properties defaults = (Properties)Fields.read(Reflections.defaultsField, properties);
if (defaults != null) {
writer.startNode("defaults");
marshal(defaults, writer, context);
Expand Down Expand Up @@ -102,4 +101,7 @@ public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext co
}
}

private static class Reflections {
private final static Field defaultsField = Fields.locate(Properties.class, Properties.class, false);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2004, 2005 Joe Walnes.
* Copyright (C) 2006, 2007, 2010, 2011, 2013, 2016, 2018 XStream Committers.
* Copyright (C) 2006, 2007, 2010, 2011, 2013, 2016, 2018, 2020 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
Expand Down Expand Up @@ -47,7 +47,6 @@ public int compare(Object o1, Object o2) {
}

private final static Comparator NULL_MARKER = new NullComparator();
private final static Field comparatorField = Fields.locate(TreeMap.class, Comparator.class, false);

public TreeMapConverter(Mapper mapper) {
super(mapper, TreeMap.class);
Expand All @@ -71,7 +70,7 @@ protected void marshalComparator(Comparator comparator, HierarchicalStreamWriter
}

public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
TreeMap result = comparatorField != null ? new TreeMap() : null;
TreeMap result = Reflections.comparatorField != null ? new TreeMap() : null;
final Comparator comparator = unmarshalComparator(reader, context, result);
if (result == null) {
result = comparator == null || comparator == NULL_MARKER ? new TreeMap() : new TreeMap(comparator);
Expand Down Expand Up @@ -116,19 +115,23 @@ protected void populateTreeMap(HierarchicalStreamReader reader, UnmarshallingCon
populateMap(reader, context, result, sortedMap);
try {
if (JVM.hasOptimizedTreeMapPutAll()) {
if (comparator != null && comparatorField != null) {
comparatorField.set(result, comparator);
if (comparator != null && Reflections.comparatorField != null) {
Reflections.comparatorField.set(result, comparator);
}
result.putAll(sortedMap); // internal optimization will not call comparator
} else if (comparatorField != null) {
comparatorField.set(result, sortedMap.comparator());
} else if (Reflections.comparatorField != null) {
Reflections.comparatorField.set(result, sortedMap.comparator());
result.putAll(sortedMap); // "sort" by index
comparatorField.set(result, comparator);
Reflections.comparatorField.set(result, comparator);
} else {
result.putAll(sortedMap); // will use comparator for already sorted map
}
} catch (final IllegalAccessException e) {
throw new ObjectAccessException("Cannot set comparator of TreeMap", e);
}
}

private static class Reflections {
private final static Field comparatorField = Fields.locate(TreeMap.class, Comparator.class, false);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2004, 2005 Joe Walnes.
* Copyright (C) 2006, 2007, 2010, 2011, 2013, 2014, 2016, 2018 XStream Committers.
* Copyright (C) 2006, 2007, 2010, 2011, 2013, 2014, 2016, 2018, 2020 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
Expand Down Expand Up @@ -41,40 +41,6 @@
*/
public class TreeSetConverter extends CollectionConverter {
private transient TreeMapConverter treeMapConverter;
private final static Field sortedMapField;
private final static Object constantValue;
static {
Object value = null;
sortedMapField = JVM.hasOptimizedTreeSetAddAll() ? Fields.locate(TreeSet.class, SortedMap.class, false) : null;
if (sortedMapField != null) {
TreeSet set = new TreeSet();
set.add("1");
set.add("2");

Map backingMap = null;
try {
backingMap = (Map)sortedMapField.get(set);
} catch (final IllegalAccessException e) {
// give up;
}
if (backingMap != null) {
Object[] values = backingMap.values().toArray();
if (values[0] == values[1]) {
value = values[0];
}
}
} else {
Field valueField = Fields.locate(TreeSet.class, Object.class, true);
if (valueField != null) {
try {
value = valueField.get(null);
} catch (final IllegalAccessException e) {
// give up;
}
}
}
constantValue = value;
}

public TreeSetConverter(Mapper mapper) {
super(mapper, TreeSet.class);
Expand All @@ -93,11 +59,11 @@ public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext co
Comparator unmarshalledComparator = treeMapConverter.unmarshalComparator(reader, context, null);
boolean inFirstElement = unmarshalledComparator instanceof Mapper.Null;
Comparator comparator = inFirstElement ? null : unmarshalledComparator;
if (sortedMapField != null) {
if (Reflections.sortedMapField != null) {
TreeSet possibleResult = comparator == null ? new TreeSet() : new TreeSet(comparator);
Object backingMap = null;
try {
backingMap = sortedMapField.get(possibleResult);
backingMap = Reflections.sortedMapField.get(possibleResult);
} catch (IllegalAccessException e) {
throw new ObjectAccessException("Cannot get backing map of TreeSet", e);
}
Expand Down Expand Up @@ -135,7 +101,10 @@ protected void populateMap(HierarchicalStreamReader reader,
UnmarshallingContext context, Map map, final Map target) {
populateCollection(reader, context, new AbstractList() {
public boolean add(Object object) {
return target.put(object, constantValue != null ? constantValue : object) != null;
return target
.put(object, Reflections.constantValue != null
? Reflections.constantValue
: object) != null;
}

public Object get(int location) {
Expand All @@ -156,4 +125,42 @@ protected void putCurrentEntryIntoMap(HierarchicalStreamReader reader, Unmarshal
};
return this;
}

private static class Reflections {

private final static Field sortedMapField;
private final static Object constantValue;
static {
Object value = null;
sortedMapField = JVM.hasOptimizedTreeSetAddAll() ? Fields.locate(TreeSet.class, SortedMap.class, false) : null;
if (sortedMapField != null) {
TreeSet set = new TreeSet();
set.add("1");
set.add("2");

Map backingMap = null;
try {
backingMap = (Map)sortedMapField.get(set);
} catch (final IllegalAccessException e) {
// give up;
}
if (backingMap != null) {
Object[] values = backingMap.values().toArray();
if (values[0] == values[1]) {
value = values[0];
}
}
} else {
Field valueField = Fields.locate(TreeSet.class, Object.class, true);
if (valueField != null) {
try {
value = valueField.get(null);
} catch (final IllegalAccessException e) {
// give up;
}
}
}
constantValue = value;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2005 Joe Walnes.
* Copyright (C) 2006, 2007, 2008, 2009, 2013 XStream Committers.
* Copyright (C) 2006, 2007, 2008, 2009, 2013, 2020 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
Expand Down Expand Up @@ -37,18 +37,16 @@
*/
public class EnumMapConverter extends MapConverter {

private final static Field typeField = Fields.locate(EnumMap.class, Class.class, false);

public EnumMapConverter(Mapper mapper) {
super(mapper);
}

public boolean canConvert(Class type) {
return typeField != null && type == EnumMap.class;
return type == EnumMap.class && Reflections.typeField != null;
}

public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {
Class type = (Class) Fields.read(typeField, source);
Class type = (Class) Fields.read(Reflections.typeField, source);
String attributeName = mapper().aliasForSystemAttribute("enum-type");
if (attributeName != null) {
writer.addAttribute(attributeName, mapper().serializedClass(type));
Expand All @@ -67,4 +65,8 @@ public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext co
populateMap(reader, context, map);
return map;
}

private static class Reflections {
private final static Field typeField = Fields.locate(EnumMap.class, Class.class, false);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2005 Joe Walnes.
* Copyright (C) 2006, 2007, 2008, 2009, 2018 XStream Committers.
* Copyright (C) 2006, 2007, 2008, 2009, 2018, 2020 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
Expand Down Expand Up @@ -39,20 +39,19 @@
*/
public class EnumSetConverter implements Converter {

private final static Field typeField = Fields.locate(EnumSet.class, Class.class, false);
private final Mapper mapper;

public EnumSetConverter(Mapper mapper) {
this.mapper = mapper;
}

public boolean canConvert(Class type) {
return typeField != null && type != null && EnumSet.class.isAssignableFrom(type);
return type != null && EnumSet.class.isAssignableFrom(type) && Reflections.typeField != null;
}

public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {
EnumSet set = (EnumSet) source;
Class enumTypeForSet = (Class) Fields.read(typeField, set);
Class enumTypeForSet = (Class) Fields.read(Reflections.typeField, set);
String attributeName = mapper.aliasForSystemAttribute("enum-type");
if (attributeName != null) {
writer.addAttribute(attributeName, mapper.serializedClass(enumTypeForSet));
Expand Down Expand Up @@ -93,4 +92,7 @@ public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext co
return set;
}

private static class Reflections {
private final static Field typeField = Fields.locate(EnumSet.class, Class.class, false);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2004, 2005 Joe Walnes.
* Copyright (C) 2006, 2007, 2008, 2010, 2013, 2018 XStream Committers.
* Copyright (C) 2006, 2007, 2008, 2010, 2013, 2018, 2020 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
Expand Down Expand Up @@ -39,12 +39,6 @@ public class DynamicProxyConverter implements Converter {

private ClassLoaderReference classLoaderReference;
private Mapper mapper;
private static final Field HANDLER = Fields.locate(Proxy.class, InvocationHandler.class, false);
private static final InvocationHandler DUMMY = new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return null;
}
};

/**
* @deprecated As of 1.4.5 use {@link #DynamicProxyConverter(Mapper, ClassLoaderReference)}
Expand Down Expand Up @@ -121,16 +115,26 @@ public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext co
Class[] interfacesAsArray = new Class[interfaces.size()];
interfaces.toArray(interfacesAsArray);
Object proxy = null;
if (HANDLER != null) { // we will not be able to resolve references to the proxy
proxy = Proxy.newProxyInstance(classLoaderReference.getReference(), interfacesAsArray, DUMMY);
if (Reflections.HANDLER != null) { // we will not be able to resolve references to the proxy
proxy = Proxy.newProxyInstance(classLoaderReference.getReference(), interfacesAsArray, Reflections.DUMMY);
}
handler = (InvocationHandler) context.convertAnother(proxy, handlerType);
reader.moveUp();
if (HANDLER != null) {
Fields.write(HANDLER, proxy, handler);
if (Reflections.HANDLER != null) {
Fields.write(Reflections.HANDLER, proxy, handler);
} else {
proxy = Proxy.newProxyInstance(classLoaderReference.getReference(), interfacesAsArray, handler);
}
return proxy;
}

private static class Reflections {

private static final Field HANDLER = Fields.locate(Proxy.class, InvocationHandler.class, false);
private static final InvocationHandler DUMMY = new InvocationHandler() {
public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
return null;
}
};
}
}
Loading