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

Last change on this file since 1748 was 1748, checked in by stoecker, 15 years ago

applied relation sort - fix #27789 - patch by cjw

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