source: josm/trunk/src/org/openstreetmap/josm/plugins/PluginHandler.java@ 2017

Last change on this file since 2017 was 2017, checked in by Gubaer, 15 years ago

removed OptionPaneUtil
cleanup of deprecated Layer API
cleanup of deprecated APIs in OsmPrimitive and Way
cleanup of imports

File size: 15.2 KB
Line 
1//License: GPL. Copyright 2007 by Immanuel Scholz and others
2package org.openstreetmap.josm.plugins;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.Font;
7import java.awt.GridBagLayout;
8import java.awt.event.ActionEvent;
9import java.net.URL;
10import java.net.URLClassLoader;
11import java.util.ArrayList;
12import java.util.Arrays;
13import java.util.Collection;
14import java.util.Collections;
15import java.util.LinkedList;
16import java.util.List;
17import java.util.SortedMap;
18import java.util.TreeMap;
19import java.util.Map.Entry;
20
21import javax.swing.AbstractAction;
22import javax.swing.BorderFactory;
23import javax.swing.Box;
24import javax.swing.JButton;
25import javax.swing.JLabel;
26import javax.swing.JOptionPane;
27import javax.swing.JPanel;
28import javax.swing.JScrollPane;
29import javax.swing.JTextArea;
30import javax.swing.UIManager;
31
32import org.openstreetmap.josm.Main;
33import org.openstreetmap.josm.actions.AboutAction;
34import org.openstreetmap.josm.gui.ExtendedDialog;
35import org.openstreetmap.josm.gui.MapFrame;
36import org.openstreetmap.josm.gui.download.DownloadSelection;
37import org.openstreetmap.josm.gui.preferences.PreferenceSettingFactory;
38import org.openstreetmap.josm.tools.GBC;
39import org.openstreetmap.josm.tools.ImageProvider;
40
41public class PluginHandler {
42 /**
43 * All installed and loaded plugins (resp. their main classes)
44 */
45 public final static Collection<PluginProxy> pluginList = new LinkedList<PluginProxy>();
46 /**
47 * Load all plugins specified in preferences. If the parameter is
48 * <code>true</code>, all early plugins are loaded (before constructor).
49 */
50 public static void loadPlugins(boolean early) {
51 List<String> plugins = new LinkedList<String>();
52 Collection<String> cp = Main.pref.getCollection("plugins", null);
53 if (cp != null) {
54 plugins.addAll(cp);
55 }
56 if (System.getProperty("josm.plugins") != null) {
57 plugins.addAll(Arrays.asList(System.getProperty("josm.plugins").split(",")));
58 }
59
60 String [] oldplugins = new String[] {"mappaint", "unglueplugin",
61 "lang-de", "lang-en_GB", "lang-fr", "lang-it", "lang-pl", "lang-ro",
62 "lang-ru", "ewmsplugin", "ywms", "tways-0.2", "geotagged", "landsat",
63 "namefinder", "waypoints", "slippy_map_chooser", "tcx-support"};
64 for (String p : oldplugins) {
65 if (plugins.contains(p)) {
66 plugins.remove(p);
67 Main.pref.removeFromCollection("plugins", p);
68 JOptionPane.showMessageDialog(
69 Main.parent,
70 tr("Loading of {0} plugin was requested. This plugin is no longer required.", p),
71 tr("Warning"),
72 JOptionPane.WARNING_MESSAGE
73 );
74 }
75 }
76
77 if (plugins.isEmpty())
78 return;
79
80 SortedMap<Integer, Collection<PluginInformation>> p = new TreeMap<Integer, Collection<PluginInformation>>();
81 for (String pluginName : plugins) {
82 PluginInformation info = PluginInformation.findPlugin(pluginName);
83 if (info != null) {
84 if (info.early != early) {
85 continue;
86 }
87 if (info.mainversion > AboutAction.getVersionNumber()) {
88 JOptionPane.showMessageDialog(
89 Main.parent,
90 tr("Plugin {0} requires JOSM update to version {1}.", pluginName,
91 info.mainversion),
92 tr("Warning"),
93 JOptionPane.WARNING_MESSAGE
94 );
95 continue;
96 }
97 if(info.requires != null)
98 {
99 String warn = null;
100 for(String n : info.requires.split(";"))
101 {
102 if(!plugins.contains(n))
103 { warn = n; break; }
104 }
105 if(warn != null)
106 {
107 JOptionPane.showMessageDialog(Main.parent,
108 tr("Plugin {0} is required by plugin {1} but was not found.",
109 warn, pluginName),
110 tr("Error"),
111 JOptionPane.ERROR_MESSAGE
112 );
113 continue;
114 }
115 }
116 if (!p.containsKey(info.stage)) {
117 p.put(info.stage, new LinkedList<PluginInformation>());
118 }
119 p.get(info.stage).add(info);
120 } else if(early) {
121 JOptionPane.showMessageDialog(
122 Main.parent,
123 tr("Plugin not found: {0}.", pluginName),
124 tr("Error"),
125 JOptionPane.ERROR_MESSAGE
126 );
127 }
128 }
129
130 if (!early) {
131 long tim = System.currentTimeMillis();
132 long last = Main.pref.getLong("pluginmanager.lastupdate", 0);
133 Integer maxTime = Main.pref.getInteger("pluginmanager.warntime", 30);
134 long d = (tim - last)/(24*60*60*1000l);
135 if ((last <= 0) || (maxTime <= 0)) {
136 Main.pref.put("pluginmanager.lastupdate",Long.toString(tim));
137 } else if (d > maxTime) {
138 JOptionPane.showMessageDialog(Main.parent,
139 "<html>" +
140 tr("Last plugin update more than {0} days ago.", d) +
141 "<br><em>" +
142 tr("(You can change the number of days after which this warning appears<br>by setting the config option 'pluginmanager.warntime'.)") +
143 "</html>",
144 tr("Warning"),
145 JOptionPane.WARNING_MESSAGE
146 );
147 }
148 }
149
150 // iterate all plugins and collect all libraries of all plugins:
151 List<URL> allPluginLibraries = new ArrayList<URL>();
152 for (Collection<PluginInformation> c : p.values()) {
153 for (PluginInformation info : c) {
154 allPluginLibraries.addAll(info.libraries);
155 }
156 }
157 // create a classloader for all plugins:
158 URL[] jarUrls = new URL[allPluginLibraries.size()];
159 jarUrls = allPluginLibraries.toArray(jarUrls);
160 URLClassLoader pluginClassLoader = new URLClassLoader(jarUrls, Main.class.getClassLoader());
161 ImageProvider.sources.add(0, pluginClassLoader);
162
163 for (Collection<PluginInformation> c : p.values()) {
164 for (PluginInformation info : c) {
165 try {
166 Class<?> klass = info.loadClass(pluginClassLoader);
167 if (klass != null) {
168 System.out.println("loading "+info.name);
169 pluginList.add(info.load(klass));
170 }
171 } catch (Throwable e) {
172 e.printStackTrace();
173
174 int result = new ExtendedDialog(Main.parent,
175 tr("Disable plugin"),
176 tr("Could not load plugin {0}. Delete from preferences?", info.name),
177 new String[] {tr("Disable plugin"), tr("Keep plugin")},
178 new String[] {"dialogs/delete.png", "cancel.png"}).getValue();
179
180 if(result == 1)
181 {
182 plugins.remove(info.name);
183 Main.pref.removeFromCollection("plugins", info.name);
184 }
185 }
186 }
187 }
188 }
189 public static void setMapFrame(MapFrame old, MapFrame map) {
190 for (PluginProxy plugin : pluginList) {
191 plugin.mapFrameInitialized(old, map);
192 }
193 }
194
195 public static Object getPlugin(String name) {
196 for (PluginProxy plugin : pluginList)
197 if(plugin.info.name.equals(name))
198 return plugin.plugin;
199 return null;
200 }
201
202 public static void addDownloadSelection(List<DownloadSelection> downloadSelections)
203 {
204 for (PluginProxy p : pluginList) {
205 p.addDownloadSelection(downloadSelections);
206 }
207 }
208 public static void getPreferenceSetting(Collection<PreferenceSettingFactory> settings)
209 {
210 for (PluginProxy plugin : pluginList) {
211 settings.add(new PluginPreferenceFactory(plugin));
212 }
213 }
214
215 public static void earlyCleanup()
216 {
217 if (!PluginDownloader.moveUpdatedPlugins()) {
218 JOptionPane.showMessageDialog(
219 Main.parent,
220 tr("Activating the updated plugins failed. Check if JOSM has the permission to overwrite the existing ones."),
221 tr("Plugins"), JOptionPane.ERROR_MESSAGE);
222 }
223 }
224 public static Boolean checkException(Throwable e)
225 {
226 PluginProxy plugin = null;
227
228 // Check for an explicit problem when calling a plugin function
229 if (e instanceof PluginException) {
230 plugin = ((PluginException)e).plugin;
231 }
232
233 if (plugin == null)
234 {
235 String name = null;
236 /**
237 * Analyze the stack of the argument and find a name of a plugin, if
238 * some known problem pattern has been found.
239 *
240 * Note: This heuristic is not meant as discrimination against specific
241 * plugins, but only to stop the flood of similar bug reports about plugins.
242 * Of course, plugin writers are free to install their own version of
243 * an exception handler with their email address listed to receive
244 * bug reports ;-).
245 */
246 for (StackTraceElement element : e.getStackTrace()) {
247 String c = element.getClassName();
248
249 if (c.contains("wmsplugin.") || c.contains(".WMSLayer")) {
250 name = "wmsplugin";
251 }
252 if (c.contains("livegps.")) {
253 name = "livegps";
254 }
255 if (c.startsWith("UtilsPlugin.")) {
256 name = "UtilsPlugin";
257 }
258
259 if (c.startsWith("org.openstreetmap.josm.plugins.")) {
260 String p = c.substring("org.openstreetmap.josm.plugins.".length());
261 if (p.indexOf('.') != -1 && p.matches("[a-z].*")) {
262 name = p.substring(0,p.indexOf('.'));
263 }
264 }
265 if(name != null) {
266 break;
267 }
268 }
269 for (PluginProxy p : pluginList)
270 {
271 if (p.info.name.equals(name))
272 {
273 plugin = p;
274 break;
275 }
276 }
277 }
278
279 if (plugin != null) {
280 int answer = new ExtendedDialog(Main.parent,
281 tr("Disable plugin"),
282 tr("An unexpected exception occurred that may have come from the ''{0}'' plugin.", plugin.info.name)
283 + "\n"
284 + (plugin.info.author != null
285 ? tr("According to the information within the plugin, the author is {0}.", plugin.info.author)
286 : "")
287 + "\n"
288 + tr("Try updating to the newest version of this plugin before reporting a bug.")
289 + "\n"
290 + tr("Should the plugin be disabled?"),
291 new String[] {tr("Disable plugin"), tr("Cancel")},
292 new String[] {"dialogs/delete.png", "cancel.png"}).getValue();
293 if (answer == 1) {
294 List<String> plugins = new ArrayList<String>(Main.pref.getCollection("plugins", Collections.<String>emptyList()));
295 if (plugins.contains(plugin.info.name)) {
296 while (plugins.remove(plugin.info.name)) {}
297 Main.pref.putCollection("plugins", plugins);
298 JOptionPane.showMessageDialog(Main.parent,
299 tr("The plugin has been removed from the configuration. Please restart JOSM to unload the plugin."),
300 tr("Information"),
301 JOptionPane.INFORMATION_MESSAGE);
302 } else {
303 JOptionPane.showMessageDialog(
304 Main.parent,
305 tr("The plugin could not be removed. Probably it was already disabled"),
306 tr("Error"),
307 JOptionPane.ERROR_MESSAGE
308 );
309 }
310 return true;
311 }
312 }
313 return false;
314 }
315 public static String getBugReportText()
316 {
317 String text = "";
318 String pl = Main.pref.get("plugins");
319 if(pl != null && pl.length() != 0) {
320 text += "Plugins: "+pl+"\n";
321 }
322 for (final PluginProxy pp : pluginList) {
323 text += "Plugin " + pp.info.name + (pp.info.version != null && !pp.info.version.equals("") ? " Version: "+pp.info.version+"\n" : "\n");
324 }
325 return text;
326 }
327 public static JPanel getInfoPanel()
328 {
329 JPanel pluginTab = new JPanel(new GridBagLayout());
330 for (final PluginProxy p : pluginList) {
331 String name = p.info.name + (p.info.version != null && !p.info.version.equals("") ? " Version: "+p.info.version : "");
332 pluginTab.add(new JLabel(name), GBC.std());
333 pluginTab.add(Box.createHorizontalGlue(), GBC.std().fill(GBC.HORIZONTAL));
334 pluginTab.add(new JButton(new AbstractAction(tr("Information")){
335 public void actionPerformed(ActionEvent event) {
336 StringBuilder b = new StringBuilder();
337 for (Entry<String,String> e : p.info.attr.entrySet()) {
338 b.append(e.getKey());
339 b.append(": ");
340 b.append(e.getValue());
341 b.append("\n");
342 }
343 JTextArea a = new JTextArea(10,40);
344 a.setEditable(false);
345 a.setText(b.toString());
346 JOptionPane.showMessageDialog(
347 Main.parent,
348 new JScrollPane(a),
349 tr("Plugin information"),
350 JOptionPane.INFORMATION_MESSAGE
351 );
352 }
353 }), GBC.eol());
354
355 JTextArea description = new JTextArea((p.info.description==null? tr("no description available"):p.info.description));
356 description.setEditable(false);
357 description.setFont(new JLabel().getFont().deriveFont(Font.ITALIC));
358 description.setLineWrap(true);
359 description.setWrapStyleWord(true);
360 description.setBorder(BorderFactory.createEmptyBorder(0,20,0,0));
361 description.setBackground(UIManager.getColor("Panel.background"));
362
363 pluginTab.add(description, GBC.eop().fill(GBC.HORIZONTAL));
364 }
365 return pluginTab;
366 }
367}
Note: See TracBrowser for help on using the repository browser.