Changeset 8017 in josm


Ignore:
Timestamp:
2015-02-09T08:43:18+01:00 (5 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.

Location:
trunk/src/org/openstreetmap/josm
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/gui/MainApplication.java

    r8015 r8017  
    423423
    424424        monitor.indeterminateSubTask(tr("Loading early plugins"));
    425         PluginHandler.loadEarlyPlugins(splash,pluginsToLoad, monitor.createSubTaskMonitor(1, false));
     425        PluginHandler.loadEarlyPlugins(splash, pluginsToLoad, monitor.createSubTaskMonitor(1, false));
    426426
    427427        monitor.indeterminateSubTask(tr("Setting defaults"));
     
    432432
    433433        monitor.indeterminateSubTask(tr("Loading plugins"));
    434         PluginHandler.loadLatePlugins(splash,pluginsToLoad,  monitor.createSubTaskMonitor(1, false));
     434        PluginHandler.loadLatePlugins(splash, pluginsToLoad,  monitor.createSubTaskMonitor(1, false));
    435435        toolbar.refreshToolbarControl();
    436436
  • trunk/src/org/openstreetmap/josm/gui/preferences/PreferenceTabbedPane.java

    r7509 r8017  
    318318            public void run() {
    319319                boolean requiresRestart = false;
    320                 if (task != null && !task.isCanceled()) {
    321                     if (!task.getDownloadedPlugins().isEmpty()) {
    322                         requiresRestart = true;
    323                     }
    324                 }
    325320
    326321                for (PreferenceSetting setting : settingsInitialized) {
     
    370365                            );
    371366                }
     367
     368                // load the plugins that can be loaded at runtime
     369                List<PluginInformation> newPlugins = preference.getNewlyActivatedPlugins();
     370                if (newPlugins != null) {
     371                    Collection<PluginInformation> downloadedPlugins = null;
     372                    if (task != null && !task.isCanceled()) {
     373                        downloadedPlugins = task.getDownloadedPlugins();
     374                    }
     375                    List<PluginInformation> toLoad = new ArrayList<>();
     376                    for (PluginInformation pi : newPlugins) {
     377                        if (toDownload.contains(pi) && downloadedPlugins != null && !downloadedPlugins.contains(pi)) {
     378                            continue; // failed download
     379                        }
     380                        if (pi.canloadatruntime) {
     381                            toLoad.add(pi);
     382                        }
     383                    }
     384                    if (!toLoad.isEmpty()) {
     385                        PluginHandler.loadPlugins(PreferenceTabbedPane.this, toLoad, null); // FIXME: progress bar
     386                    }
     387                }
     388
    372389                Main.parent.repaint();
    373390            }
  • trunk/src/org/openstreetmap/josm/gui/preferences/plugin/PluginPreference.java

    r7668 r8017  
    123123     * @since 6797
    124124     */
    125     public static void notifyDownloadResults(final Component parent, PluginDownloadTask task) {
     125    public void notifyDownloadResults(final Component parent, PluginDownloadTask task) {
    126126        final Collection<PluginInformation> downloaded = task.getDownloadedPlugins();
    127127        final Collection<PluginInformation> failed = task.getFailedPlugins();
     
    129129        sb.append("<html>");
    130130        sb.append(buildDownloadSummary(task));
    131         if (!downloaded.isEmpty()) {
     131        boolean restartRequired = false;
     132        for (PluginInformation pi : downloaded) {
     133            if (!model.getNewlyActivatedPlugins().contains(pi) || !pi.canloadatruntime) {
     134                restartRequired = true;
     135                break;
     136            }
     137        }
     138        if (restartRequired) {
    132139            sb.append(tr("Please restart JOSM to activate the downloaded plugins."));
    133140        }
     
    276283    }
    277284
     285    public List<PluginInformation> getNewlyActivatedPlugins() {
     286        return model != null ? model.getNewlyActivatedPlugins() : null;
     287    }
     288
    278289    @Override
    279290    public boolean ok() {
     
    285296            Collections.sort(l);
    286297            Main.pref.putCollection("plugins", l);
    287             return true;
     298            if (!model.getNewlyDeactivatedPlugins().isEmpty()) return true;
     299            for (PluginInformation pi : model.getNewlyActivatedPlugins()) {
     300                if (!pi.canloadatruntime) return true;
     301            }
    288302        }
    289303        return false;
     
    436450                    //
    437451                    Iterator<PluginInformation> it = toUpdate.iterator();
    438                     while(it.hasNext()) {
     452                    while (it.hasNext()) {
    439453                        PluginInformation pi = it.next();
    440454                        if (!pi.isUpdateRequired()) {
     
    590604        }
    591605    }
     606
     607
    592608}
  • trunk/src/org/openstreetmap/josm/gui/preferences/plugin/PluginPreferencesModel.java

    r7005 r8017  
    2525 */
    2626public class PluginPreferencesModel extends Observable {
     27    // remember the initial list of active plugins
     28    private final Set<String> currentActivePlugins;
    2729    private final List<PluginInformation> availablePlugins = new ArrayList<>();
     30    private String filterExpression;
    2831    private final List<PluginInformation> displayedPlugins = new ArrayList<>();
    2932    private final Map<PluginInformation, Boolean> selectedPluginsMap = new HashMap<>();
     33    // plugins that still require an update/download
    3034    private Set<String> pendingDownloads = new HashSet<>();
    31     private String filterExpression;
    32     private Set<String> currentActivePlugins;
    3335
    3436    /**
     
    197199        PluginInformation pi = getPluginInformation(name);
    198200        if (pi != null) {
    199             selectedPluginsMap.put(pi,selected);
     201            selectedPluginsMap.put(pi, selected);
    200202            if (pi.isUpdateRequired()) {
    201203                pendingDownloads.add(pi.name);
     
    213215     * @param plugins the list of plugins to clear for a pending download
    214216     */
    215     public void clearPendingPlugins(Collection<PluginInformation> plugins){
     217    public void clearPendingPlugins(Collection<PluginInformation> plugins) {
    216218        if (plugins == null || plugins.isEmpty()) return;
    217         for(PluginInformation pi: plugins) {
     219        for (PluginInformation pi: plugins) {
    218220            pendingDownloads.remove(pi.name);
    219221        }
  • trunk/src/org/openstreetmap/josm/plugins/PluginDownloadTask.java

    r7597 r8017  
    187187
    188188    /**
    189      * Replies the list of successfully downloaded plugins
    190      *
    191      * @return the list of successfully downloaded plugins
     189     * Replies the list of plugins whose download has failed.
     190     *
     191     * @return the list of plugins whose download has failed
    192192     */
    193193    public Collection<PluginInformation> getFailedPlugins() {
     
    196196
    197197    /**
    198      * Replies the list of plugins whose download has failed
    199      *
    200      * @return the list of plugins whose download has failed
     198     * Replies the list of successfully downloaded plugins.
     199     *
     200     * @return the list of successfully downloaded plugins
    201201     */
    202202    public Collection<PluginInformation> getDownloadedPlugins() {
  • 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
  • trunk/src/org/openstreetmap/josm/plugins/PluginInformation.java

    r7655 r8017  
    7878    /** The plugin icon. */
    7979    public ImageIcon icon;
     80    /** Plugin can be loaded at any time and not just at start. */
     81    public boolean canloadatruntime = false;
    8082    /** The libraries referenced in Class-Path manifest attribute. */
    8183    public List<URL> libraries = new LinkedList<>();
     
    169171        this.icon = other.icon;
    170172        this.iconPath = other.iconPath;
     173        this.canloadatruntime = other.canloadatruntime;
    171174        this.libraries = other.libraries;
    172175        this.attr.clear();
     
    189192        this.early = other.early;
    190193        this.className = other.className;
     194        this.canloadatruntime = other.canloadatruntime;
    191195        this.libraries = other.libraries;
    192196        this.stage = other.stage;
     
    250254            }
    251255        }
     256        canloadatruntime = Boolean.parseBoolean(attr.getValue("Plugin-Canloadatruntime"));
    252257        if (oldcheck && mainversion > Version.getInstance().getVersion()) {
    253258            int myv = Version.getInstance().getVersion();
Note: See TracChangeset for help on using the changeset viewer.