source: josm/trunk/src/org/openstreetmap/josm/plugins/PluginSelection.java@ 2484

Last change on this file since 2484 was 2372, checked in by stoecker, 14 years ago

fix #3391 - update plugins after josm update

File size: 17.8 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;
5import static org.openstreetmap.josm.tools.I18n.trn;
6
7import java.awt.GridBagConstraints;
8import java.awt.Insets;
9import java.awt.event.ActionEvent;
10import java.awt.event.ActionListener;
11import java.io.BufferedReader;
12import java.io.ByteArrayInputStream;
13import java.io.File;
14import java.io.FileInputStream;
15import java.io.InputStreamReader;
16import java.util.Arrays;
17import java.util.Collection;
18import java.util.Collections;
19import java.util.Comparator;
20import java.util.HashMap;
21import java.util.HashSet;
22import java.util.LinkedList;
23import java.util.Map;
24import java.util.Set;
25import java.util.TreeMap;
26import java.util.Map.Entry;
27
28import javax.swing.BorderFactory;
29import javax.swing.JCheckBox;
30import javax.swing.JEditorPane;
31import javax.swing.JOptionPane;
32import javax.swing.JPanel;
33import javax.swing.JTextField;
34import javax.swing.UIManager;
35import javax.swing.event.HyperlinkEvent;
36import javax.swing.event.HyperlinkListener;
37import javax.swing.event.HyperlinkEvent.EventType;
38
39import org.openstreetmap.josm.Main;
40import org.openstreetmap.josm.data.Version;
41import org.openstreetmap.josm.gui.ExtendedDialog;
42import org.openstreetmap.josm.tools.OpenBrowser;
43
44public class PluginSelection {
45
46 private Map<String, Boolean> pluginMap;
47 private Map<String, PluginInformation> availablePlugins;
48 private Map<String, PluginInformation> localPlugins;
49
50 private JTextField txtFilter = null;
51
52 /* Get a copy of PluginPreference's txtField so we can use it for searching */
53 public void passTxtFilter(JTextField filter) {
54 txtFilter = filter;
55 }
56
57 public void updateDescription(JPanel pluginPanel) {
58 int count = PluginDownloader.downloadDescription();
59 if (count > 0) {
60 JOptionPane.showMessageDialog(Main.parent,
61 trn("Downloaded plugin information from {0} site",
62 "Downloaded plugin information from {0} sites", count, count),
63 tr("Information"),
64 JOptionPane.INFORMATION_MESSAGE
65 );
66 } else {
67 JOptionPane.showMessageDialog(
68 Main.parent,
69 tr("No plugin information found."),
70 tr("Error"),
71 JOptionPane.ERROR_MESSAGE
72 );
73 }
74 loadPlugins();
75 drawPanel(pluginPanel);
76 }
77
78 public void update() {
79 update(null);
80 }
81
82 public void update(JPanel pluginPanel) {
83 // refresh description
84 int num = PluginDownloader.downloadDescription();
85 Boolean done = false;
86 loadPlugins();
87 if(pluginPanel != null)
88 drawPanel(pluginPanel);
89
90 Set<PluginInformation> toUpdate = new HashSet<PluginInformation>();
91 StringBuilder toUpdateStr = new StringBuilder();
92 for (String pluginName : Main.pref.getCollection("plugins", Collections.<String>emptySet())) {
93 PluginInformation local = localPlugins.get(pluginName);
94 PluginInformation description = availablePlugins.get(pluginName);
95
96 if (description == null) {
97 System.out.println(tr("Plug-in named {0} is not available. Update skipped.", pluginName));
98 continue;
99 }
100
101 if (local == null || (description.version != null && !description.version.equals(local.version))) {
102 toUpdate.add(description);
103 toUpdateStr.append(pluginName+"\n");
104 }
105 }
106 if (toUpdate.isEmpty()) {
107 JOptionPane.showMessageDialog(
108 Main.parent,
109 tr("All installed plugins are up to date."),
110 tr("Information"),
111 JOptionPane.INFORMATION_MESSAGE
112 );
113 done = true;
114 } else {
115 ExtendedDialog ed = new ExtendedDialog(Main.parent,
116 tr("Update"),
117 new String[] {tr("Update Plugins"), tr("Cancel")});
118 ed.setButtonIcons(new String[] {"dialogs/refresh.png", "cancel.png"});
119 ed.setContent(tr("Update the following plugins:\n\n{0}", toUpdateStr.toString()));
120 ed.showDialog();
121
122 if (ed.getValue() == 1) {
123 PluginDownloader.update(toUpdate, pluginPanel != null);
124 done = true;
125 }
126 }
127 if (done && num >= 1) {
128 Main.pref.put("pluginmanager.lastupdate", Long.toString(System.currentTimeMillis()));
129 Main.pref.putInteger("pluginmanager.version", Version.getInstance().getVersion());
130 }
131 loadPlugins();
132 if(pluginPanel != null)
133 drawPanel(pluginPanel);
134 }
135
136 public boolean finish() {
137 Collection<PluginInformation> toDownload = new LinkedList<PluginInformation>();
138 Collection<String> installedPlugins = Main.pref.getCollection("plugins", Collections.<String>emptySet());
139
140 String msg = "";
141 for (Entry<String, Boolean> entry : pluginMap.entrySet()) {
142 if(entry.getValue() && !installedPlugins.contains(entry.getKey()))
143 {
144 String name = entry.getKey();
145 PluginInformation ap = availablePlugins.get(name);
146 PluginInformation pi = localPlugins.get(name);
147 if(pi == null || (pi.version == null && ap.version != null)
148 || (pi.version != null && !pi.version.equals(ap.version)))
149 {
150 toDownload.add(ap);
151 msg += name + "\n";
152 }
153 }
154 }
155 if (!toDownload.isEmpty()) {
156 ExtendedDialog ed = new ExtendedDialog(Main.parent,
157 tr("Download missing plugins"),
158 new String[] {tr("Download Plugins"), tr("Cancel")});
159 ed.setButtonIcons(new String[] {"download.png", "cancel.png"});
160 ed.setContent(tr("Download the following plugins?\n\n{0}", msg));
161 ed.showDialog();
162
163 Collection<PluginInformation> error =
164 (ed.getValue() != 1 ? toDownload : new PluginDownloader().download(toDownload));
165 for (PluginInformation pd : error) {
166 pluginMap.put(pd.name, false);
167 }
168
169 }
170 LinkedList<String> plugins = new LinkedList<String>();
171 for (Map.Entry<String, Boolean> d : pluginMap.entrySet()) {
172 if (d.getValue()) {
173 plugins.add(d.getKey());
174 }
175 }
176
177 Collections.sort(plugins);
178 return Main.pref.putCollection("plugins", plugins);
179 }
180
181 /* return true when plugin list changed */
182 public void drawPanel(JPanel pluginPanel) {
183 Collection<String> enabledPlugins = Main.pref.getCollection("plugins", null);
184
185 if (pluginMap == null) {
186 pluginMap = new HashMap<String, Boolean>();
187 } else {
188 // Keep the map in bounds; possibly slightly pointless.
189 Set<String> pluginsToRemove = new HashSet<String>();
190 for (final String pname : pluginMap.keySet()) {
191 if (availablePlugins.get(pname) == null) {
192 pluginsToRemove.add(pname);
193 }
194 }
195
196 for (String pname : pluginsToRemove) {
197 pluginMap.remove(pname);
198 }
199 }
200
201 pluginPanel.removeAll();
202
203 GridBagConstraints gbc = new GridBagConstraints();
204 gbc.gridx = 0;
205 gbc.anchor = GridBagConstraints.NORTHWEST;
206
207 int row = 0;
208 for (final PluginInformation plugin : availablePlugins.values()) {
209 boolean enabled = (enabledPlugins != null) && enabledPlugins.contains(plugin.name);
210 if (pluginMap.get(plugin.name) == null) {
211 pluginMap.put(plugin.name, enabled);
212 }
213
214 String remoteversion = plugin.version;
215 if ((remoteversion == null) || remoteversion.equals("")) {
216 remoteversion = tr("unknown");
217 } else if(plugin.oldmode) {
218 remoteversion += "*";
219 }
220
221 String localversion = "";
222 PluginInformation p = localPlugins.get(plugin.name);
223 if(p != null)
224 {
225 if (p.version != null && !p.version.equals("")) {
226 localversion = p.version;
227 } else {
228 localversion = tr("unknown");
229 }
230 localversion = " (" + localversion + ")";
231 }
232
233 /* If this plugin doesn't match our search parameters we don't want to display it */
234 if (txtFilter.getText() != null) {
235 boolean matches = filterNameAndDescription(txtFilter.getText(),plugin.name,
236 plugin.getLinkDescription(),
237 remoteversion, localversion);
238 if (!matches) {
239 /* This is not the plugin you're looking for */
240 continue;
241 }
242 }
243
244 final JCheckBox pluginCheck = new JCheckBox(
245 tr("{0}: Version {1}{2}", plugin.name, remoteversion, localversion),
246 pluginMap.get(plugin.name));
247 gbc.gridy = row++;
248 gbc.insets = new Insets(5,5,0,5);
249 gbc.weighty = 0.1;
250 gbc.fill = GridBagConstraints.NONE;
251 pluginPanel.add(pluginCheck, gbc);
252
253 pluginCheck.setToolTipText(plugin.downloadlink != null ? ""+plugin.downloadlink : tr("Plugin bundled with JOSM"));
254
255 JEditorPane description = new JEditorPane();
256 description.setContentType("text/html");
257 description.setEditable(false);
258 description.setText("<html><body bgcolor=\"#" + Integer.toHexString( UIManager.getColor("Panel.background").getRGB() & 0x00ffffff ) +"\"><i>"+plugin.getLinkDescription()+"</i></body></html>");
259 description.setBorder(BorderFactory.createEmptyBorder());
260 description.setBackground(UIManager.getColor("Panel.background"));
261 description.addHyperlinkListener(new HyperlinkListener() {
262 public void hyperlinkUpdate(HyperlinkEvent e) {
263 if(e.getEventType() == EventType.ACTIVATED) {
264 OpenBrowser.displayUrl(e.getURL().toString());
265 }
266 }
267 });
268
269 gbc.gridy = row++;
270 gbc.insets = new Insets(3,25,5,5);
271 gbc.weighty = 0.9;
272 gbc.weightx = 1.0;
273 gbc.anchor = GridBagConstraints.WEST;
274 gbc.fill = GridBagConstraints.HORIZONTAL;
275 pluginPanel.add(description, gbc);
276
277 pluginCheck.addActionListener(new ActionListener(){
278 public void actionPerformed(ActionEvent e) {
279 pluginMap.put(plugin.name, pluginCheck.isSelected());
280 }
281 });
282 }
283 pluginPanel.updateUI();
284 }
285
286 private static boolean filterNameAndDescription(String filter, final String name, final String description,
287 final String remoteversion, final String localversion) {
288 final String input[] = filter.split("\\s+");
289 /* We're doing case-insensitive matching */
290 final String name_lc = name.toLowerCase();
291 final String description_lc = description.toLowerCase();
292 final String remoteversion_lc = remoteversion.toLowerCase();
293 final String localversion_lc = localversion.toLowerCase();
294
295 boolean canHas = true;
296
297 /* Make 'foo bar' search for 'bar' or 'foo' in both name and description */
298 for (String bit : input) {
299 final String lc_bit = bit.toLowerCase();
300 if (!name_lc.contains(lc_bit) &&
301 !description_lc.contains(lc_bit) &&
302 !remoteversion_lc.contains(lc_bit) &&
303 !localversion_lc.contains(lc_bit)) {
304 canHas = false;
305 }
306 }
307
308 return canHas;
309 }
310
311 public void loadPlugins() {
312 availablePlugins = new TreeMap<String, PluginInformation>(new Comparator<String>(){
313 public int compare(String o1, String o2) {
314 return o1.compareToIgnoreCase(o2);
315 }
316 });
317 localPlugins = new TreeMap<String, PluginInformation>(new Comparator<String>(){
318 public int compare(String o1, String o2) {
319 return o1.compareToIgnoreCase(o2);
320 }
321 });
322 for (String location : PluginInformation.getPluginLocations()) {
323 File[] pluginFiles = new File(location).listFiles();
324 if (pluginFiles != null) {
325 Arrays.sort(pluginFiles);
326 for (File f : pluginFiles) {
327 if (!f.isFile()) {
328 continue;
329 }
330 String fname = f.getName();
331 if (fname.endsWith(".jar")) {
332 try {
333 PluginInformation info = new PluginInformation(f,fname.substring(0,fname.length()-4));
334 if (!availablePlugins.containsKey(info.name)) {
335 availablePlugins.put(info.name, info);
336 }
337 if (!localPlugins.containsKey(info.name)) {
338 localPlugins.put(info.name, info);
339 }
340 } catch (PluginException x) {
341 }
342 } else if (fname.endsWith(".jar.new")) {
343 try {
344 PluginInformation info = new PluginInformation(f,fname.substring(0,fname.length()-8));
345 availablePlugins.put(info.name, info);
346 localPlugins.put(info.name, info);
347 } catch (PluginException x) {
348 }
349 } else if (fname.matches("^[0-9]+-site.*\\.txt$")) {
350 int err = 0;
351 try {
352 BufferedReader r = new BufferedReader(new InputStreamReader(new FileInputStream(f), "utf-8"));
353 String name = null;
354 String url = null;
355 String manifest = null;
356 for (String line = r.readLine(); line != null; line = r.readLine())
357 {
358 if(line.startsWith("\t"))
359 {
360 line = line.substring(1);
361 if(line.length() > 70)
362 {
363 manifest += line.substring(0,70)+"\n";
364 line = " " + line.substring(70);
365 }
366 manifest += line+"\n";
367 }
368 else
369 {
370 if(name != null)
371 {
372 try
373 {
374 PluginInformation info = new PluginInformation(
375 new ByteArrayInputStream(manifest.getBytes("utf-8")),
376 name.substring(0,name.length()-4), url);
377 if(!availablePlugins.containsKey(info.name)) {
378 availablePlugins.put(info.name, info);
379 }
380 }
381 catch (Exception e)
382 {
383 e.printStackTrace();
384 ++err;
385 }
386 }
387 String x[] = line.split(";");
388 name = x[0];
389 url = x[1];
390 manifest = null;
391 }
392 }
393 if(name != null)
394 {
395 PluginInformation info = new PluginInformation(
396 new ByteArrayInputStream(manifest.getBytes("utf-8")),
397 name.substring(0,name.length()-4), url);
398 if(!availablePlugins.containsKey(info.name)) {
399 availablePlugins.put(info.name, info);
400 }
401 }
402 r.close();
403 } catch (Exception e) {
404 e.printStackTrace();
405 ++err;
406 }
407 if(err > 0)
408 {
409 JOptionPane.showMessageDialog(
410 Main.parent,
411 tr("Error reading plugin information file: {0}", f.getName()),
412 tr("Error"),
413 JOptionPane.ERROR_MESSAGE
414 );
415 }
416 }
417 }
418 }
419 }
420 for (PluginProxy proxy : PluginHandler.pluginList)
421 {
422 if (!availablePlugins.containsKey(proxy.info.name)) {
423 availablePlugins.put(proxy.info.name, proxy.info);
424 }
425 if (!localPlugins.containsKey(proxy.info.name)) {
426 localPlugins.put(proxy.info.name, proxy.info);
427 }
428 }
429 }
430}
Note: See TracBrowser for help on using the repository browser.