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

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

closed #2596 - wrong texts in plugin information

File size: 15.4 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;
11
12import java.io.BufferedReader;
13import java.io.ByteArrayInputStream;
14import java.io.File;
15import java.io.FileInputStream;
16import java.io.InputStreamReader;
17import java.io.IOException;
18import java.util.Arrays;
19import java.util.Collection;
20import java.util.Collections;
21import java.util.Comparator;
22import java.util.HashMap;
23import java.util.HashSet;
24import java.util.LinkedList;
25import java.util.Map;
26import java.util.Set;
27import java.util.SortedMap;
28import java.util.TreeMap;
29import java.util.Map.Entry;
30
31import javax.swing.BorderFactory;
32import javax.swing.JCheckBox;
33import javax.swing.JEditorPane;
34import javax.swing.JOptionPane;
35import javax.swing.JPanel;
36import javax.swing.UIManager;
37import javax.swing.event.HyperlinkEvent;
38import javax.swing.event.HyperlinkListener;
39import javax.swing.event.HyperlinkEvent.EventType;
40
41import org.openstreetmap.josm.Main;
42import org.openstreetmap.josm.gui.ExtendedDialog;
43import org.openstreetmap.josm.tools.OpenBrowser;
44
45public class PluginSelection {
46
47 private Map<String, Boolean> pluginMap;
48 private Map<String, PluginInformation> availablePlugins;
49
50 public void updateDescription(JPanel pluginPanel) {
51 int count = PluginDownloader.downloadDescription();
52 if (count > 0)
53 JOptionPane.showMessageDialog(Main.parent,
54 trn("Downloaded plugin information from {0} site",
55 "Downloaded plugin information from {0} sites", count, count));
56 else
57 JOptionPane.showMessageDialog(Main.parent, tr("No plugin information found."));
58 drawPanel(pluginPanel);
59 }
60
61 public void update(JPanel pluginPanel) {
62 // refresh description
63 int num = PluginDownloader.downloadDescription();
64 Boolean done = false;
65 drawPanel(pluginPanel);
66
67 Set<PluginInformation> toUpdate = new HashSet<PluginInformation>();
68 StringBuilder toUpdateStr = new StringBuilder();
69 for (PluginProxy proxy : PluginHandler.pluginList) {
70 PluginInformation description = availablePlugins.get(proxy.info.name);
71 if (description != null && (description.version == null || description.version.equals("")) ?
72 (proxy.info.version != null && proxy.info.version.equals("")) : !description.version.equals(proxy.info.version)) {
73 toUpdate.add(description);
74 toUpdateStr.append(description.name+"\n");
75 }
76 }
77 if (toUpdate.isEmpty()) {
78 JOptionPane.showMessageDialog(Main.parent, tr("All installed plugins are up to date."));
79 done = true;
80 } else {
81 int answer = new ExtendedDialog(Main.parent,
82 tr("Update"),
83 tr("Update the following plugins:\n\n{0}", toUpdateStr.toString()),
84 new String[] {tr("Update Plugins"), tr("Cancel")},
85 new String[] {"dialogs/refresh.png", "cancel.png"}).getValue();
86 if (answer == 1) {
87 PluginDownloader.update(toUpdate);
88 done = true;
89 }
90 }
91 if (done && num >= 1)
92 Main.pref.put("pluginmanager.lastupdate", Long.toString(System.currentTimeMillis()));
93 drawPanel(pluginPanel);
94 }
95
96 public Boolean finish() {
97 Collection<PluginInformation> toDownload = new LinkedList<PluginInformation>();
98 String msg = "";
99 for (Entry<String, Boolean> entry : pluginMap.entrySet()) {
100 if (entry.getValue() && PluginInformation.findPlugin(entry.getKey()) == null) {
101 toDownload.add(availablePlugins.get(entry.getKey()));
102 msg += entry.getKey() + "\n";
103 }
104 }
105 if (!toDownload.isEmpty()) {
106 int answer = new ExtendedDialog(Main.parent,
107 tr("Download missing plugins"),
108 tr("Download the following plugins?\n\n{0}", msg),
109 new String[] {tr("Download Plugins"), tr("Cancel")},
110 new String[] {"download.png", "cancel.png"}).getValue();
111 if (answer != 1)
112 for (PluginInformation pd : toDownload)
113 pluginMap.put(pd.name, false);
114 else
115 for (PluginInformation pd : toDownload)
116 if (!PluginDownloader.downloadPlugin(pd))
117 pluginMap.put(pd.name, false);
118
119 }
120 LinkedList<String> plugins = new LinkedList<String>();
121 for (Map.Entry<String, Boolean> d : pluginMap.entrySet()) {
122 if (d.getValue())
123 plugins.add(d.getKey());
124 }
125
126 Collections.sort(plugins);
127 return Main.pref.putCollection("plugins", plugins);
128 }
129
130 /* return true when plugin list changed */
131 public void drawPanel(JPanel pluginPanel) {
132 availablePlugins = getAvailablePlugins();
133 Collection<String> enabledPlugins = Main.pref.getCollection("plugins", null);
134
135 if (pluginMap == null)
136 pluginMap = new HashMap<String, Boolean>();
137 else {
138 // Keep the map in bounds; possibly slightly pointless.
139 Set<String> pluginsToRemove = new HashSet<String>();
140 for (final String pname : pluginMap.keySet()) {
141 if (availablePlugins.get(pname) == null) pluginsToRemove.add(pname);
142 }
143
144 for (String pname : pluginsToRemove) {
145 pluginMap.remove(pname);
146 }
147 }
148
149 pluginPanel.removeAll();
150
151 GridBagConstraints gbc = new GridBagConstraints();
152 gbc.gridx = 0;
153 gbc.anchor = GridBagConstraints.NORTHWEST;
154
155 int row = 0;
156 for (final PluginInformation plugin : availablePlugins.values()) {
157 boolean enabled = (enabledPlugins != null) && enabledPlugins.contains(plugin.name);
158 if (pluginMap.get(plugin.name) == null)
159 pluginMap.put(plugin.name, enabled);
160
161 String remoteversion = plugin.version;
162 if ((remoteversion == null) || remoteversion.equals(""))
163 remoteversion = tr("unknown");
164
165 String localversion;
166 PluginInformation p = PluginInformation.findPlugin(plugin.name);
167 if (p != null) {
168 if (p.version != null && !p.version.equals(""))
169 localversion = p.version;
170 else
171 localversion = tr("unknown");
172 localversion = " (" + localversion + ")";
173 } else
174 localversion = "";
175
176 final JCheckBox pluginCheck = new JCheckBox(
177 tr("{0}: Version {1}{2}", plugin.name, remoteversion, localversion),
178 pluginMap.get(plugin.name));
179 gbc.gridy = row++;
180 gbc.insets = new Insets(5,5,0,5);
181 gbc.weighty = 0.1;
182 gbc.fill = GridBagConstraints.NONE;
183 pluginPanel.add(pluginCheck, gbc);
184
185 pluginCheck.setToolTipText(plugin.downloadlink != null ? ""+plugin.downloadlink : tr("Plugin bundled with JOSM"));
186
187 JEditorPane description = new JEditorPane();
188 description.setContentType("text/html");
189 description.setEditable(false);
190 description.setText("<html><i>"+plugin.getLinkDescription()+"</i></html>");
191 description.setBorder(BorderFactory.createEmptyBorder(0,20,0,0));
192 description.setBackground(UIManager.getColor("Panel.background"));
193 description.addHyperlinkListener(new HyperlinkListener() {
194 public void hyperlinkUpdate(HyperlinkEvent e) {
195 if(e.getEventType() == EventType.ACTIVATED) {
196 OpenBrowser.displayUrl(e.getURL().toString());
197 }
198 }
199 });
200
201 gbc.gridy = row++;
202 gbc.insets = new Insets(3,5,5,5);
203 gbc.weighty = 0.9;
204 gbc.weightx = 1.0;
205 gbc.anchor = GridBagConstraints.WEST;
206 gbc.fill = GridBagConstraints.HORIZONTAL;
207 pluginPanel.add(description, gbc);
208
209 pluginCheck.addActionListener(new ActionListener(){
210 public void actionPerformed(ActionEvent e) {
211 // if user enabled a plugin, it is not loaded but found somewhere on disk: offer to delete jar
212 if (pluginCheck.isSelected()) {
213 PluginInformation plinfo = PluginInformation.findPlugin(plugin.name);
214 if ((getLoaded(plugin.name) == null) && (plinfo != null)) {
215 try {
216 int answer = new ExtendedDialog(Main.parent,
217 tr("Plugin already exists"),
218 tr("Plugin archive already available. Do you want to download"
219 + " the current version by deleting existing archive?\n\n{0}",
220 plinfo.file.getCanonicalPath()),
221 new String[] {tr("Delete and Download"), tr("Cancel")},
222 new String[] {"download.png", "cancel.png"}).getValue();
223
224 if (answer == 1) {
225 if (!plinfo.file.delete()) {
226 JOptionPane.showMessageDialog(Main.parent, tr("Error deleting plugin file: {0}", plinfo.file.getCanonicalPath()));
227 }
228 }
229 } catch (IOException e1) {
230 e1.printStackTrace();
231 JOptionPane.showMessageDialog(Main.parent, tr("Error deleting plugin file: {0}", e1.getMessage()));
232 }
233 }
234 }
235 pluginMap.put(plugin.name, pluginCheck.isSelected());
236 }
237 });
238 }
239 pluginPanel.updateUI();
240 }
241
242 /**
243 * Return information about a loaded plugin.
244 *
245 * Note that if you call this in your plugins bootstrap, you may get <code>null</code> if
246 * the plugin requested is not loaded yet.
247 *
248 * @return The PluginInformation to a specific plugin, but only if the plugin is loaded.
249 * If it is not loaded, <code>null</code> is returned.
250 */
251 private static PluginInformation getLoaded(String pluginName) {
252 for (PluginProxy p : PluginHandler.pluginList)
253 if (p.info.name.equals(pluginName))
254 return p.info;
255 return null;
256 }
257
258 private Map<String, PluginInformation> getAvailablePlugins() {
259 SortedMap<String, PluginInformation> availablePlugins = new TreeMap<String, PluginInformation>(new Comparator<String>(){
260 public int compare(String o1, String o2) {
261 return o1.compareToIgnoreCase(o2);
262 }
263 });
264 for (String location : PluginInformation.getPluginLocations()) {
265 File[] pluginFiles = new File(location).listFiles();
266 if (pluginFiles != null) {
267 Arrays.sort(pluginFiles);
268 for (File f : pluginFiles) {
269 if (!f.isFile())
270 continue;
271 String fname = f.getName();
272 if (fname.endsWith(".jar")) {
273 try {
274 PluginInformation info = new PluginInformation(f,fname.substring(0,fname.length()-4));
275 if (!availablePlugins.containsKey(info.name))
276 availablePlugins.put(info.name, info);
277 } catch (PluginException x) {
278 }
279 } else if (fname.matches("^[0-9]+-site.*\\.txt$")) {
280 int err = 0;
281 try {
282 BufferedReader r = new BufferedReader(new InputStreamReader(new FileInputStream(f), "utf-8"));
283 String name = null;
284 String url = null;
285 String manifest = null;
286 for (String line = r.readLine(); line != null; line = r.readLine())
287 {
288 if(line.startsWith("\t"))
289 {
290 line = line.substring(1);
291 if(line.length() > 70)
292 {
293 manifest += line.substring(0,70)+"\n";
294 line = " " + line.substring(70);
295 }
296 manifest += line+"\n";
297 }
298 else
299 {
300 if(name != null)
301 {
302 try
303 {
304 PluginInformation info = new PluginInformation(
305 new ByteArrayInputStream(manifest.getBytes("utf-8")),
306 name.substring(0,name.length()-4));
307 info.downloadlink = url;
308 if(!availablePlugins.containsKey(info.name))
309 availablePlugins.put(info.name, info);
310 }
311 catch (Exception e)
312 {
313 e.printStackTrace();
314 ++err;
315 }
316 }
317 String x[] = line.split(";");
318 name = x[0];
319 url = x[1];
320 manifest = null;
321 }
322 }
323 if(name != null)
324 {
325 PluginInformation info = new PluginInformation(
326 new ByteArrayInputStream(manifest.getBytes("utf-8")),
327 name.substring(0,name.length()-4));
328 info.downloadlink = url;
329 if(!availablePlugins.containsKey(info.name))
330 availablePlugins.put(info.name, info);
331 }
332 r.close();
333 } catch (Exception e) {
334 e.printStackTrace();
335 ++err;
336 }
337 if(err > 0)
338 {
339 JOptionPane.showMessageDialog(Main.parent, tr("Error reading plugin information file: {0}", f.getName()));
340 }
341 }
342 }
343 }
344 }
345 for (PluginProxy proxy : PluginHandler.pluginList)
346 if (!availablePlugins.containsKey(proxy.info.name))
347 availablePlugins.put(proxy.info.name, proxy.info);
348 return availablePlugins;
349 }
350}
Note: See TracBrowser for help on using the repository browser.