Changeset 2817 in josm for trunk/src/org/openstreetmap/josm/plugins
- Timestamp:
- 2010-01-11T21:06:49+01:00 (16 years ago)
- Location:
- trunk/src/org/openstreetmap/josm/plugins
- Files:
-
- 6 added
- 2 deleted
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/plugins/Plugin.java
r1169 r2817 53 53 */ 54 54 public final String getPluginDir() { 55 return new File(Main.pref.getPluginsDir File(), info.name).getPath();55 return new File(Main.pref.getPluginsDirectory(), info.name).getPath(); 56 56 } 57 57 … … 81 81 String pluginDirName = Main.pref.getPreferencesDir()+"plugins/"+info.name+"/"; 82 82 File pluginDir = new File(pluginDirName); 83 if (!pluginDir.exists()) 83 if (!pluginDir.exists()) { 84 84 pluginDir.mkdirs(); 85 } 85 86 FileOutputStream out = new FileOutputStream(pluginDirName+to); 86 87 InputStream in = getClass().getResourceAsStream(from); 87 88 byte[] buffer = new byte[8192]; 88 for(int len = in.read(buffer); len > 0; len = in.read(buffer)) 89 for(int len = in.read(buffer); len > 0; len = in.read(buffer)) { 89 90 out.write(buffer, 0, len); 91 } 90 92 in.close(); 91 93 out.close(); -
trunk/src/org/openstreetmap/josm/plugins/PluginException.java
r2512 r2817 11 11 * @author Immanuel.Scholz 12 12 */ 13 public class PluginException extends RuntimeException {13 public class PluginException extends Exception { 14 14 public final PluginProxy plugin; 15 15 public final String name; … … 20 20 this.name = name; 21 21 } 22 23 public PluginException(String name, String message) { 24 super(message); 25 this.plugin = null; 26 this.name = name; 27 } 28 29 public PluginException(String name, Throwable cause) { 30 super(tr("An error occurred in plugin {0}", name), cause); 31 this.plugin = null; 32 this.name = name; 33 } 22 34 } -
trunk/src/org/openstreetmap/josm/plugins/PluginHandler.java
r2584 r2817 4 4 import static org.openstreetmap.josm.gui.help.HelpUtil.ht; 5 5 import static org.openstreetmap.josm.tools.I18n.tr; 6 import static org.openstreetmap.josm.tools.I18n.trn; 6 7 7 8 import java.awt.Font; 8 9 import java.awt.GridBagLayout; 9 10 import java.awt.event.ActionEvent; 11 import java.io.File; 12 import java.io.FilenameFilter; 10 13 import java.net.URL; 11 14 import java.net.URLClassLoader; … … 14 17 import java.util.Collection; 15 18 import java.util.Collections; 19 import java.util.Comparator; 20 import java.util.HashMap; 21 import java.util.HashSet; 22 import java.util.Iterator; 16 23 import java.util.LinkedList; 17 24 import java.util.List; 18 import java.util. SortedMap;19 import java.util. TreeMap;25 import java.util.Map; 26 import java.util.Set; 20 27 import java.util.Map.Entry; 28 import java.util.concurrent.ExecutionException; 29 import java.util.concurrent.ExecutorService; 30 import java.util.concurrent.Executors; 31 import java.util.concurrent.Future; 21 32 22 33 import javax.swing.AbstractAction; … … 37 48 import org.openstreetmap.josm.gui.download.DownloadSelection; 38 49 import org.openstreetmap.josm.gui.preferences.PreferenceSettingFactory; 50 import org.openstreetmap.josm.gui.progress.NullProgressMonitor; 51 import org.openstreetmap.josm.gui.progress.ProgressMonitor; 52 import org.openstreetmap.josm.tools.CheckParameterUtil; 39 53 import org.openstreetmap.josm.tools.GBC; 40 54 import org.openstreetmap.josm.tools.ImageProvider; 41 55 56 /** 57 * PluginHandler is basically a collection of static utility functions used to bootstrap 58 * and manage the loaded plugins. 59 * 60 */ 42 61 public class PluginHandler { 43 62 44 public static String [] oldplugins = new String[] {"mappaint", "unglueplugin", 45 "lang-de", "lang-en_GB", "lang-fr", "lang-it", "lang-pl", "lang-ro", 46 "lang-ru", "ewmsplugin", "ywms", "tways-0.2", "geotagged", "landsat", 47 "namefinder", "waypoints", "slippy_map_chooser", "tcx-support", "usertools", 48 "AgPifoJ", "utilsplugin"}; 49 public static String [] unmaintained = new String[] {"gpsbabelgui", "Intersect_way"}; 63 final public static String [] DEPRECATED_PLUGINS = new String[] {"mappaint", "unglueplugin", 64 "lang-de", "lang-en_GB", "lang-fr", "lang-it", "lang-pl", "lang-ro", 65 "lang-ru", "ewmsplugin", "ywms", "tways-0.2", "geotagged", "landsat", 66 "namefinder", "waypoints", "slippy_map_chooser", "tcx-support", "usertools", 67 "AgPifoJ", "utilsplugin"}; 68 69 final public static String [] UNMAINTAINED_PLUGINS = new String[] {"gpsbabelgui", "Intersect_way"}; 50 70 51 71 /** … … 53 73 */ 54 74 public final static Collection<PluginProxy> pluginList = new LinkedList<PluginProxy>(); 55 /** 56 * Load all plugins specified in preferences. If the parameter is 57 * <code>true</code>, all early plugins are loaded (before constructor). 58 */ 59 public static void loadPlugins(boolean early) { 60 List<String> plugins = new LinkedList<String>(); 61 Collection<String> cp = Main.pref.getCollection("plugins", null); 62 if (cp != null) { 63 plugins.addAll(cp); 64 } 65 if (System.getProperty("josm.plugins") != null) { 66 plugins.addAll(Arrays.asList(System.getProperty("josm.plugins").split(","))); 67 } 68 69 for (String p : oldplugins) { 75 76 77 /** 78 * Removes deprecated plugins from a collection of plugins. Modifies the 79 * collection <code>plugins</code>. 80 * 81 * Also notifies the user about removed deprecated plugins 82 * 83 * @param plugins the collection of plugins 84 */ 85 private static void filterDeprecatedPlugins(Collection<String> plugins) { 86 Set<String> removedPlugins = new HashSet<String>(); 87 for (String p : DEPRECATED_PLUGINS) { 70 88 if (plugins.contains(p)) { 71 89 plugins.remove(p); 72 90 Main.pref.removeFromCollection("plugins", p); 73 JOptionPane.showMessageDialog( 74 Main.parent, 75 tr("Plugin {0} is no longer necessary and has been deactivated.", p), 76 tr("Warning"), 77 JOptionPane.WARNING_MESSAGE 78 ); 79 } 80 } 81 if(early) 82 { 83 for (String p : unmaintained) { 84 if (plugins.contains(p) && disablePlugin(tr("<html>Loading of {0} plugin was requested." 85 +"<br>This plugin is no longer developed and very likely will produce errors." 86 +"<br>It should be disabled.<br>Delete from preferences?</html>", p), p)) { 87 plugins.remove(p); 88 } 89 } 90 } 91 92 if (plugins.isEmpty()) 91 removedPlugins.add(p); 92 } 93 } 94 if (removedPlugins.isEmpty()) 93 95 return; 94 96 95 if(early) 96 { 97 String doUpdate = null; 98 String check = null; 99 int v = Version.getInstance().getVersion(); 100 if(Main.pref.getInteger("pluginmanager.version", 0) < v) 101 { 102 doUpdate = tr("You updated your JOSM software.\nTo prevent problems the plugins should be updated as well.\n" 103 + "Update plugins now?"); 104 check = "pluginmanger.version"; 105 } 106 else 107 { 108 long tim = System.currentTimeMillis(); 109 long last = Main.pref.getLong("pluginmanager.lastupdate", 0); 110 Integer maxTime = Main.pref.getInteger("pluginmanager.warntime", 60); 111 long d = (tim - last)/(24*60*60*1000l); 112 if ((last <= 0) || (maxTime <= 0)) { 113 Main.pref.put("pluginmanager.lastupdate",Long.toString(tim)); 114 } else if (d > maxTime) { 115 doUpdate = tr("Last plugin update more than {0} days ago.", d); 116 check = "pluginmanager.time"; 117 } 118 } 119 if(doUpdate != null) 120 { 121 ExtendedDialog dialog = new ExtendedDialog( 122 Main.parent, 123 tr("Update plugins"), 124 new String[] {tr("Update plugins"), tr("Skip update")} 125 ); 126 dialog.setContent(doUpdate); 127 dialog.toggleEnable(check); 128 dialog.setButtonIcons( new String[] {"dialogs/refresh.png", "cancel.png"}); 129 dialog.configureContextsensitiveHelp(ht("/Plugin/AutomaticUpdate"), true /* show help button */); 130 dialog.showDialog(); 131 if(dialog.getValue() == 1) { 132 new PluginSelection().update(); 133 } 134 } 135 } 136 137 SortedMap<Integer, Collection<PluginInformation>> p = new TreeMap<Integer, Collection<PluginInformation>>(); 138 for (String pluginName : plugins) { 139 PluginInformation info = PluginInformation.findPlugin(pluginName); 140 if (info != null) { 141 if (info.early != early) { 142 continue; 143 } 144 int josmVersion = Version.getInstance().getVersion(); 145 if (info.mainversion > josmVersion && josmVersion != Version.JOSM_UNKNOWN_VERSION) { 146 JOptionPane.showMessageDialog( 147 Main.parent, 148 tr("Plugin {0} requires JOSM update to version {1}.", pluginName, 149 info.mainversion), 150 tr("Warning"), 151 JOptionPane.WARNING_MESSAGE 152 ); 153 continue; 154 } 155 156 if(info.requires != null) 157 { 158 String warn = null; 159 for(String n : info.requires.split(";")) 160 { 161 if(!plugins.contains(n)) 162 { warn = n; break; } 163 } 164 if(warn != null) 165 { 166 JOptionPane.showMessageDialog(Main.parent, 167 tr("Plugin {0} is required by plugin {1} but was not found.", 168 warn, pluginName), 169 tr("Error"), 170 JOptionPane.ERROR_MESSAGE 171 ); 172 continue; 173 } 174 } 175 if (!p.containsKey(info.stage)) { 176 p.put(info.stage, new LinkedList<PluginInformation>()); 177 } 178 p.get(info.stage).add(info); 179 } else if(early) { 180 JOptionPane.showMessageDialog( 181 Main.parent, 182 tr("Plugin not found: {0}.", pluginName), 183 tr("Error"), 184 JOptionPane.ERROR_MESSAGE 185 ); 186 } 187 } 188 97 // notify user about removed deprecated plugins 98 // 99 StringBuffer sb = new StringBuffer(); 100 sb.append("<html>"); 101 sb.append(trn( 102 "The following plugin is no longer necessary and has been deactivated:", 103 "The following plugins are no longer necessary and have been deactivated:", 104 removedPlugins.size() 105 )); 106 sb.append("<ul>"); 107 for (String name: removedPlugins) { 108 sb.append("<li>").append(name).append("</li>"); 109 } 110 sb.append("</ul>"); 111 sb.append("</html>"); 112 JOptionPane.showMessageDialog( 113 Main.parent, 114 sb.toString(), 115 tr("Warning"), 116 JOptionPane.WARNING_MESSAGE 117 ); 118 } 119 120 /** 121 * Removes unmaintained plugins from a collection of plugins. Modifies the 122 * collection <code>plugins</code>. Also removes the plugin from the list 123 * of plugins in the preferences, if necessary. 124 * 125 * Asks the user for every unmaintained plugin whether it should be removed. 126 * 127 * @param plugins the collection of plugins 128 */ 129 private static void filterUnmaintainedPlugins(Collection<String> plugins) { 130 for (String unmaintained : UNMAINTAINED_PLUGINS) { 131 if (!plugins.contains(unmaintained)) { 132 continue; 133 } 134 String msg = tr("<html>Loading of {0} plugin was requested." 135 + "<br>This plugin is no longer developed and very likely will produce errors." 136 +"<br>It should be disabled.<br>Delete from preferences?</html>", unmaintained); 137 if (confirmDisablePlugin(msg,unmaintained)) { 138 Main.pref.removeFromCollection("plugins", unmaintained); 139 plugins.remove(unmaintained); 140 } 141 } 142 } 143 144 /** 145 * Checks whether the locally available plugins should be updated and 146 * asks the user if running an update is OK. An update is advised if 147 * JOSM was updated to a new version since the last plugin updates or 148 * if the plugins were last updated a long time ago. 149 * 150 * @return true if a plugin update should be run; false, otherwise 151 */ 152 public static boolean checkAndConfirmPluginUpdate() { 153 String message = null; 154 String togglePreferenceKey = null; 155 int v = Version.getInstance().getVersion(); 156 if (Main.pref.getInteger("pluginmanager.version", 0) < v) { 157 message = tr("<html>You updated your JOSM software.<br>" 158 + "To prevent problems the plugins should be updated as well.<br><br>" 159 + "Update plugins now?" 160 + "</html>" 161 ); 162 togglePreferenceKey = "pluginmanger.version"; 163 } else { 164 long tim = System.currentTimeMillis(); 165 long last = Main.pref.getLong("pluginmanager.lastupdate", 0); 166 Integer maxTime = Main.pref.getInteger("pluginmanager.warntime", 60); 167 long d = (tim - last) / (24 * 60 * 60 * 1000l); 168 if ((last <= 0) || (maxTime <= 0)) { 169 Main.pref.put("pluginmanager.lastupdate", Long.toString(tim)); 170 } else if (d > maxTime) { 171 message = tr("Last plugin update more than {0} days ago.", d); 172 togglePreferenceKey = "pluginmanager.time"; 173 } 174 } 175 if (message == null) return false; 176 177 // ask whether update is fine 178 // 179 ExtendedDialog dialog = new ExtendedDialog( 180 Main.parent, 181 tr("Update plugins"), 182 new String[] { 183 tr("Update plugins"), tr("Skip update") 184 } 185 ); 186 dialog.setContent(message); 187 dialog.toggleEnable(togglePreferenceKey); 188 dialog.setButtonIcons( new String[] {"dialogs/refresh.png", "cancel.png"}); 189 dialog.configureContextsensitiveHelp(ht("/Plugin/AutomaticUpdate"), true /* show help button */); 190 dialog.showDialog(); 191 return dialog.getValue() == 1; 192 } 193 194 /** 195 * Alerts the user if a plugin required by another plugin is missing 196 * 197 * @param plugin the the plugin 198 * @param missingRequiredPlugin the missing required plugin 199 */ 200 private static void alertMissingRequiredPlugin(String plugin, Set<String> missingRequiredPlugin) { 201 StringBuilder sb = new StringBuilder(); 202 sb.append("<html>"); 203 sb.append(trn("A required plugin for plugin {0} was not found. The required plugin is:", 204 "{1} required plugins for plugin {0} were not found. The required plugins are:", 205 missingRequiredPlugin.size(), 206 plugin, 207 missingRequiredPlugin.size() 208 )); 209 sb.append("<ul>"); 210 for (String p: missingRequiredPlugin) { 211 sb.append("<li>").append(p).append("</li>"); 212 } 213 sb.append("</ul>").append("</html>"); 214 JOptionPane.showMessageDialog( 215 Main.parent, 216 sb.toString(), 217 tr("Error"), 218 JOptionPane.ERROR_MESSAGE 219 ); 220 } 221 222 /** 223 * Checks whether all preconditions for loading the plugin <code>plugin</code> are met. The 224 * current JOSM version must be compatible with the plugin and no other plugins this plugin 225 * depends on should be missing. 226 * 227 * @param plugins the collection of all loaded plugins 228 * @param plugin the plugin for which preconditions are checked 229 * @return true, if the preconditions are met; false otherwise 230 */ 231 public static boolean checkLoadPreconditions(Collection<PluginInformation> plugins, PluginInformation plugin) { 232 233 // make sure the plugin is compatible with the current JOSM version 234 // 235 int josmVersion = Version.getInstance().getVersion(); 236 if (plugin.mainversion > josmVersion && josmVersion != Version.JOSM_UNKNOWN_VERSION) { 237 JOptionPane.showMessageDialog( 238 Main.parent, 239 tr("Plugin {0} requires JOSM update to version {1}.", plugin.name, 240 plugin.mainversion), 241 tr("Warning"), 242 JOptionPane.WARNING_MESSAGE 243 ); 244 return false; 245 } 246 247 // make sure the dependencies to other plugins are not broken 248 // 249 if(plugin.requires != null){ 250 Set<String> pluginNames = new HashSet<String>(); 251 for (PluginInformation pi: plugins) { 252 pluginNames.add(pi.name); 253 } 254 Set<String> missingPlugins = new HashSet<String>(); 255 for (String requiredPlugin : plugin.requires.split(";")) { 256 if (!pluginNames.contains(requiredPlugin)) { 257 missingPlugins.add(requiredPlugin); 258 } 259 } 260 if (!missingPlugins.isEmpty()) { 261 alertMissingRequiredPlugin(plugin.name, missingPlugins); 262 return false; 263 } 264 } 265 return true; 266 } 267 268 /** 269 * Creates a class loader for loading plugin code. 270 * 271 * @param plugins the collection of plugins which are going to be loaded with this 272 * class loader 273 * @return the class loader 274 */ 275 public static ClassLoader createClassLoader(Collection<PluginInformation> plugins) { 189 276 // iterate all plugins and collect all libraries of all plugins: 190 List<URL> allPluginLibraries = new ArrayList<URL>(); 191 for (Collection<PluginInformation> c : p.values()) { 192 for (PluginInformation info : c) { 193 allPluginLibraries.addAll(info.libraries); 194 } 195 } 277 List<URL> allPluginLibraries = new LinkedList<URL>(); 278 File pluginDir = Main.pref.getPluginsDirectory(); 279 for (PluginInformation info : plugins) { 280 if (info.libraries == null) { 281 continue; 282 } 283 allPluginLibraries.addAll(info.libraries); 284 File pluginJar = new File(pluginDir, info.name + ".jar"); 285 URL pluginJarUrl = PluginInformation.fileToURL(pluginJar); 286 allPluginLibraries.add(pluginJarUrl); 287 } 288 196 289 // create a classloader for all plugins: 197 290 URL[] jarUrls = new URL[allPluginLibraries.size()]; 198 291 jarUrls = allPluginLibraries.toArray(jarUrls); 199 292 URLClassLoader pluginClassLoader = new URLClassLoader(jarUrls, Main.class.getClassLoader()); 200 ImageProvider.sources.add(0, pluginClassLoader); 201 202 for (Collection<PluginInformation> c : p.values()) { 203 for (PluginInformation info : c) { 204 try { 205 Class<?> klass = info.loadClass(pluginClassLoader); 206 if (klass != null) { 207 System.out.println("loading "+info.name); 208 pluginList.add(info.load(klass)); 293 return pluginClassLoader; 294 } 295 296 /** 297 * Loads and instantiates the plugin described by <code>plugin</code> using 298 * the class loader <code>pluginClassLoader</code>. 299 * 300 * @param plugin the plugin 301 * @param pluginClassLoader the plugin class loader 302 */ 303 public static void loadPlugin(PluginInformation plugin, ClassLoader pluginClassLoader) { 304 try { 305 Class<?> klass = plugin.loadClass(pluginClassLoader); 306 if (klass != null) { 307 System.out.println(tr("loading plugin ''{0}''", plugin.name)); 308 pluginList.add(plugin.load(klass)); 309 } 310 } catch (Throwable e) { 311 e.printStackTrace(); 312 String msg = tr("Could not load plugin {0}. Delete from preferences?", plugin.name); 313 if (confirmDisablePlugin(msg, plugin.name)) { 314 Main.pref.removeFromCollection("plugins", plugin.name); 315 } 316 } 317 } 318 319 /** 320 * Loads the plugin in <code>plugins</code> from locally available jar files into 321 * memory. 322 * 323 * @param plugins the list of plugins 324 * @param monitor the progress monitor. Defaults to {@see NullProgressMonitor#INSTANCE} if null. 325 */ 326 public static void loadPlugins(Collection<PluginInformation> plugins, ProgressMonitor monitor) { 327 if (monitor == null) { 328 monitor = NullProgressMonitor.INSTANCE; 329 } 330 try { 331 monitor.beginTask(tr("Loading plugins ...")); 332 List<PluginInformation> toLoad = new LinkedList<PluginInformation>(); 333 // sort the plugins according to their "staging" equivalence class. The 334 // lower the value of "stage" the earlier the plugin should be loaded. 335 // 336 Collections.sort( 337 toLoad, 338 new Comparator<PluginInformation>() { 339 public int compare(PluginInformation o1, PluginInformation o2) { 340 if (o1.stage < o2.stage) return -1; 341 if (o1.stage == o2.stage) return 0; 342 return 1; 343 } 209 344 } 210 } catch (Throwable e) { 211 e.printStackTrace(); 212 disablePlugin(tr("Could not load plugin {0}. Delete from preferences?", info.name), info.name); 213 } 214 } 215 } 216 } 217 public static boolean disablePlugin(String reason, String name) 218 { 345 ); 346 monitor.subTask(tr("Checking plugin preconditions...")); 347 for (PluginInformation pi: plugins) { 348 if (checkLoadPreconditions(plugins, pi)) { 349 toLoad.add(pi); 350 } 351 } 352 if (toLoad.isEmpty()) 353 return; 354 355 ClassLoader pluginClassLoader = createClassLoader(toLoad); 356 ImageProvider.sources.add(0, pluginClassLoader); 357 monitor.setTicksCount(toLoad.size()); 358 for (PluginInformation info : toLoad) { 359 monitor.setExtraText(tr("Loading plugin ''{0}''...", info.name)); 360 loadPlugin(info, pluginClassLoader); 361 monitor.worked(1); 362 } 363 } finally { 364 monitor.finishTask(); 365 } 366 } 367 368 /** 369 * Loads plugins from <code>plugins</code> which have the flag {@see PluginInformation#early} 370 * set to true. 371 * 372 * @param plugins the collection of plugins 373 * @param monitor the progress monitor. Defaults to {@see NullProgressMonitor#INSTANCE} if null. 374 */ 375 public static void loadEarlyPlugins(Collection<PluginInformation> plugins, ProgressMonitor monitor) { 376 List<PluginInformation> earlyPlugins = new ArrayList<PluginInformation>(plugins.size()); 377 for (PluginInformation pi: plugins) { 378 if (pi.early) { 379 earlyPlugins.add(pi); 380 } 381 } 382 loadPlugins(earlyPlugins, monitor); 383 } 384 385 /** 386 * Loads plugins from <code>plugins</code> which have the flag {@see PluginInformation#early} 387 * set to false. 388 * 389 * @param plugins the collection of plugins 390 * @param monitor the progress monitor. Defaults to {@see NullProgressMonitor#INSTANCE} if null. 391 */ 392 public static void loadLatePlugins(Collection<PluginInformation> plugins, ProgressMonitor monitor) { 393 List<PluginInformation> latePlugins = new ArrayList<PluginInformation>(plugins.size()); 394 for (PluginInformation pi: plugins) { 395 if (!pi.early) { 396 latePlugins.add(pi); 397 } 398 } 399 loadPlugins(latePlugins, monitor); 400 } 401 402 /** 403 * Loads locally available plugin information from local plugin jars and from cached 404 * plugin lists. 405 * 406 * @param monitor the progress monitor. Defaults to {@see NullProgressMonitor#INSTANCE} if null. 407 * @return the list of locally available plugin information 408 * 409 */ 410 private static Map<String, PluginInformation> loadLocallyAvailablePluginInformation(ProgressMonitor monitor) { 411 if (monitor == null) { 412 monitor = NullProgressMonitor.INSTANCE; 413 } 414 try { 415 ReadLocalPluginInformationTask task = new ReadLocalPluginInformationTask(monitor); 416 ExecutorService service = Executors.newSingleThreadExecutor(); 417 Future<?> future = service.submit(task); 418 try { 419 future.get(); 420 } catch(ExecutionException e) { 421 e.printStackTrace(); 422 return null; 423 } catch(InterruptedException e) { 424 e.printStackTrace(); 425 return null; 426 } 427 HashMap<String, PluginInformation> ret = new HashMap<String, PluginInformation>(); 428 for (PluginInformation pi: task.getAvailablePlugins()) { 429 ret.put(pi.name, pi); 430 } 431 return ret; 432 } finally { 433 monitor.finishTask(); 434 } 435 } 436 437 private static void alertMissingPluginInformation(Collection<String> plugins) { 438 StringBuilder sb = new StringBuilder(); 439 sb.append("<html>"); 440 sb.append(trn("JOSM could not find information about the following plugin:", 441 "JOSM could not find information about the following plugins:", 442 plugins.size())); 443 sb.append("<ul>"); 444 for (String plugin: plugins) { 445 sb.append("<li>").append(plugin).append("</li>"); 446 } 447 sb.append("</ul>"); 448 sb.append(trn("The plugin is not going to be loaded.", 449 "The plugins are not going to be loaded.", 450 plugins.size())); 451 sb.append("</html>"); 452 JOptionPane.showMessageDialog( 453 Main.parent, 454 sb.toString(), 455 tr("Warning"), 456 JOptionPane.WARNING_MESSAGE 457 ); 458 } 459 460 /** 461 * Builds the set of plugins to load. Deprecated and unmaintained plugins are filtered 462 * out. This involves user interaction. This method displays alert and confirmation 463 * messages. 464 * 465 * @param monitor the progress monitor. Defaults to {@see NullProgressMonitor#INSTANCE} if null. 466 * @return the set of plugins to load (as set of plugin names) 467 */ 468 public static List<PluginInformation> buildListOfPluginsToLoad(ProgressMonitor monitor) { 469 if (monitor == null) { 470 monitor = NullProgressMonitor.INSTANCE; 471 } 472 try { 473 monitor.beginTask(tr("Determine plugins to load...")); 474 Set<String> plugins = new HashSet<String>(); 475 plugins.addAll(Main.pref.getCollection("plugins", new LinkedList<String>())); 476 if (System.getProperty("josm.plugins") != null) { 477 plugins.addAll(Arrays.asList(System.getProperty("josm.plugins").split(","))); 478 } 479 monitor.subTask(tr("Removing deprecated plugins...")); 480 filterDeprecatedPlugins(plugins); 481 monitor.subTask(tr("Removing umaintained plugins...")); 482 filterUnmaintainedPlugins(plugins); 483 Map<String, PluginInformation> infos = loadLocallyAvailablePluginInformation(monitor.createSubTaskMonitor(1,false)); 484 List<PluginInformation> ret = new LinkedList<PluginInformation>(); 485 for (Iterator<String> it = plugins.iterator(); it.hasNext();) { 486 String plugin = it.next(); 487 if (infos.containsKey(plugin)) { 488 ret.add(infos.get(plugin)); 489 it.remove(); 490 } 491 } 492 if (!plugins.isEmpty()) { 493 alertMissingPluginInformation(plugins); 494 } 495 return ret; 496 } finally { 497 monitor.finishTask(); 498 } 499 } 500 501 private static void alertFailedPluginUpdate(Collection<PluginInformation> plugins) { 502 StringBuffer sb = new StringBuffer(); 503 sb.append("<html>"); 504 sb.append(trn( 505 "Updating the following plugin has failed:", 506 "Updating the following plugins has failed:", 507 plugins.size() 508 ) 509 ); 510 sb.append("<ul>"); 511 for (PluginInformation pi: plugins) { 512 sb.append("<li>").append(pi.name).append("</li>"); 513 } 514 sb.append("</ul>"); 515 sb.append(tr("Please open the Preference Dialog after JOSM has started and try to update them manually.")); 516 sb.append("</html>"); 517 JOptionPane.showMessageDialog( 518 Main.parent, 519 sb.toString(), 520 tr("Plugin update failed"), 521 JOptionPane.ERROR_MESSAGE 522 ); 523 } 524 525 /** 526 * Updates the plugins in <code>plugins</code>. 527 * 528 * @param plugins the collection of plugins to update. Must not be null. 529 * @param monitor the progress monitor. Defaults to {@see NullProgressMonitor#INSTANCE} if null. 530 * @throws IllegalArgumentException thrown if plugins is null 531 */ 532 public static void updatePlugins(Collection<PluginInformation> plugins, ProgressMonitor monitor) throws IllegalArgumentException{ 533 CheckParameterUtil.ensureParameterNotNull(plugins, "plugins"); 534 if (monitor == null) { 535 monitor = NullProgressMonitor.INSTANCE; 536 } 537 try { 538 PluginDownloadTask task = new PluginDownloadTask( 539 monitor, 540 plugins, 541 tr("Update plugins") 542 ); 543 ExecutorService service = Executors.newSingleThreadExecutor(); 544 Future<?> future = service.submit(task); 545 try { 546 future.get(); 547 } catch(ExecutionException e) { 548 e.printStackTrace(); 549 } catch(InterruptedException e) { 550 e.printStackTrace(); 551 } 552 if (! task.getFailedPlugins().isEmpty()) { 553 alertFailedPluginUpdate(task.getFailedPlugins()); 554 return; 555 } 556 } finally { 557 monitor.finishTask(); 558 } 559 // remember the update because it was successful 560 // 561 Main.pref.putInteger("pluginmanager.version", Version.getInstance().getVersion()); 562 Main.pref.put("pluginmanager.lastupdate", Long.toString(System.currentTimeMillis())); 563 } 564 565 /** 566 * Ask the user for confirmation that a plugin shall be disabled. 567 * 568 * @param reason the reason for disabling the plugin 569 * @param name the plugin name 570 * @return true, if the plugin shall be disabled; false, otherwise 571 */ 572 public static boolean confirmDisablePlugin(String reason, String name) { 219 573 ExtendedDialog dialog = new ExtendedDialog( 220 574 Main.parent, 221 575 tr("Disable plugin"), 222 new String[] {tr("Disable plugin"), tr("Keep plugin")} 576 new String[] { 577 tr("Disable plugin"), tr("Keep plugin") 578 } 223 579 ); 224 580 dialog.setContent(reason); 225 dialog.setButtonIcons( 581 dialog.setButtonIcons(new String[] { "dialogs/delete.png", "cancel.png" }); 226 582 dialog.showDialog(); 227 int result = dialog.getValue(); 228 229 if(result == 1) 230 { 231 Main.pref.removeFromCollection("plugins", name); 232 return true; 233 } 234 return false; 235 } 236 237 public static void setMapFrame(MapFrame old, MapFrame map) { 583 return dialog.getValue() == 1; 584 } 585 586 /** 587 * Notified loaded plugins about a new map frame 588 * 589 * @param old the old map frame 590 * @param map the new map frame 591 */ 592 public static void notifyMapFrameChanged(MapFrame old, MapFrame map) { 238 593 for (PluginProxy plugin : pluginList) { 239 594 plugin.mapFrameInitialized(old, map); … … 248 603 } 249 604 250 public static void addDownloadSelection(List<DownloadSelection> downloadSelections) 251 { 605 public static void addDownloadSelection(List<DownloadSelection> downloadSelections) { 252 606 for (PluginProxy p : pluginList) { 253 607 p.addDownloadSelection(downloadSelections); 254 608 } 255 609 } 256 public static void getPreferenceSetting(Collection<PreferenceSettingFactory> settings) 257 { 610 611 public static void getPreferenceSetting(Collection<PreferenceSettingFactory> settings) { 258 612 for (PluginProxy plugin : pluginList) { 259 613 settings.add(new PluginPreferenceFactory(plugin)); … … 261 615 } 262 616 263 public static void earlyCleanup() 264 { 265 if (!PluginDownloader.moveUpdatedPlugins()) { 266 JOptionPane.showMessageDialog( 267 Main.parent, 268 tr("Activating the updated plugins failed. Check if JOSM has the permission to overwrite the existing ones."), 269 tr("Plugins"), JOptionPane.ERROR_MESSAGE); 270 } 271 } 272 public static Boolean checkException(Throwable e) 617 /** 618 * Installs downloaded plugins. Moves files with the suffix ".jar.new" to the corresponding 619 * ".jar" files. 620 * 621 */ 622 public static void installDownloadedPlugins() { 623 File pluginDir = Main.pref.getPluginsDirectory(); 624 if (! pluginDir.exists() || ! pluginDir.isDirectory() || ! pluginDir.canWrite()) 625 return; 626 627 final File[] files = pluginDir.listFiles(new FilenameFilter() { 628 public boolean accept(File dir, String name) { 629 return name.endsWith(".jar.new"); 630 }}); 631 632 for (File updatedPlugin : files) { 633 final String filePath = updatedPlugin.getPath(); 634 File plugin = new File(filePath.substring(0, filePath.length() - 4)); 635 String pluginName = updatedPlugin.getName().substring(0, updatedPlugin.getName().length() - 8); 636 if (plugin.exists()) { 637 if (!plugin.delete()) { 638 System.err.println(tr("Warning: failed to delete outdated plugin ''{0}''.", plugin.toString())); 639 System.err.println(tr("Warning: failed to install already downloaded plugin ''{0}''. Skipping installation. JOSM still going to load the old plugin version.", pluginName)); 640 continue; 641 } 642 } 643 if (!updatedPlugin.renameTo(plugin)) { 644 System.err.println(tr("Warning: failed to install plugin ''{0}'' from temporary download file ''{1}''. Renaming failed.", plugin.toString(), updatedPlugin.toString())); 645 System.err.println(tr("Warning: failed to install already downloaded plugin ''{0}''. Skipping installation. JOSM still going to load the old plugin version.", pluginName)); 646 } 647 } 648 return; 649 } 650 651 public static boolean checkException(Throwable e) 273 652 { 274 653 PluginProxy plugin = null; … … 350 729 return false; 351 730 } 352 public static String getBugReportText() 353 { 731 732 public static String getBugReportText() { 354 733 String text = ""; 355 734 String pl = Main.pref.getCollectionAsString("plugins"); 356 if(pl != null && pl.length() != 0) { 357 text += "Plugins: " +pl+"\n";735 if (pl != null && pl.length() != 0) { 736 text += "Plugins: " + pl + "\n"; 358 737 } 359 738 for (final PluginProxy pp : pluginList) { 360 text += "Plugin " + pp.info.name + (pp.info.version != null && !pp.info.version.equals("") ? " Version: "+pp.info.version+"\n" : "\n"); 739 text += "Plugin " 740 + pp.info.name 741 + (pp.info.version != null && !pp.info.version.equals("") ? " Version: " + pp.info.version + "\n" 742 : "\n"); 361 743 } 362 744 return text; 363 745 } 364 public static JPanel getInfoPanel() 365 { 746 747 public static JPanel getInfoPanel() { 366 748 JPanel pluginTab = new JPanel(new GridBagLayout()); 367 749 for (final PluginProxy p : pluginList) { 368 String name = p.info.name + (p.info.version != null && !p.info.version.equals("") ? " Version: "+p.info.version : ""); 750 String name = p.info.name 751 + (p.info.version != null && !p.info.version.equals("") ? " Version: " + p.info.version : ""); 369 752 pluginTab.add(new JLabel(name), GBC.std()); 370 753 pluginTab.add(Box.createHorizontalGlue(), GBC.std().fill(GBC.HORIZONTAL)); 371 pluginTab.add(new JButton(new AbstractAction(tr("Information")){ 754 pluginTab.add(new JButton(new AbstractAction(tr("Information")) { 372 755 public void actionPerformed(ActionEvent event) { 373 756 StringBuilder b = new StringBuilder(); 374 for (Entry<String,String> e : p.info.attr.entrySet()) { 757 for (Entry<String, String> e : p.info.attr.entrySet()) { 375 758 b.append(e.getKey()); 376 759 b.append(": "); … … 378 761 b.append("\n"); 379 762 } 380 JTextArea a = new JTextArea(10,40); 763 JTextArea a = new JTextArea(10, 40); 381 764 a.setEditable(false); 382 765 a.setText(b.toString()); 383 JOptionPane.showMessageDialog( 384 Main.parent, 385 new JScrollPane(a), 386 tr("Plugin information"), 387 JOptionPane.INFORMATION_MESSAGE 388 ); 766 JOptionPane.showMessageDialog(Main.parent, new JScrollPane(a), tr("Plugin information"), 767 JOptionPane.INFORMATION_MESSAGE); 389 768 } 390 769 }), GBC.eol()); 391 770 392 JTextArea description = new JTextArea((p.info.description==null? tr("no description available"):p.info.description)); 771 JTextArea description = new JTextArea((p.info.description == null ? tr("no description available") 772 : p.info.description)); 393 773 description.setEditable(false); 394 774 description.setFont(new JLabel().getFont().deriveFont(Font.ITALIC)); 395 775 description.setLineWrap(true); 396 776 description.setWrapStyleWord(true); 397 description.setBorder(BorderFactory.createEmptyBorder(0, 20,0,0));777 description.setBorder(BorderFactory.createEmptyBorder(0, 20, 0, 0)); 398 778 description.setBackground(UIManager.getColor("Panel.background")); 399 779 -
trunk/src/org/openstreetmap/josm/plugins/PluginInformation.java
r2620 r2817 43 43 public int stage = 50; 44 44 public String version = null; 45 public String localversion = null; 45 46 public String downloadlink = null; 46 47 public List<URL> libraries = new LinkedList<URL>(); … … 60 61 * @param file the plugin jar file. 61 62 */ 62 public PluginInformation(File file) { 63 public PluginInformation(File file) throws PluginException{ 63 64 this(file, file.getName().substring(0, file.getName().length()-4)); 64 65 } 65 66 66 public PluginInformation(File file, String name) { 67 public PluginInformation(File file, String name) throws PluginException{ 67 68 this.name = name; 68 69 this.file = file; 70 JarInputStream jar = null; 69 71 try { 70 JarInputStreamjar = new JarInputStream(new FileInputStream(file));72 jar = new JarInputStream(new FileInputStream(file)); 71 73 Manifest manifest = jar.getManifest(); 72 74 if (manifest == null) 73 throw new IOException(file+" contains no manifest.");75 throw new PluginException(name, tr("The plugin file ''{0}'' doesn't include a Manifest.", file.toString())); 74 76 scanManifest(manifest, false); 75 77 libraries.add(0, fileToURL(file)); 76 jar.close();77 78 } catch (IOException e) { 78 throw new PluginException(null, name, e); 79 } 80 } 81 82 public PluginInformation(InputStream manifestStream, String name, String url) { 79 throw new PluginException(name, e); 80 } finally { 81 if (jar != null) { 82 try { 83 jar.close(); 84 } catch(IOException e) { /* ignore */ } 85 } 86 } 87 } 88 89 public PluginInformation(InputStream manifestStream, String name, String url) throws PluginException { 83 90 this.name = name; 84 91 try { … … 90 97 scanManifest(manifest, url != null); 91 98 } catch (IOException e) { 92 throw new PluginException(n ull, name, e);99 throw new PluginException(name, e); 93 100 } 94 101 } … … 167 174 } 168 175 169 public String getLinkDescription() 170 { 171 String d = description == null ? tr("no description available") : description; 172 if(link != null) { 173 d += " <A HREF=\""+link+"\">"+tr("More details")+"</A>"; 174 } 175 return d; 176 /** 177 * Replies the description as HTML document, including a link to a web page with 178 * more information, provided such a link is available. 179 * 180 * @return the description as HTML document 181 */ 182 public String getDescriptionAsHtml() { 183 StringBuilder sb = new StringBuilder(); 184 sb.append("<html><body>"); 185 sb.append(description == null ? tr("no description available") : description); 186 if (link != null) { 187 sb.append(" <a href=\"").append(link).append("\">").append(tr("More info...")).append("</a>"); 188 } 189 sb.append("</body></html>"); 190 return sb.toString(); 176 191 } 177 192 … … 179 194 * Load and instantiate the plugin 180 195 */ 181 public PluginProxy load(Class<?> klass) { 196 public PluginProxy load(Class<?> klass) throws PluginException{ 182 197 try { 183 198 currentPluginInitialization = this; 184 199 return new PluginProxy(klass.newInstance(), this); 185 } catch (Exception e) { 186 throw new PluginException(null, name, e); 200 } catch(IllegalAccessException e) { 201 throw new PluginException(name, e); 202 } catch (InstantiationException e) { 203 throw new PluginException(name, e); 187 204 } 188 205 } … … 191 208 * Load the class of the plugin 192 209 */ 193 public Class<?> loadClass(ClassLoader classLoader) { 210 public Class<?> loadClass(ClassLoader classLoader) throws PluginException { 194 211 if (className == null) 195 212 return null; 196 try 213 try{ 197 214 Class<?> realClass = Class.forName(className, true, classLoader); 198 215 return realClass; 199 } catch (Exception e) { 200 throw new PluginException(n ull, name, e);216 } catch (ClassNotFoundException e) { 217 throw new PluginException(name, e); 201 218 } 202 219 } … … 272 289 return all; 273 290 } 291 292 /** 293 * Replies true if the plugin with the given information is most likely outdated with 294 * respect to the referenceVersion. 295 * 296 * @param referenceVersion the reference version. Can be null if we don't know a 297 * reference version 298 * 299 * @return true, if the plugin needs to be updated; false, otherweise 300 */ 301 public boolean isUpdateRequired(String referenceVersion) { 302 if (this.version == null && referenceVersion!= null) 303 return true; 304 if (this.version != null && !this.version.equals(referenceVersion)) 305 return true; 306 return false; 307 } 308 309 /** 310 * Replies true if this this plugin should be updated/downloaded because either 311 * it is not available locally (its local version is null) or its local version is 312 * older than the available version on the server. 313 * 314 * @return true if the plugin should be updated 315 */ 316 public boolean isUpdateRequired() { 317 if (this.localversion == null) return false; 318 return isUpdateRequired(this.localversion); 319 } 320 321 protected boolean matches(String filter, String value) { 322 if (filter == null) return true; 323 if (value == null) return false; 324 return value.toLowerCase().contains(filter.toLowerCase()); 325 } 326 327 /** 328 * Replies true if either the name, the description, or the version match (case insensitive) 329 * one of the words in filter. Replies true if filter is null. 330 * 331 * @param filter the filter expression 332 * @return true if this plugin info matches with the filter 333 */ 334 public boolean matches(String filter) { 335 if (filter == null) return true; 336 String words[] = filter.split("\\s+"); 337 for (String word: words) { 338 if (matches(word, name) 339 || matches(word, description) 340 || matches(word, version) 341 || matches(word, localversion)) 342 return true; 343 } 344 return false; 345 } 346 347 /** 348 * Replies the name of the plugin 349 */ 350 public String getName() { 351 return name; 352 } 353 354 /** 355 * Sets the name 356 * @param name 357 */ 358 public void setName(String name) { 359 this.name = name; 360 } 361 274 362 }
Note:
See TracChangeset
for help on using the changeset viewer.