Index: trunk/src/org/openstreetmap/josm/plugins/PluginHandler.java
===================================================================
--- trunk/src/org/openstreetmap/josm/plugins/PluginHandler.java	(revision 9869)
+++ trunk/src/org/openstreetmap/josm/plugins/PluginHandler.java	(revision 9870)
@@ -130,4 +130,5 @@
             new DeprecatedPlugin("missingRoads", tr("replaced by new {0} plugin", "ImproveOsm")),
             new DeprecatedPlugin("trafficFlowDirection", tr("replaced by new {0} plugin", "ImproveOsm")),
+            new DeprecatedPlugin("kendzi3d-jogl", tr("replaced by new {0} plugin", "jogl")),
         });
     }
@@ -145,14 +146,4 @@
         /** Short explanation about deprecation, can be {@code null} */
         public final String reason;
-        /** Code to run to perform migration, can be {@code null} */
-        private final Runnable migration;
-
-        /**
-         * Constructs a new {@code DeprecatedPlugin}.
-         * @param name The plugin name
-         */
-        public DeprecatedPlugin(String name) {
-            this(name, null, null);
-        }
 
         /**
@@ -162,31 +153,43 @@
          */
         public DeprecatedPlugin(String name, String reason) {
-            this(name, reason, null);
-        }
-
-        /**
-         * Constructs a new {@code DeprecatedPlugin}.
-         * @param name The plugin name
-         * @param reason The reason about deprecation
-         * @param migration The code to run to perform migration
-         */
-        public DeprecatedPlugin(String name, String reason, Runnable migration) {
             this.name = name;
             this.reason = reason;
-            this.migration = migration;
-        }
-
-        /**
-         * Performs migration.
-         */
-        public void migrate() {
-            if (migration != null) {
-                migration.run();
-            }
+        }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = prime + ((name == null) ? 0 : name.hashCode());
+            return prime * result + ((reason == null) ? 0 : reason.hashCode());
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj)
+                return true;
+            if (obj == null)
+                return false;
+            if (getClass() != obj.getClass())
+                return false;
+            DeprecatedPlugin other = (DeprecatedPlugin) obj;
+            if (name == null) {
+                if (other.name != null)
+                    return false;
+            } else if (!name.equals(other.name))
+                return false;
+            if (reason == null) {
+                if (other.reason != null)
+                    return false;
+            } else if (!reason.equals(other.reason))
+                return false;
+            return true;
         }
 
         @Override
         public int compareTo(DeprecatedPlugin o) {
-            return name.compareTo(o.name);
+            int d = name.compareTo(o.name);
+            if (d == 0)
+                d = reason.compareTo(o.reason);
+            return d;
         }
     }
@@ -217,5 +220,5 @@
      * List of unmaintained plugins. Not really up-to-date as the vast majority of plugins are not maintained after a few months, sadly...
      */
-    private static final String[] UNMAINTAINED_PLUGINS = new String[] {
+    static final String[] UNMAINTAINED_PLUGINS = new String[] {
         "gpsbabelgui",
         "Intersect_way",
@@ -282,5 +285,4 @@
                 Main.pref.removeFromCollection("plugins", depr.name);
                 removedPlugins.add(depr);
-                depr.migrate();
             }
         }
@@ -661,4 +663,5 @@
         if (pluginClassLoader == null) {
             pluginClassLoader = AccessController.doPrivileged(new PrivilegedAction<DynamicURLClassLoader>() {
+                @Override
                 public DynamicURLClassLoader run() {
                     return new DynamicURLClassLoader(new URL[0], Main.class.getClassLoader());
@@ -853,11 +856,13 @@
                 plugins.size()))
           .append("</html>");
-        HelpAwareOptionPane.showOptionDialog(
-                parent,
-                sb.toString(),
-                tr("Warning"),
-                JOptionPane.WARNING_MESSAGE,
-                HelpUtil.ht("/Plugin/Loading#MissingPluginInfos")
-        );
+        if (!GraphicsEnvironment.isHeadless()) {
+            HelpAwareOptionPane.showOptionDialog(
+                    parent,
+                    sb.toString(),
+                    tr("Warning"),
+                    JOptionPane.WARNING_MESSAGE,
+                    HelpUtil.ht("/Plugin/Loading#MissingPluginInfos")
+            );
+        }
     }
 
@@ -878,5 +883,5 @@
             monitor.beginTask(tr("Determine plugins to load..."));
             Set<String> plugins = new HashSet<>();
-            plugins.addAll(Main.pref.getCollection("plugins",  new LinkedList<String>()));
+            plugins.addAll(Main.pref.getCollection("plugins", new LinkedList<String>()));
             if (System.getProperty("josm.plugins") != null) {
                 plugins.addAll(Arrays.asList(System.getProperty("josm.plugins").split(",")));
Index: trunk/test/unit/org/openstreetmap/josm/plugins/PluginHandlerTest.java
===================================================================
--- trunk/test/unit/org/openstreetmap/josm/plugins/PluginHandlerTest.java	(revision 9870)
+++ trunk/test/unit/org/openstreetmap/josm/plugins/PluginHandlerTest.java	(revision 9870)
@@ -0,0 +1,60 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.openstreetmap.josm.JOSMFixture;
+import org.openstreetmap.josm.plugins.PluginHandler.DeprecatedPlugin;
+import org.openstreetmap.josm.tools.Utils;
+
+import nl.jqno.equalsverifier.EqualsVerifier;
+
+/**
+ * Unit tests of {@link PluginHandler} class.
+ */
+public class PluginHandlerTest {
+
+    /**
+     * Setup test.
+     */
+    @BeforeClass
+    public static void setUp() {
+        JOSMFixture.createUnitTestFixture().init();
+    }
+
+    /**
+     * Unit test of methods {@link DeprecatedPlugin#equals} and {@link DeprecatedPlugin#hashCode}.
+     */
+    @Test
+    public void equalsContract() {
+        EqualsVerifier.forClass(DeprecatedPlugin.class).usingGetClass().verify();
+    }
+
+    /**
+     * Unit test of {@link PluginHandler#buildListOfPluginsToLoad}.
+     */
+    @Test
+    public void testBuildListOfPluginsToLoad() {
+        final String old = System.getProperty("josm.plugins");
+        try {
+            System.setProperty("josm.plugins",
+                    Utils.join(",", PluginHandler.DEPRECATED_PLUGINS) + "," +
+                    Utils.join(",", Arrays.asList(PluginHandler.UNMAINTAINED_PLUGINS)));
+            List<PluginInformation> list = PluginHandler.buildListOfPluginsToLoad(null, null);
+            assertNotNull(list);
+            assertTrue(list.isEmpty());
+        } finally {
+            if (old != null) {
+                System.setProperty("josm.plugins", old);
+            } else {
+                System.clearProperty("josm.plugins");
+            }
+        }
+    }
+}
