Skip to content

Commit 8985ab4

Browse files
committed
support additional class loaders for savables
1 parent 7d11616 commit 8985ab4

3 files changed

Lines changed: 58 additions & 8 deletions

File tree

jme3-core/src/main/java/com/jme3/export/SavableClassUtil.java

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import java.lang.reflect.Field;
4141
import java.lang.reflect.InvocationTargetException;
4242
import java.util.ArrayList;
43+
import java.util.Collection;
4344
import java.util.HashMap;
4445
import java.util.List;
4546
import java.util.logging.Level;
@@ -198,9 +199,13 @@ public static Savable fromName(String className)
198199
* @throws ClassNotFoundException thrown if the class name is not in the classpath.
199200
* @throws SecurityException thrown if the filter rejects the class name.
200201
*/
201-
public static Savable fromName(String className, SavableClassFilter classFilter)
202-
throws ClassNotFoundException, IllegalAccessException,
203-
InstantiationException, InvocationTargetException {
202+
public static Savable fromName(String className, SavableClassFilter classFilter)
203+
throws ClassNotFoundException, IllegalAccessException, InstantiationException, InvocationTargetException {
204+
return fromName(className, classFilter, null);
205+
}
206+
207+
public static Savable fromName(String className, SavableClassFilter classFilter, Collection<ClassLoader> additionalClassLoaders)
208+
throws ClassNotFoundException, IllegalAccessException, InstantiationException, InvocationTargetException {
204209
className = remapClass(className);
205210
if (classFilter == null) {
206211
throw new NullPointerException("classFilter");
@@ -209,7 +214,7 @@ public static Savable fromName(String className, SavableClassFilter classFilter)
209214
throw new SecurityException("Savable class rejected by filter: " + className);
210215
}
211216

212-
Constructor noArgConstructor = findNoArgConstructor(className);
217+
Constructor noArgConstructor = findNoArgConstructor(className, additionalClassLoaders);
213218
noArgConstructor.setAccessible(true);
214219
try {
215220
return (Savable) noArgConstructor.newInstance();
@@ -226,6 +231,7 @@ public static Savable fromName(String className, SavableClassFilter classFilter)
226231
}
227232
}
228233

234+
229235
/**
230236
* @deprecated use {@link #fromName(java.lang.String)} instead
231237
*/
@@ -263,12 +269,32 @@ public static Savable fromName(String className, List<ClassLoader> loaders) thro
263269
* @return the pre-existing constructor (not null)
264270
*/
265271
@SuppressWarnings("unchecked")
266-
private static Constructor findNoArgConstructor(String className)
272+
private static Constructor findNoArgConstructor(String className, Collection<ClassLoader> additionalClassLoaders)
267273
throws ClassNotFoundException, InstantiationException {
268-
Class clazz = Class.forName(className);
274+
Class clazz = null;
275+
276+
try {
277+
clazz = Class.forName(className);
278+
} catch (ClassNotFoundException e) {
279+
if (additionalClassLoaders != null) {
280+
for (ClassLoader classLoader : additionalClassLoaders) {
281+
try {
282+
clazz = Class.forName(className, true, classLoader);
283+
break;
284+
} catch (ClassNotFoundException ex) {
285+
// ignore
286+
}
287+
}
288+
}
289+
if (clazz == null) {
290+
throw e;
291+
}
292+
}
293+
269294
if (!SavableClassUtil.isImplementingSavable(clazz)) {
270295
throw new InstantiationException("Class " + className + " does not implement Savable.");
271296
}
297+
272298
Constructor result;
273299
try {
274300
result = clazz.getDeclaredConstructor();

jme3-core/src/plugins/java/com/jme3/export/binary/BinaryImporter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,7 @@ public Savable readObject(int id) {
399399
throw new IOException("Invalid J3O object data length: " + dataLength);
400400
}
401401

402-
Savable out = SavableClassUtil.fromName(bco.className, classFilter);
402+
Savable out = SavableClassUtil.fromName(bco.className, classFilter, assetManager == null ? null : assetManager.getClassLoaders());
403403

404404
BinaryInputCapsule cap = new BinaryInputCapsule(this, out, bco);
405405
cap.setContent(dataArray, loc, loc+dataLength);

jme3-plugins/src/xml/java/com/jme3/export/xml/DOMInputCapsule.java

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434

3535
import com.jme3.export.InputCapsule;
3636
import com.jme3.export.Savable;
37+
import com.jme3.export.SavableClassFilter;
3738
import com.jme3.export.SavableClassUtil;
3839
import com.jme3.util.BufferUtils;
3940
import com.jme3.util.IntMap;
@@ -56,6 +57,7 @@
5657
*/
5758
public class DOMInputCapsule implements InputCapsule {
5859
private static final Logger logger = Logger.getLogger(DOMInputCapsule.class .getName());
60+
private SavableClassFilter classFilter = SavableClassFilter.ACCEPT_ALL;
5961

6062
private Document doc;
6163
private Element currentElement;
@@ -85,6 +87,28 @@ public int getSavableVersion(Class<? extends Savable> desiredClass) {
8587
}
8688
}
8789

90+
/**
91+
* Sets the policy used before this importer instantiates classes.
92+
* The default accepts all classes for backward compatibility.
93+
* Use a restrictive filter when loading assets from untrusted sources.
94+
*
95+
* @param classFilter the filter to apply
96+
*/
97+
public void setClassFilter(SavableClassFilter classFilter) {
98+
if (classFilter == null) {
99+
throw new NullPointerException("classFilter");
100+
}
101+
this.classFilter = classFilter;
102+
}
103+
104+
/**
105+
* @return the current class filter
106+
*/
107+
public SavableClassFilter getClassFilter() {
108+
return classFilter;
109+
}
110+
111+
88112
private Element findChildElement(String name) {
89113
if (currentElement == null) {
90114
return null;
@@ -574,7 +598,7 @@ private Savable readSavableFromCurrentElement(Savable defVal) throws IOException
574598

575599
Savable tmp = null;
576600
try {
577-
tmp = SavableClassUtil.fromName(className);
601+
tmp = SavableClassUtil.fromName(className, classFilter, importer.getAssetManager() == null ? null : importer.getAssetManager().getClassLoaders());
578602
} catch (ClassNotFoundException | IllegalAccessException | InstantiationException | InvocationTargetException e) {
579603
throw new IOException(e);
580604
}

0 commit comments

Comments
 (0)