Skip to content
Merged
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
4 changes: 2 additions & 2 deletions jme3-core/src/main/java/com/jme3/asset/AssetManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
import com.jme3.texture.plugins.TGALoader;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumSet;
import java.util.List;

Expand Down Expand Up @@ -122,7 +122,7 @@ public default void removeClassLoader(ClassLoader loader) {
*/
@Deprecated
public default List<ClassLoader> getClassLoaders() {
return new ArrayList<>();
return Collections.emptyList();
}

/**
Expand Down
44 changes: 38 additions & 6 deletions jme3-core/src/main/java/com/jme3/export/SavableClassUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.logging.Level;
Expand Down Expand Up @@ -198,9 +199,13 @@ public static Savable fromName(String className)
* @throws ClassNotFoundException thrown if the class name is not in the classpath.
* @throws SecurityException thrown if the filter rejects the class name.
*/
public static Savable fromName(String className, SavableClassFilter classFilter)
throws ClassNotFoundException, IllegalAccessException,
InstantiationException, InvocationTargetException {
public static Savable fromName(String className, SavableClassFilter classFilter)
throws ClassNotFoundException, IllegalAccessException, InstantiationException, InvocationTargetException {
return fromName(className, classFilter, null);
}

public static Savable fromName(String className, SavableClassFilter classFilter, Collection<ClassLoader> additionalClassLoaders)
throws ClassNotFoundException, IllegalAccessException, InstantiationException, InvocationTargetException {
className = remapClass(className);
if (classFilter == null) {
throw new NullPointerException("classFilter");
Expand All @@ -209,7 +214,7 @@ public static Savable fromName(String className, SavableClassFilter classFilter)
throw new SecurityException("Savable class rejected by filter: " + className);
}

Constructor noArgConstructor = findNoArgConstructor(className);
Constructor noArgConstructor = findNoArgConstructor(className, additionalClassLoaders);
noArgConstructor.setAccessible(true);
try {
return (Savable) noArgConstructor.newInstance();
Expand All @@ -226,6 +231,7 @@ public static Savable fromName(String className, SavableClassFilter classFilter)
}
}


/**
* @deprecated use {@link #fromName(java.lang.String)} instead
*/
Expand All @@ -240,6 +246,9 @@ public static Savable fromName(String className, List<ClassLoader> loaders) thro
String newClassName = remapClass(className);
synchronized (loaders) {
for (ClassLoader classLoader : loaders) {
if (classLoader == null) {
continue;
}
final Class<?> loadedClass;
try {
loadedClass = classLoader.loadClass(newClassName);
Expand All @@ -263,12 +272,35 @@ public static Savable fromName(String className, List<ClassLoader> loaders) thro
* @return the pre-existing constructor (not null)
*/
@SuppressWarnings("unchecked")
private static Constructor findNoArgConstructor(String className)
private static Constructor findNoArgConstructor(String className, Collection<ClassLoader> additionalClassLoaders)
throws ClassNotFoundException, InstantiationException {
Class clazz = Class.forName(className);
Class clazz = null;

try {
clazz = Class.forName(className);
} catch (ClassNotFoundException e) {
if (additionalClassLoaders != null) {
for (ClassLoader classLoader : additionalClassLoaders) {
if (classLoader == null) {
continue;
}
try {
clazz = Class.forName(className, true, classLoader);
break;
} catch (ClassNotFoundException ex) {
// ignore
}
}
}
Comment thread
riccardobl marked this conversation as resolved.
if (clazz == null) {
throw e;
}
}

if (!SavableClassUtil.isImplementingSavable(clazz)) {
throw new InstantiationException("Class " + className + " does not implement Savable.");
}

Constructor result;
try {
result = clazz.getDeclaredConstructor();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,7 @@ public Savable readObject(int id) {
throw new IOException("Invalid J3O object data length: " + dataLength);
}

Savable out = SavableClassUtil.fromName(bco.className, classFilter);
Savable out = SavableClassUtil.fromName(bco.className, classFilter, assetManager == null ? null : assetManager.getClassLoaders());
Comment thread
riccardobl marked this conversation as resolved.

BinaryInputCapsule cap = new BinaryInputCapsule(this, out, bco);
cap.setContent(dataArray, loc, loc+dataLength);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@

import com.jme3.export.InputCapsule;
import com.jme3.export.Savable;
import com.jme3.export.SavableClassFilter;
import com.jme3.export.SavableClassUtil;
import com.jme3.util.BufferUtils;
import com.jme3.util.IntMap;
Expand All @@ -56,6 +57,7 @@
*/
public class DOMInputCapsule implements InputCapsule {
private static final Logger logger = Logger.getLogger(DOMInputCapsule.class .getName());
private SavableClassFilter classFilter = SavableClassFilter.ACCEPT_ALL;

private Document doc;
private Element currentElement;
Expand Down Expand Up @@ -85,6 +87,28 @@ public int getSavableVersion(Class<? extends Savable> desiredClass) {
}
}

/**
* Sets the policy used before this importer instantiates classes.
* The default accepts all classes for backward compatibility.
* Use a restrictive filter when loading assets from untrusted sources.
*
* @param classFilter the filter to apply
*/
public void setClassFilter(SavableClassFilter classFilter) {
if (classFilter == null) {
throw new NullPointerException("classFilter");
}
this.classFilter = classFilter;
}

/**
* @return the current class filter
*/
public SavableClassFilter getClassFilter() {
return classFilter;
}


private Element findChildElement(String name) {
if (currentElement == null) {
return null;
Expand Down Expand Up @@ -574,7 +598,7 @@ private Savable readSavableFromCurrentElement(Savable defVal) throws IOException

Savable tmp = null;
try {
tmp = SavableClassUtil.fromName(className);
tmp = SavableClassUtil.fromName(className, classFilter, importer.getAssetManager() == null ? null : importer.getAssetManager().getClassLoaders());
} catch (ClassNotFoundException | IllegalAccessException | InstantiationException | InvocationTargetException e) {
throw new IOException(e);
}
Expand Down
Loading