Changeset 12322 in josm for trunk/src/org/openstreetmap/josm


Ignore:
Timestamp:
2017-06-06T13:43:28+02:00 (7 years ago)
Author:
bastiK
Message:

fixed #14901 - restrict plugin classpath

Separate class loader for each plugin instead of unified class loader.

Location:
trunk/src/org/openstreetmap/josm/plugins
Files:
1 added
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/plugins/PluginHandler.java

    r12279 r12322  
    290290
    291291    /**
    292      * Global plugin ClassLoader.
    293      */
    294     private static DynamicURLClassLoader pluginClassLoader;
     292     * Class loader to locate resources from plugins.
     293     * @see #getJoinedPluginResourceCL()
     294     */
     295    private static DynamicURLClassLoader joinedPluginResourceCL;
    295296
    296297    /**
     
    709710
    710711    /**
    711      * Get the class loader for loading plugin code.
     712     * Method to get the (now obsolete) class loader for loading plugin code.
    712713     *
    713714     * @return the class loader
    714      */
     715     * @deprecated There is no longer a unified plugin class loader. Use {@link PluginProxy#classLoader}
     716     * to get the class loader for each plugin. Or <code>PluginClass.class.getClassLoader()</code>
     717     * to access the class loader from within the plugin.
     718     */
     719    @Deprecated
    715720    public static synchronized DynamicURLClassLoader getPluginClassLoader() {
    716         if (pluginClassLoader == null) {
    717             pluginClassLoader = AccessController.doPrivileged((PrivilegedAction<DynamicURLClassLoader>)
     721        return getJoinedPluginResourceCL();
     722    }
     723
     724    /**
     725     * Get class loader to locate resources from plugins.
     726     *
     727     * It joins URLs of all plugins, to find images, etc.
     728     * (Not for loading Java classes - each plugin has a separate {@link PluginClassLoader}
     729     * for that purpose.)
     730     * @return class loader to locate resources from plugins
     731     */
     732    private static synchronized DynamicURLClassLoader getJoinedPluginResourceCL() {
     733        if (joinedPluginResourceCL == null) {
     734            joinedPluginResourceCL = AccessController.doPrivileged((PrivilegedAction<DynamicURLClassLoader>)
    718735                    () -> new DynamicURLClassLoader(new URL[0], Main.class.getClassLoader()));
    719             sources.add(0, pluginClassLoader);
    720         }
    721         return pluginClassLoader;
    722     }
    723 
    724     /**
    725      * Add more plugins to the plugin class loader.
    726      *
    727      * @param plugins the plugins that should be handled by the plugin class loader
    728      */
    729     public static void extendPluginClassLoader(Collection<PluginInformation> plugins) {
     736            sources.add(0, joinedPluginResourceCL);
     737        }
     738        return joinedPluginResourceCL;
     739    }
     740
     741    /**
     742     * Add more plugins to the joined plugin resource class loader.
     743     *
     744     * @param plugins the plugins to add
     745     */
     746    private static void extendJoinedPluginResourceCL(Collection<PluginInformation> plugins) {
    730747        // iterate all plugins and collect all libraries of all plugins:
    731748        File pluginDir = Main.pref.getPluginsDirectory();
    732         DynamicURLClassLoader cl = getPluginClassLoader();
     749        DynamicURLClassLoader cl = getJoinedPluginResourceCL();
    733750
    734751        for (PluginInformation info : plugins) {
     
    754771     * @param pluginClassLoader the plugin class loader
    755772     */
    756     public static void loadPlugin(Component parent, PluginInformation plugin, ClassLoader pluginClassLoader) {
     773    private static void loadPlugin(Component parent, PluginInformation plugin, PluginClassLoader pluginClassLoader) {
    757774        String msg = tr("Could not load plugin {0}. Delete from preferences?", plugin.name);
    758775        try {
     
    760777            if (klass != null) {
    761778                Main.info(tr("loading plugin ''{0}'' (version {1})", plugin.name, plugin.localversion));
    762                 PluginProxy pluginProxy = plugin.load(klass);
     779                PluginProxy pluginProxy = plugin.load(klass, pluginClassLoader);
    763780                pluginList.add(pluginProxy);
    764781                Main.addAndFireMapFrameListener(pluginProxy);
     
    808825                return;
    809826
    810             extendPluginClassLoader(toLoad);
     827            Map<PluginInformation, PluginClassLoader> classLoaders = new HashMap<>();
     828            for (PluginInformation info : toLoad) {
     829                classLoaders.put(info, new PluginClassLoader(
     830                        info.libraries.toArray(new URL[0]),
     831                        Main.class.getClassLoader(),
     832                        null));
     833            }
     834
     835            // resolve dependencies
     836            for (PluginInformation info : toLoad) {
     837                PluginClassLoader cl = classLoaders.get(info);
     838                DEPENDENCIES:
     839                for (String depName : info.getRequiredPlugins()) {
     840                    for (PluginInformation depInfo : toLoad) {
     841                        if (depInfo.getName().equals(depName)) {
     842                            cl.addDependency(classLoaders.get(depInfo));
     843                            continue DEPENDENCIES;
     844                        }
     845                    }
     846                    for (PluginProxy proxy : pluginList) {
     847                        if (proxy.getPluginInformation().getName().equals(depName)) {
     848                            cl.addDependency(proxy.getClassLoader());
     849                            continue DEPENDENCIES;
     850                        }
     851                    }
     852                    throw new AssertionError("unable to find dependency " + depName + " for plugin " + info.getName());
     853                }
     854            }
     855
     856            extendJoinedPluginResourceCL(toLoad);
    811857            monitor.setTicksCount(toLoad.size());
    812858            for (PluginInformation info : toLoad) {
    813859                monitor.setExtraText(tr("Loading plugin ''{0}''...", info.name));
    814                 loadPlugin(parent, info, getPluginClassLoader());
     860                loadPlugin(parent, info, classLoaders.get(info));
    815861                monitor.worked(1);
    816862            }
     
    11621208        for (PluginProxy plugin : pluginList) {
    11631209            if (plugin.getPluginInformation().name.equals(name))
    1164                 return plugin.plugin;
     1210                return plugin.getPlugin();
    11651211        }
    11661212        return null;
  • trunk/src/org/openstreetmap/josm/plugins/PluginInformation.java

    r12218 r12322  
    316316     *
    317317     * @param klass the plugin class
     318     * @param classLoader the class loader for the plugin
    318319     * @return the instantiated and initialized plugin
    319320     * @throws PluginException if the plugin cannot be loaded or instanciated
    320      */
    321     public PluginProxy load(Class<?> klass) throws PluginException {
     321     * @since 12322
     322     */
     323    public PluginProxy load(Class<?> klass, PluginClassLoader classLoader) throws PluginException {
    322324        try {
    323325            Constructor<?> c = klass.getConstructor(PluginInformation.class);
    324326            Object plugin = c.newInstance(this);
    325             return new PluginProxy(plugin, this);
     327            return new PluginProxy(plugin, this, classLoader);
    326328        } catch (ReflectiveOperationException e) {
    327329            throw new PluginException(name, e);
  • trunk/src/org/openstreetmap/josm/plugins/PluginProxy.java

    r12218 r12322  
    2222     * The plugin.
    2323     */
    24     public final Object plugin;
     24    private final Object plugin;
     25    private final PluginClassLoader classLoader;
    2526
    2627    /**
     
    2829     * @param plugin the plugin
    2930     * @param info the associated plugin info
     31     * @param classLoader the class loader for the plugin
     32     * @since 12322
    3033     */
    31     public PluginProxy(Object plugin, PluginInformation info) {
     34    public PluginProxy(Object plugin, PluginInformation info, PluginClassLoader classLoader) {
    3235        super(info);
    3336        this.plugin = plugin;
     37        this.classLoader = classLoader;
     38    }
     39
     40    /**
     41     * Get the plugin object.
     42     * @return the plugin object
     43     * @since 12322
     44     */
     45    public Object getPlugin() {
     46        return plugin;
     47    }
     48
     49    /**
     50     * Get the class loader for the plugin.
     51     * @return the plugin class loader
     52     * @since 12322
     53     */
     54    public PluginClassLoader getClassLoader() {
     55        return classLoader;
    3456    }
    3557
Note: See TracChangeset for help on using the changeset viewer.