Ticket #14901: plugin-classloader.patch

File plugin-classloader.patch, 6.8 KB (added by bastiK, 8 years ago)

WIP

  • src/org/openstreetmap/josm/plugins/PluginClassLoader.java

     
     1// License: GPL. For details, see LICENSE file.
     2package org.openstreetmap.josm.plugins;
     3
     4import java.net.URL;
     5import java.net.URLClassLoader;
     6import java.util.ArrayList;
     7import java.util.Collection;
     8
     9/**
     10 * Class loader for plugins.
     11 *
     12 * Plugin will have access to JOSM core classes and the classes of the plugin
     13 * and all required plugins.
     14 */
     15public class PluginClassLoader extends URLClassLoader {
     16
     17    Collection<PluginClassLoader> dependencies;
     18
     19    static {
     20        ClassLoader.registerAsParallelCapable();
     21    }
     22
     23    public PluginClassLoader(URL[] urls, ClassLoader parent, Collection<PluginClassLoader> dependencies) {
     24        super(urls, parent);
     25        this.dependencies = dependencies == null ? new ArrayList<>() : new ArrayList<>(dependencies);
     26    }
     27
     28    public void addDependency(PluginClassLoader dependency) {
     29        dependencies.add(dependency);
     30    }
     31
     32    @Override
     33    protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
     34        for (PluginClassLoader dep : dependencies) {
     35            try {
     36                Class<?> result = dep.loadClass(name, resolve);
     37                if (result != null) {
     38                    return result;
     39                }
     40            } catch (ClassNotFoundException e) {}
     41        }
     42        Class<?> result = super.loadClass(name, resolve);
     43        if (result != null) {
     44            return result;
     45        }
     46        throw new ClassNotFoundException(name);
     47    }
     48}
  • src/org/openstreetmap/josm/plugins/PluginHandler.java

    Property changes on: src/org/openstreetmap/josm/plugins/PluginClassLoader.java
    ___________________________________________________________________
    Added: svn:eol-style
    ## -0,0 +1 ##
    +native
    \ No newline at end of property
     
    753753     * @param plugin the plugin
    754754     * @param pluginClassLoader the plugin class loader
    755755     */
    756     public static void loadPlugin(Component parent, PluginInformation plugin, ClassLoader pluginClassLoader) {
     756    public static void loadPlugin(Component parent, PluginInformation plugin, PluginClassLoader pluginClassLoader) {
    757757        String msg = tr("Could not load plugin {0}. Delete from preferences?", plugin.name);
    758758        try {
    759759            Class<?> klass = plugin.loadClass(pluginClassLoader);
    760760            if (klass != null) {
    761761                Main.info(tr("loading plugin ''{0}'' (version {1})", plugin.name, plugin.localversion));
    762                 PluginProxy pluginProxy = plugin.load(klass);
     762                PluginProxy pluginProxy = plugin.load(klass, pluginClassLoader);
    763763                pluginList.add(pluginProxy);
    764764                Main.addAndFireMapFrameListener(pluginProxy);
    765765            }
     
    807807            if (toLoad.isEmpty())
    808808                return;
    809809
     810            Map<PluginInformation, PluginClassLoader> classLoaders = new HashMap<>();
     811            for (PluginInformation info : toLoad) {
     812                classLoaders.put(info, new PluginClassLoader(
     813                        info.libraries.toArray(new URL[0]),
     814                        Main.class.getClassLoader(),
     815                        null));
     816            }
     817
     818            // resolve dependencies
     819            for (PluginInformation info : toLoad) {
     820                PluginClassLoader cl = classLoaders.get(info);
     821                DEPENDENCIES:
     822                for (String depName : info.getRequiredPlugins()) {
     823                    for (PluginInformation depInfo : toLoad) {
     824                        if (depInfo.getName().equals(depName)) {
     825                            cl.addDependency(classLoaders.get(depInfo));
     826                            continue DEPENDENCIES;
     827                        }
     828                    }
     829                    for (PluginProxy proxy : pluginList) {
     830                        if (proxy.getPluginInformation().getName().equals(depName)) {
     831                            cl.addDependency(proxy.classLoader);
     832                            break;
     833                        }
     834                    }
     835                    throw new AssertionError();
     836                }
     837            }
     838
    810839            extendPluginClassLoader(toLoad);
    811840            monitor.setTicksCount(toLoad.size());
    812841            for (PluginInformation info : toLoad) {
    813842                monitor.setExtraText(tr("Loading plugin ''{0}''...", info.name));
    814                 loadPlugin(parent, info, getPluginClassLoader());
     843                loadPlugin(parent, info, classLoaders.get(info));
    815844                monitor.worked(1);
    816845            }
    817846        } finally {
  • src/org/openstreetmap/josm/plugins/PluginInformation.java

     
    318318     * @return the instantiated and initialized plugin
    319319     * @throws PluginException if the plugin cannot be loaded or instanciated
    320320     */
    321     public PluginProxy load(Class<?> klass) throws PluginException {
     321    public PluginProxy load(Class<?> klass, PluginClassLoader classLoader) throws PluginException {
    322322        try {
    323323            Constructor<?> c = klass.getConstructor(PluginInformation.class);
    324324            Object plugin = c.newInstance(this);
    325             return new PluginProxy(plugin, this);
     325            return new PluginProxy(plugin, this, classLoader);
    326326        } catch (ReflectiveOperationException e) {
    327327            throw new PluginException(name, e);
    328328        }
  • src/org/openstreetmap/josm/plugins/PluginProxy.java

     
    2222     * The plugin.
    2323     */
    2424    public final Object plugin;
     25    public final PluginClassLoader classLoader;
    2526
    2627    /**
    2728     * Constructs a new {@code PluginProxy}.
     
    2829     * @param plugin the plugin
    2930     * @param info the associated plugin info
    3031     */
    31     public PluginProxy(Object plugin, PluginInformation info) {
     32    public PluginProxy(Object plugin, PluginInformation info, PluginClassLoader classLoader) {
    3233        super(info);
    3334        this.plugin = plugin;
     35        this.classLoader = classLoader;
    3436    }
    3537
    3638    private void handlePluginException(Exception e) {