Bladeren bron

Replace direct usage of ClassLoader with ResourcesLoader (#2059)

Riccardo Balbo 2 jaren geleden
bovenliggende
commit
f915e5606f
21 gewijzigde bestanden met toevoegingen van 408 en 50 verwijderingen
  1. 2 2
      jme3-android/src/main/java/com/jme3/system/android/JmeAndroidSystem.java
  2. 3 2
      jme3-core/src/main/java/com/jme3/app/LegacyApplication.java
  3. 3 1
      jme3-core/src/main/java/com/jme3/asset/AssetConfig.java
  4. 17 4
      jme3-core/src/main/java/com/jme3/asset/AssetManager.java
  5. 5 3
      jme3-core/src/main/java/com/jme3/asset/DesktopAssetManager.java
  6. 4 0
      jme3-core/src/main/java/com/jme3/export/SavableClassUtil.java
  7. 5 3
      jme3-core/src/main/java/com/jme3/input/JoystickCompatibilityMappings.java
  8. 3 2
      jme3-core/src/main/java/com/jme3/system/JmeSystemDelegate.java
  9. 3 1
      jme3-core/src/main/java/com/jme3/system/JmeVersion.java
  10. 72 0
      jme3-core/src/main/java/com/jme3/util/res/DefaultResourceLoader.java
  11. 81 0
      jme3-core/src/main/java/com/jme3/util/res/ResourceLoader.java
  12. 182 0
      jme3-core/src/main/java/com/jme3/util/res/Resources.java
  13. 6 14
      jme3-core/src/plugins/java/com/jme3/asset/plugins/ClasspathLocator.java
  14. 1 6
      jme3-core/src/plugins/java/com/jme3/export/binary/BinaryImporter.java
  15. 3 1
      jme3-core/src/test/java/com/jme3/system/MockJmeSystemDelegate.java
  16. 3 1
      jme3-desktop/src/main/java/com/jme3/app/AppletHarness.java
  17. 3 1
      jme3-desktop/src/main/java/com/jme3/system/JmeDesktopSystem.java
  18. 7 5
      jme3-desktop/src/main/java/com/jme3/system/NativeLibraryLoader.java
  19. 2 2
      jme3-ios/src/main/java/com/jme3/system/ios/JmeIosSystem.java
  20. 1 1
      jme3-plugins/src/xml/java/com/jme3/export/xml/DOMInputCapsule.java
  21. 2 1
      jme3-vr/src/main/java/com/jme3/app/VRApplication.java

+ 2 - 2
jme3-android/src/main/java/com/jme3/system/android/JmeAndroidSystem.java

@@ -17,7 +17,7 @@ import com.jme3.audio.openal.EFX;
 import com.jme3.system.*;
 import com.jme3.system.JmeContext.Type;
 import com.jme3.util.AndroidScreenshots;
-import com.jme3.util.functional.VoidFunction;
+import com.jme3.util.res.Resources;
 
 import java.io.File;
 import java.io.IOException;
@@ -52,7 +52,7 @@ public class JmeAndroidSystem extends JmeSystemDelegate {
     
     @Override
     public URL getPlatformAssetConfigURL() {
-        return Thread.currentThread().getContextClassLoader().getResource("com/jme3/asset/Android.cfg");
+        return Resources.getResource("com/jme3/asset/Android.cfg");
     }
 
     @Override

+ 3 - 2
jme3-core/src/main/java/com/jme3/app/LegacyApplication.java

@@ -52,6 +52,7 @@ import com.jme3.renderer.ViewPort;
 import com.jme3.system.AppSettings;
 import com.jme3.system.JmeContext;
 import com.jme3.system.JmeContext.Type;
+import com.jme3.util.res.Resources;
 import com.jme3.system.JmeSystem;
 import com.jme3.system.NanoTimer;
 import com.jme3.system.SystemListener;
@@ -217,7 +218,7 @@ public class LegacyApplication implements Application, SystemListener {
                     //do nothing, we check assetCfgUrl
                 }
                 if (assetCfgUrl == null) {
-                    assetCfgUrl = LegacyApplication.class.getClassLoader().getResource(assetCfg);
+                    assetCfgUrl = Resources.getResource(assetCfg);
                     if (assetCfgUrl == null) {
                         logger.log(Level.SEVERE, "Unable to access AssetConfigURL in asset config:{0}", 
                                 assetCfg);
@@ -225,7 +226,7 @@ public class LegacyApplication implements Application, SystemListener {
                     }
                 }
             }
-        }
+        }      
         if (assetCfgUrl == null) {
             assetCfgUrl = JmeSystem.getPlatformAssetConfigURL();
         }

