Ticket #18277: 18277.3.patch

File 18277.3.patch, 7.0 KB (added by taylor.smock, 6 years ago)

Change returnBoolean to restartNeeded, log error when a plugin can't destroy itself, and add initial test (currently fails -- there is a plugin that implements destroyable already, but I don't know if that is the cause of the failure).

  • src/org/openstreetmap/josm/gui/preferences/plugin/PluginPreference.java

     
    5555import org.openstreetmap.josm.gui.util.GuiHelper;
    5656import org.openstreetmap.josm.gui.widgets.FilterField;
    5757import org.openstreetmap.josm.plugins.PluginDownloadTask;
     58import org.openstreetmap.josm.plugins.PluginHandler;
    5859import org.openstreetmap.josm.plugins.PluginInformation;
    5960import org.openstreetmap.josm.plugins.ReadLocalPluginInformationTask;
    6061import org.openstreetmap.josm.plugins.ReadRemotePluginInformationTask;
     
    324325            List<String> l = new LinkedList<>(model.getSelectedPluginNames());
    325326            Collections.sort(l);
    326327            Config.getPref().putList("plugins", l);
    327             if (!model.getNewlyDeactivatedPlugins().isEmpty())
    328                 return true;
     328            List<PluginInformation> deactivatedPlugins = model.getNewlyDeactivatedPlugins();
     329            if (!deactivatedPlugins.isEmpty()) {
     330                boolean requiresRestart = PluginHandler.removePlugins(deactivatedPlugins);
     331                if (requiresRestart)
     332                    return requiresRestart;
     333            }
    329334            for (PluginInformation pi : model.getNewlyActivatedPlugins()) {
    330335                if (!pi.canloadatruntime)
    331336                    return true;
  • src/org/openstreetmap/josm/plugins/PluginHandler.java

     
    6868import org.openstreetmap.josm.io.OfflineAccessException;
    6969import org.openstreetmap.josm.io.OnlineResource;
    7070import org.openstreetmap.josm.spi.preferences.Config;
     71import org.openstreetmap.josm.tools.Destroyable;
    7172import org.openstreetmap.josm.tools.GBC;
    7273import org.openstreetmap.josm.tools.I18n;
    7374import org.openstreetmap.josm.tools.ImageProvider;
     
    11671168                        pluginsToDownload,
    11681169                        tr("Update plugins")
    11691170                );
    1170 
    11711171                try {
    11721172                    pluginDownloadTask.run();
    11731173                } catch (RuntimeException e) { // NOPMD
     
    13311331                    URL oldPluginURL = updatedPlugin.toURI().toURL();
    13321332                    pluginsToLoad.stream().filter(x -> x.libraries.contains(oldPluginURL)).forEach(
    13331333                            x -> Collections.replaceAll(x.libraries, oldPluginURL, newPluginURL));
     1334
     1335                    // Attempt to update loaded plugin (must implement Destroyable)
     1336                    PluginInformation tInfo = pluginsToLoad.parallelStream()
     1337                            .filter(x -> x.libraries.contains(newPluginURL)).findAny().orElse(null);
     1338                    if (tInfo != null) {
     1339                        Object tUpdatedPlugin = getPlugin(tInfo.name);
     1340                        if (tUpdatedPlugin instanceof Destroyable) {
     1341                            ((Destroyable) tUpdatedPlugin).destroy();
     1342                            PluginHandler.loadPlugins(getInfoPanel(), Collections.singleton(tInfo),
     1343                                    NullProgressMonitor.INSTANCE);
     1344                        }
     1345                    }
    13341346                } catch (MalformedURLException e) {
    13351347                    Logging.warn(e);
    13361348                }
     
    16421654            return cbDontShowAgain.isSelected();
    16431655        }
    16441656    }
     1657
     1658    /**
     1659     * Remove deactivated plugins, returning true if JOSM should restart
     1660     *
     1661     * @param deactivatedPlugins
     1662     * @return true if there was a plugin that requires a restart
     1663     */
     1664    public static boolean removePlugins(List<PluginInformation> deactivatedPlugins) {
     1665        List<Destroyable> noRestart = deactivatedPlugins.parallelStream()
     1666                .map(info -> PluginHandler.getPlugin(info.name)).filter(Destroyable.class::isInstance)
     1667                .map(Destroyable.class::cast).collect(Collectors.toList());
     1668        boolean restartNeeded;
     1669        try {
     1670            noRestart.forEach(Destroyable::destroy);
     1671            restartNeeded = deactivatedPlugins.size() != noRestart.size();
     1672        } catch (Exception e) {
     1673            Logging.error(e);
     1674            restartNeeded = true;
     1675        }
     1676        return restartNeeded;
     1677    }
    16451678}
  • test/unit/org/openstreetmap/josm/plugins/PluginHandlerTestIT.java

     
    1313import java.util.Iterator;
    1414import java.util.List;
    1515import java.util.Map;
     16import java.util.Optional;
    1617import java.util.Set;
    1718import java.util.function.Consumer;
    1819import java.util.stream.Collectors;
     
    3031import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
    3132import org.openstreetmap.josm.spi.preferences.Config;
    3233import org.openstreetmap.josm.testutils.JOSMTestRules;
     34import org.openstreetmap.josm.tools.Destroyable;
    3335import org.openstreetmap.josm.tools.Utils;
    3436
    3537import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
     
    7476            testPlugin(MainApplication.getLayerManager()::removeLayer, layer, layerExceptions, loadedPlugins);
    7577        }
    7678
     79        testCompletelyRestartlessPlugins(loadedPlugins);
     80
    7781        debugPrint(invalidManifestEntries);
    7882        debugPrint(loadingExceptions);
    7983        debugPrint(layerExceptions);
     
    8387        assertTrue(msg, invalidManifestEntries.isEmpty() && loadingExceptions.isEmpty() && layerExceptions.isEmpty());
    8488    }
    8589
     90    private static void testCompletelyRestartlessPlugins(List<PluginInformation> loadedPlugins) {
     91        List<PluginInformation> restartable = loadedPlugins.parallelStream()
     92                .filter(info -> PluginHandler.getPlugin(info.name) instanceof Destroyable).collect(Collectors.toList());
     93        // ensure good plugin behavior with regards to Destroyable
     94        for (int i = 0; i < 2; i++) {
     95            assertFalse(PluginHandler.removePlugins(restartable));
     96            Optional<PluginInformation> optional = restartable.stream()
     97                    .filter(info -> PluginHandler.getPlugins().contains(info)).findAny();
     98            assertTrue(restartable.stream().noneMatch(info -> PluginHandler.getPlugins().contains(info)));
     99            PluginHandler.loadEarlyPlugins(null, restartable, null);
     100            PluginHandler.loadLatePlugins(null, restartable, null);
     101        }
     102
     103        assertTrue(PluginHandler.removePlugins(loadedPlugins));
     104        assertTrue(restartable.parallelStream().noneMatch(info -> PluginHandler.getPlugins().contains(info)));
     105    }
     106
    86107    private static void debugPrint(Map<String, ?> invalidManifestEntries) {
    87108        System.out.println(invalidManifestEntries.entrySet()
    88109                .stream()