Ignore:
Timestamp:
2015-02-09T08:43:18+01:00 (9 years ago)
Author:
bastiK
Message:

see #11090 - basic support for plugin loading at runtime.

This is still in testing stage. It will be announced on
the mailing list when plugin authors can start to adapt
their code.

File:
1 edited

Legend:

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

    r7956 r8017  
    187187
    188188    /**
     189     * ClassLoader that makes the addURL method of URLClassLoader public.
     190     *
     191     * Like URLClassLoader, but allows to add more URLs after construction.
     192     */
     193    public static class DynamicURLClassLoader extends URLClassLoader {
     194
     195        public DynamicURLClassLoader(URL[] urls, ClassLoader parent) {
     196            super(urls, parent);
     197        }
     198
     199        @Override
     200        public void addURL(URL url) {
     201            super.addURL(url);
     202        }
     203    }
     204
     205    /**
    189206     * List of unmaintained plugins. Not really up-to-date as the vast majority of plugins are not really maintained after a few months, sadly...
    190207     */
     
    200217     */
    201218    public static final Collection<PluginProxy> pluginList = new LinkedList<>();
     219
     220    /**
     221     * Global plugin ClassLoader.
     222     */
     223    private static DynamicURLClassLoader pluginClassLoader;
    202224
    203225    /**
     
    536558
    537559    /**
    538      * Creates a class loader for loading plugin code.
    539      *
    540      * @param plugins the collection of plugins which are going to be loaded with this
    541      * class loader
     560     * Get the class loader for loading plugin code.
     561     *
    542562     * @return the class loader
    543563     */
    544     public static ClassLoader createClassLoader(Collection<PluginInformation> plugins) {
     564    public static DynamicURLClassLoader getPluginClassLoader() {
     565        if (pluginClassLoader == null) {
     566            pluginClassLoader = AccessController.doPrivileged(new PrivilegedAction<DynamicURLClassLoader>() {
     567                public DynamicURLClassLoader run() {
     568                    return new DynamicURLClassLoader(new URL[0], Main.class.getClassLoader());
     569                }
     570            });
     571            sources.add(0, pluginClassLoader);
     572        }
     573        return pluginClassLoader;
     574    }
     575
     576    /**
     577     * Add more plugins to the plugin class loader.
     578     *
     579     * @param plugins the plugins that should be handled by the plugin class loader
     580     */
     581    public static void extendPluginClassLoader(Collection<PluginInformation> plugins) {
    545582        // iterate all plugins and collect all libraries of all plugins:
    546         List<URL> allPluginLibraries = new LinkedList<>();
    547583        File pluginDir = Main.pref.getPluginsDirectory();
    548 
    549         // Add all plugins already loaded (to include early plugins in the classloader, allowing late plugins to rely on early ones)
    550         Collection<PluginInformation> allPlugins = new HashSet<>(plugins);
    551         for (PluginProxy proxy : pluginList) {
    552             allPlugins.add(proxy.getPluginInformation());
    553         }
    554 
    555         for (PluginInformation info : allPlugins) {
     584        DynamicURLClassLoader cl = getPluginClassLoader();
     585
     586        for (PluginInformation info : plugins) {
    556587            if (info.libraries == null) {
    557588                continue;
    558589            }
    559             allPluginLibraries.addAll(info.libraries);
     590            for (URL libUrl : info.libraries) {
     591                cl.addURL(libUrl);
     592            }
    560593            File pluginJar = new File(pluginDir, info.name + ".jar");
    561594            I18n.addTexts(pluginJar);
    562595            URL pluginJarUrl = Utils.fileToURL(pluginJar);
    563             allPluginLibraries.add(pluginJarUrl);
    564         }
    565 
    566         // create a classloader for all plugins:
    567         final URL[] jarUrls = allPluginLibraries.toArray(new URL[allPluginLibraries.size()]);
    568         return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
    569             public ClassLoader run() {
    570                 return new URLClassLoader(jarUrls, Main.class.getClassLoader());
    571             }
    572       });
     596            cl.addURL(pluginJarUrl);
     597        }
    573598    }
    574599
     
    614639     * @param monitor the progress monitor. Defaults to {@link NullProgressMonitor#INSTANCE} if null.
    615640     */
    616     public static void loadPlugins(Component parent,Collection<PluginInformation> plugins, ProgressMonitor monitor) {
     641    public static void loadPlugins(Component parent, Collection<PluginInformation> plugins, ProgressMonitor monitor) {
    617642        if (monitor == null) {
    618643            monitor = NullProgressMonitor.INSTANCE;
     
    644669                return;
    645670
    646             ClassLoader pluginClassLoader = createClassLoader(toLoad);
    647             sources.add(0, pluginClassLoader);
     671            extendPluginClassLoader(toLoad);
    648672            monitor.setTicksCount(toLoad.size());
    649673            for (PluginInformation info : toLoad) {
    650674                monitor.setExtraText(tr("Loading plugin ''{0}''...", info.name));
    651                 loadPlugin(parent, info, pluginClassLoader);
     675                loadPlugin(parent, info, getPluginClassLoader());
    652676                monitor.worked(1);
    653677            }
     
    10451069     * If {@code dowarn} is true, this methods emits warning messages on the console if a downloaded
    10461070     * but not yet installed plugin .jar can't be be installed. If {@code dowarn} is false, the
    1047      * installation of the respective plugin is sillently skipped.
     1071     * installation of the respective plugin is silently skipped.
    10481072     *
    10491073     * @param dowarn if true, warning messages are displayed; false otherwise
Note: See TracChangeset for help on using the changeset viewer.