+ 3 - 1
jme3-core/src/main/java/com/jme3/asset/AssetConfig.java

@@ -39,6 +39,8 @@ import java.util.Scanner;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
+import com.jme3.util.res.Resources;
+
 /**
  * <code>AssetConfig</code> loads a config file to configure the asset manager.
  *
@@ -101,7 +103,7 @@ public final class AssetConfig {
                     }
                 } else if (cmd.equals("INCLUDE")) {
                     String includedCfg = scan.nextLine().trim();
-                    URL includedCfgUrl = Thread.currentThread().getContextClassLoader().getResource(includedCfg);
+                    URL includedCfgUrl = Resources.getResource(includedCfg);
                     if (includedCfgUrl != null) {
                         loadText(assetManager, includedCfgUrl);
                     } else {

+ 17 - 4
jme3-core/src/main/java/com/jme3/asset/AssetManager.java

@@ -46,6 +46,7 @@ import com.jme3.texture.Texture;
 import com.jme3.texture.plugins.TGALoader;
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.ArrayList;
 import java.util.EnumSet;
 import java.util.List;
 
@@ -86,7 +87,7 @@ import java.util.List;
  * so that modifications to one instance do not leak onto others.
  */
 public interface AssetManager {
-
+    
     /**
      * Adds a {@link ClassLoader} that is used to load {@link Class classes}
      * that are needed for finding and loading Assets. 
@@ -94,23 +95,35 @@ public interface AssetManager {
      * use registerLocator for that.
      * 
      * @param loader A ClassLoader that Classes in asset files can be loaded from.
+     * @deprecated use {@link com.jme3.util.res.Resources}
      */
-    public void addClassLoader(ClassLoader loader);
+    @Deprecated
+    public default void addClassLoader(ClassLoader loader) {
+        
+    }
 
     /**
      * Remove a {@link ClassLoader} from the list of registered ClassLoaders
      * 
      * @param loader the ClassLoader to be removed
+     * @deprecated use {@link com.jme3.util.res.Resources}
      */
-    public void removeClassLoader(ClassLoader loader);
+    @Deprecated
+    public default void removeClassLoader(ClassLoader loader) {
+        
+    }
 
     /**
      * Retrieve the list of registered ClassLoaders that are used for loading 
      * {@link Class classes} from asset files.
      * 
      * @return an unmodifiable list
+    * @deprecated use {@link com.jme3.util.res.Resources}
      */
-    public List<ClassLoader> getClassLoaders();
+    @Deprecated
+    public default List<ClassLoader> getClassLoaders() {
+        return new ArrayList<>();
+    }
     
     /**
      * Register an {@link AssetLoader} by using a class object.

+ 5 - 3
jme3-core/src/main/java/com/jme3/asset/DesktopAssetManager.java

@@ -73,8 +73,8 @@ public class DesktopAssetManager implements AssetManager {
     final private CopyOnWriteArrayList<AssetEventListener> eventListeners =
             new CopyOnWriteArrayList<>();
 
-    final private List<ClassLoader> classLoaders =
-            Collections.synchronizedList(new ArrayList<>());
+    @Deprecated
+    final private List<ClassLoader> classLoaders = Collections.synchronizedList(new ArrayList<>());
 
     public DesktopAssetManager() {
         this(null);
@@ -99,21 +99,23 @@ public class DesktopAssetManager implements AssetManager {
         }
     }
 
+    @Deprecated
     @Override
     public void addClassLoader(ClassLoader loader) {
         classLoaders.add(loader);
     }
 
+    @Deprecated
     @Override
     public void removeClassLoader(ClassLoader loader) {
         classLoaders.remove(loader);
     }
 
+    @Deprecated
     @Override
     public List<ClassLoader> getClassLoaders() {
         return Collections.unmodifiableList(classLoaders);
     }
-
     @Override
     public void addAssetEventListener(AssetEventListener listener) {
         eventListeners.add(listener);

+ 4 - 0
jme3-core/src/main/java/com/jme3/export/SavableClassUtil.java

@@ -201,6 +201,10 @@ public class SavableClassUtil {
         }
     }
 
+    /**
+     * @deprecated use {@link #fromName(java.lang.String)} instead 
+     */
+    @Deprecated
     public static Savable fromName(String className, List<ClassLoader> loaders) throws InstantiationException,
             InvocationTargetException, NoSuchMethodException,
             IllegalAccessException, ClassNotFoundException, IOException {

+ 5 - 3
jme3-core/src/main/java/com/jme3/input/JoystickCompatibilityMappings.java

@@ -44,6 +44,8 @@ import java.util.logging.Logger;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
+import com.jme3.util.res.Resources;
+
 
 /**
  * Provides compatibility mapping to different joysticks
@@ -554,9 +556,9 @@ public class JoystickCompatibilityMappings {
         }
     }
 
-    protected static void loadMappings(ClassLoader cl, String path) throws IOException {
+    protected static void loadMappings(String path) throws IOException {
         logger.log(Level.FINE, "Searching for mappings for path:{0}", path);
-        for (Enumeration<URL> en = cl.getResources(path); en.hasMoreElements(); ) {
+        for (Enumeration<URL> en = Resources.getResources(path); en.hasMoreElements(); ) {
             URL u = en.nextElement();
             try {
                 loadMappingProperties(u);
@@ -574,7 +576,7 @@ public class JoystickCompatibilityMappings {
     protected static void loadDefaultMappings() {
         for (String s : searchPaths) {
             try {
-                loadMappings(JoystickCompatibilityMappings.class.getClassLoader(), s);
+                loadMappings(s);
             } catch (IOException e) {
                 logger.log(Level.SEVERE, "Error searching resource path:{0}", s);
             }

+ 3 - 2
jme3-core/src/main/java/com/jme3/system/JmeSystemDelegate.java

@@ -35,6 +35,7 @@ import com.jme3.asset.AssetManager;
 import com.jme3.asset.DesktopAssetManager;
 import com.jme3.audio.AudioRenderer;
 import com.jme3.input.SoftTextDialogInput;
+import com.jme3.util.res.Resources;
 
 import java.io.File;
 import java.io.IOException;
@@ -126,11 +127,11 @@ public abstract class JmeSystemDelegate {
     }
 
     public InputStream getResourceAsStream(String name) {
-        return this.getClass().getResourceAsStream(name);
+        return Resources.getResourceAsStream(name,this.getClass());
     }
 
     public URL getResource(String name) {
-        return this.getClass().getResource(name);
+        return Resources.getResource(name,this.getClass());
     }
 
     public boolean trackDirectMemory() {

+ 3 - 1
jme3-core/src/main/java/com/jme3/system/JmeVersion.java

@@ -36,6 +36,8 @@ import java.util.Properties;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
+import com.jme3.util.res.Resources;
+
 /**
  * Pulls in version info from the version.properties file.
  * 
@@ -48,7 +50,7 @@ public class JmeVersion {
     
     static {
         try {
-            props.load(JmeVersion.class.getResourceAsStream("version.properties"));
+            props.load(Resources.getResourceAsStream("version.properties",JmeVersion.class));
         } catch (IOException | NullPointerException ex) {
             logger.log(Level.WARNING, "Unable to read version info!", ex);
         }

+ 72 - 0
jme3-core/src/main/java/com/jme3/util/res/DefaultResourceLoader.java

@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2009-2023 jMonkeyEngine
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
+ *   may be used to endorse or promote products derived from this software
+ *   without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.jme3.util.res;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Enumeration;
+
+/**
+ * Default implementation of {@link ResourceLoader}. 
+ * Loads from classpath.
+ */
+class DefaultResourceLoader implements ResourceLoader {
+    
+    DefaultResourceLoader() {
+        
+    }
+
+    @Override
+    public InputStream getResourceAsStream(String path, Class<?> parent) {
+        if (parent == null) {
+            return Thread.currentThread().getContextClassLoader().getResourceAsStream(path);
+        } else {
+            return parent.getResourceAsStream(path);
+        }
+    }
+
+    @Override
+    public URL getResource(String path, Class<?> parent) {
+        if (parent == null) {
+            return Thread.currentThread().getContextClassLoader().getResource(path);
+        } else {
+            return parent.getResource(path);
+        }
+    }
+
+    @Override
+    public Enumeration<URL> getResources(String path) throws IOException {
+        return Thread.currentThread().getContextClassLoader().getResources(path);        
+    }
+
+}

+ 81 - 0
jme3-core/src/main/java/com/jme3/util/res/ResourceLoader.java

@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2009-2023 jMonkeyEngine
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
+ *   may be used to endorse or promote products derived from this software
+ *   without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.jme3.util.res;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Enumeration;
+
+public interface ResourceLoader {
+    /**
+     * Finds the resource with the given name relative to the given parent class
+     * or to the root if the parent is null.
+     * 
+     * @param path
+     *            The resource name
+     * @param parent
+     *            Optional parent class
+     * @return The resource URL or null if not found
+     */
+    public URL getResource(String path, Class<?> parent);
+
+    /**
+     * Finds the resource with the given name relative to the given parent class
+     * or to the root if the parent is null.
+     * 
+     * @param path
+     *            The resource name
+     * @param parent
+     *            Optional parent class
+     * @return An input stream to the resource or null if not found
+     */
+    public InputStream getResourceAsStream(String path, Class<?> parent);
+
+
+    /**
+     * Finds all resources with the given name.
+     * 
+     * 
+     * @param path
+     *            The resource name
+     * @return An enumeration of {@link java.net.URL <tt>URL</tt>} objects for
+     *         the resource. If no resources could be found, the enumeration
+     *         will be empty.
+     *
+     * @throws IOException
+     *             If I/O errors occur
+     *
+     * @throws IOException
+     */
+    public Enumeration<URL> getResources(String path) throws IOException;
+}

+ 182 - 0
jme3-core/src/main/java/com/jme3/util/res/Resources.java

@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2009-2023 jMonkeyEngine
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
+ *   may be used to endorse or promote products derived from this software
+ *   without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.jme3.util.res;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * This class is used to load resources from the default location usually the
+ * classpath.
+ */
+public class Resources {
+    /**
+     * The property name to set the ResourceLoader to use. Should be set automatically
+     * by the JmeSystemDelegate. 
+     * Note: changing this property after the first use of the ResourceLoader will have no effect.
+     */
+    public static final String PROPERTY_RESOURCE_LOADER_IMPLEMENTATION = "com.jme3.ResourceLoaderImplementation";
+
+    private static final String DEFAULT_IMPL = "com.jme3.util.res.DefaultResourceLoader";
+    private static final Logger LOGGER = Logger.getLogger(Resources.class.getName());
+    private static ResourceLoader impl = null;
+
+    @SuppressWarnings("unchecked")
+    private static Class<? extends ResourceLoader> findResourceLoaderClass(String className) {
+        Class<?> clazz = null;
+
+        try {
+            clazz = Class.forName(className);
+        } catch (final Throwable e) {
+            LOGGER.log(Level.WARNING, "Unable to access {0}", className);
+        }
+
+        if (clazz != null && !ResourceLoader.class.isAssignableFrom(clazz)) {
+            LOGGER.log(Level.WARNING, "{0} does not implement {1}", new Object[] { className, ResourceLoader.class.getName() });
+            clazz = null;
+        }
+
+        return (Class<? extends ResourceLoader>) clazz;
+    }
+
+    private static ResourceLoader getResourceLoader() {
+        if (impl != null) return impl;
+        Class<? extends ResourceLoader> clazz = null;
+        String userDefinedImpl = System.getProperty(PROPERTY_RESOURCE_LOADER_IMPLEMENTATION, null);
+        
+        if (userDefinedImpl != null) {
+            LOGGER.log(Level.FINE, "Loading user defined ResourceLoader implementation {0}", userDefinedImpl);
+            clazz = findResourceLoaderClass(userDefinedImpl);
+        }
+
+        if (clazz == null) {
+            LOGGER.log(Level.FINE, "No usable user defined ResourceLoader implementation found, using default implementation {0}", DEFAULT_IMPL);
+            clazz = findResourceLoaderClass(DEFAULT_IMPL);
+        }
+
+        if (clazz == null) {
+            throw new RuntimeException("No ResourceLoader implementation found");
+        }
+
+        try {
+            impl = (ResourceLoader) clazz.getDeclaredConstructor().newInstance();
+        } catch (final Throwable e) {
+            throw new RuntimeException("Could not instantiate ResourceLoader class " + clazz.getName(), e);
+        }
+
+        return impl;
+    }
+
+    /**
+     * Sets the resource loader implementation to use.
+     * @param impl The resource loader implementation
+     */
+    public static void setResourceLoader(ResourceLoader impl) {
+        Resources.impl = impl;
+    }
+
+    /**
+     * Finds the resource with the given name.
+     * 
+     * @param path
+     *            The resource name
+     * @return The resource URL or null if not found
+     */
+    public static URL getResource(String path) {
+        return getResourceLoader().getResource(path, null);
+    }
+
+    /**
+     * Finds the resource with the given name relative to the given parent class
+     * or to the root if the parent is null.
+     * 
+     * @param path
+     *            The resource name
+     * @param parent
+     *            Optional parent class
+     * @return The resource URL or null if not found
+     */
+    public static URL getResource(String path, Class<?> parent) {
+        return getResourceLoader().getResource(path, parent);
+    }
+
+    /**
+     * Finds the resource with the given name.
+     * 
+     * @param path
+     *            The resource name
+     * @return An input stream to the resource or null if not found
+     */
+    public static InputStream getResourceAsStream(String path) {
+        return getResourceLoader().getResourceAsStream(path, null);
+    }
+
+    /**
+     * Finds the resource with the given name relative to the given parent class
+     * or to the root if the parent is null.
+     * 
+     * @param path
+     *            The resource name
+     * @param parent
+     *            Optional parent class
+     * @return An input stream to the resource or null if not found
+     */
+    public static InputStream getResourceAsStream(String path, Class<?> parent) {
+        return getResourceLoader().getResourceAsStream(path, parent);
+    }
+
+    /**
+     * Finds all resources with the given name.
+     * 
+     * 
+     * @param path
+     *            The resource name
+     *
+     * 
+     * @return An enumeration of {@link java.net.URL <tt>URL</tt>} objects for
+     *         the resource. If no resources could be found, the enumeration
+     *         will be empty.
+     *
+     * @throws IOException
+     *             If I/O errors occur
+     *
+     * @throws IOException
+     */
+    public static Enumeration<URL> getResources(String path) throws IOException {
+        return getResourceLoader().getResources(path);
+    }
+
+}

+ 6 - 14
jme3-core/src/plugins/java/com/jme3/asset/plugins/ClasspathLocator.java

@@ -33,6 +33,8 @@ package com.jme3.asset.plugins;
 
 import com.jme3.asset.*;
 import com.jme3.system.JmeSystem;
+import com.jme3.util.res.Resources;
+
 import java.io.File;
 import java.io.IOException;
 import java.net.URISyntaxException;
@@ -87,20 +89,10 @@ public class ClasspathLocator implements AssetLocator {
 //            name = root + name;
 //        }
 
-        if (JmeSystem.isLowPermissions()){
-            url = ClasspathLocator.class.getResource("/" + name);
-        }else{
-            url = Thread.currentThread().getContextClassLoader().getResource(name);
-        }
-
-        if (url == null) {
-            final List<ClassLoader> classLoaders = manager.getClassLoaders();
-            for (final ClassLoader classLoader : classLoaders) {
-                url = classLoader.getResource(name);
-                if(url != null) {
-                    break;
-                }
-            }
+        if (JmeSystem.isLowPermissions()) {
+            url = Resources.getResource("/" + name, ClasspathLocator.class);    
+        } else {
+            url = Resources.getResource(name);
         }
 
         if (url == null)

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

@@ -329,12 +329,7 @@ public final class BinaryImporter implements JmeImporter {
             int dataLength = ByteUtils.convertIntFromBytes(dataArray, loc);
             loc+=4;
 
-            Savable out = null;
-            if (assetManager != null) {
-                out = SavableClassUtil.fromName(bco.className, assetManager.getClassLoaders());
-            } else {
-                out = SavableClassUtil.fromName(bco.className);
-            }
+            Savable  out = SavableClassUtil.fromName(bco.className);
 
             BinaryInputCapsule cap = new BinaryInputCapsule(this, out, bco);
             cap.setContent(dataArray, loc, loc+dataLength);

+ 3 - 1
jme3-core/src/test/java/com/jme3/system/MockJmeSystemDelegate.java

@@ -32,6 +32,8 @@
 package com.jme3.system;
 
 import com.jme3.audio.AudioRenderer;
+import com.jme3.util.res.Resources;
+
 import java.io.IOException;
 import java.io.OutputStream;
 import java.net.URL;
@@ -45,7 +47,7 @@ public class MockJmeSystemDelegate extends JmeSystemDelegate {
 
     @Override
     public URL getPlatformAssetConfigURL() {
-        return Thread.currentThread().getContextClassLoader().getResource("com/jme3/asset/General.cfg");
+        return Resources.getResource("com/jme3/asset/General.cfg");
     }
 
     @Override

+ 3 - 1
jme3-desktop/src/main/java/com/jme3/app/AppletHarness.java

@@ -34,6 +34,8 @@ package com.jme3.app;
 import com.jme3.system.AppSettings;
 import com.jme3.system.JmeCanvasContext;
 import com.jme3.system.JmeSystem;
+import com.jme3.util.res.Resources;
+
 import java.applet.Applet;
 import java.awt.Canvas;
 import java.awt.Graphics;
@@ -150,7 +152,7 @@ public class AppletHarness extends Applet {
             assetCfg = new URL(getParameter("AssetConfigURL"));
         } catch (MalformedURLException ex){
             System.out.println(ex.getMessage());
-            assetCfg = getClass().getResource("/com/jme3/asset/Desktop.cfg");
+            assetCfg = Resources.getResource("/com/jme3/asset/Desktop.cfg",this.getClass());
         }
 
         createCanvas();

+ 3 - 1
jme3-desktop/src/main/java/com/jme3/system/JmeDesktopSystem.java

@@ -39,6 +39,8 @@ import com.jme3.audio.openal.EFX;
 import com.jme3.system.JmeContext.Type;
 import com.jme3.texture.Image;
 import com.jme3.texture.image.ColorSpace;
+import com.jme3.util.res.Resources;
+
 import jme3tools.converters.ImageToAwt;
 
 import javax.imageio.IIOImage;
@@ -70,7 +72,7 @@ public class JmeDesktopSystem extends JmeSystemDelegate {
 
     @Override
     public URL getPlatformAssetConfigURL() {
-        return Thread.currentThread().getContextClassLoader().getResource("com/jme3/asset/Desktop.cfg");
+        return Resources.getResource("com/jme3/asset/Desktop.cfg");
     }
     
     private static BufferedImage verticalFlip(BufferedImage original) {

+ 7 - 5
jme3-desktop/src/main/java/com/jme3/system/NativeLibraryLoader.java

@@ -44,6 +44,8 @@ import java.util.Map;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
+import com.jme3.util.res.Resources;
+
 /**
  * Utility class to register, extract, and load native libraries.
  * <br>
@@ -274,7 +276,7 @@ public final class NativeLibraryLoader {
     private static int computeNativesHash() {
         URLConnection conn = null;
         String classpath = System.getProperty("java.class.path");
-        URL url = Thread.currentThread().getContextClassLoader().getResource("com/jme3/system/NativeLibraryLoader.class");
+        URL url = Resources.getResource("com/jme3/system/NativeLibraryLoader.class");
 
         try {
             StringBuilder sb = new StringBuilder(url.toString());
@@ -371,9 +373,9 @@ public final class NativeLibraryLoader {
             fileNameInJar = pathInJar;
         }
         
-        URL url = Thread.currentThread().getContextClassLoader().getResource(pathInJar);
+        URL url = Resources.getResource(pathInJar);
         if (url == null) {
-            url = Thread.currentThread().getContextClassLoader().getResource(fileNameInJar);
+            url = Resources.getResource(fileNameInJar);
         }
         
         if (url == null) {
@@ -401,7 +403,7 @@ public final class NativeLibraryLoader {
             return;
         }
         
-        URL url = Thread.currentThread().getContextClassLoader().getResource(pathInJar);
+        URL url = Resources.getResource(pathInJar);
         if (url == null) {
             return;
         }
@@ -462,7 +464,7 @@ public final class NativeLibraryLoader {
             return;
         }
 
-        URL url = Thread.currentThread().getContextClassLoader().getResource(pathInJar);
+        URL url = Resources.getResource(pathInJar);
 
         if (url == null) {
             if (isRequired) {

+ 2 - 2
jme3-ios/src/main/java/com/jme3/system/ios/JmeIosSystem.java

@@ -35,7 +35,7 @@ import com.jme3.system.AppSettings;
 import com.jme3.system.JmeContext;
 import com.jme3.system.JmeSystemDelegate;
 import com.jme3.system.NullContext;
-import com.jme3.util.functional.VoidFunction;
+import com.jme3.util.res.Resources;
 import com.jme3.audio.AudioRenderer;
 import com.jme3.audio.ios.IosAL;
 import com.jme3.audio.ios.IosALC;
@@ -64,7 +64,7 @@ public class JmeIosSystem extends JmeSystemDelegate {
 
     @Override
     public URL getPlatformAssetConfigURL() {
-        return Thread.currentThread().getContextClassLoader().getResource("com/jme3/asset/IOS.cfg");
+        return Resources.getResource("com/jme3/asset/IOS.cfg");
     }
     
     @Override

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

@@ -924,7 +924,7 @@ public class DOMInputCapsule implements InputCapsule {
             } else if (defVal != null) {
                 className = defVal.getClass().getName();
             }
-            tmp = SavableClassUtil.fromName(className, null);
+            tmp = SavableClassUtil.fromName(className);
             
             String versionsStr = currentElem.getAttribute("savable_versions");
             if (versionsStr != null && !versionsStr.equals("")){

+ 2 - 1
jme3-vr/src/main/java/com/jme3/app/VRApplication.java

@@ -49,6 +49,7 @@ import com.jme3.system.lwjgl.LwjglDisplayVR;
 import com.jme3.system.lwjgl.LwjglOffscreenBufferVR;
 import com.jme3.util.VRGUIPositioningMode;
 import com.jme3.util.VRGuiManager;
+import com.jme3.util.res.Resources;
 
 import java.awt.GraphicsDevice;
 import java.awt.GraphicsEnvironment;
@@ -1177,7 +1178,7 @@ public abstract class VRApplication implements Application, SystemListener {
                 } catch (MalformedURLException ex) {
                 }
                 if (assetCfgUrl == null) {
-                    assetCfgUrl = LegacyApplication.class.getClassLoader().getResource(assetCfg);
+                    assetCfgUrl = Resources.getResource(assetCfg);
                     if (assetCfgUrl == null) {
                         logger.log(Level.SEVERE, "Unable to access AssetConfigURL in asset config:{0}", assetCfg);
                         return;