source: josm/trunk/src/org/openstreetmap/josm/plugins/ReadLocalPluginInformationTask.java @ 5241

Revision 4737, 9.7 KB checked in by stoecker, 5 months ago (diff)

fix #7197 - fix plugin version check on load

  • Property svn:eol-style set to native
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.plugins;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.io.File;
7import java.io.FileInputStream;
8import java.io.FilenameFilter;
9import java.io.IOException;
10import java.util.ArrayList;
11import java.util.Collection;
12import java.util.HashMap;
13import java.util.List;
14import java.util.Map;
15
16import org.openstreetmap.josm.gui.PleaseWaitRunnable;
17import org.openstreetmap.josm.gui.progress.ProgressMonitor;
18import org.openstreetmap.josm.io.OsmTransferException;
19import org.openstreetmap.josm.tools.ImageProvider;
20import org.openstreetmap.josm.tools.Utils;
21import org.xml.sax.SAXException;
22
23/**
24 * This is an asynchronous task for reading plugin information from the files
25 * in the local plugin repositories.
26 *
27 * It scans the files in the local plugins repository (see {@see Preferences#getPluginsDirectory()}
28 * and extracts plugin information from three kind of files:
29 * <ul>
30 *   <li>.jar-files, assuming that they represent plugin jars</li>
31 *   <li>.jar.new-files, assuming that these are downloaded but not yet installed plugins</li>
32 *   <li>cached lists of available plugins, downloaded for instance from
33 *   <a href="http://josm.openstreetmap.de/plugins">http://josm.openstreetmap.de/plugins</a></li>
34 * </ul>
35 *
36 */
37public class ReadLocalPluginInformationTask extends PleaseWaitRunnable {
38    private Map<String, PluginInformation> availablePlugins;
39    private boolean canceled;
40
41    public ReadLocalPluginInformationTask() {
42        super(tr("Reading local plugin information.."), false);
43        availablePlugins = new HashMap<String, PluginInformation>();
44    }
45
46    public ReadLocalPluginInformationTask(ProgressMonitor monitor) {
47        super(tr("Reading local plugin information.."),monitor, false);
48        availablePlugins = new HashMap<String, PluginInformation>();
49    }
50
51    @Override
52    protected void cancel() {
53        canceled = true;
54    }
55
56    @Override
57    protected void finish() {}
58
59    protected void processJarFile(File f, String pluginName) throws PluginException{
60        PluginInformation info = new PluginInformation(
61                f,
62                pluginName
63        );
64        if (!availablePlugins.containsKey(info.getName())) {
65            info.localversion = info.version;
66            info.localmainversion = info.mainversion;
67            availablePlugins.put(info.getName(), info);
68        } else {
69            PluginInformation current = availablePlugins.get(info.getName());
70            current.localversion = info.version;
71            current.localmainversion = info.mainversion;
72            if (info.icon != null) {
73                current.icon = info.icon;
74            }
75            current.early = info.early;
76            current.className = info.className;
77            current.libraries = info.libraries;
78            current.stage = info.stage;
79            current.requires = info.requires;
80        }
81    }
82
83    protected void scanSiteCacheFiles(ProgressMonitor monitor, File pluginsDirectory) {
84        File[] siteCacheFiles = pluginsDirectory.listFiles(
85                new FilenameFilter() {
86                    public boolean accept(File dir, String name) {
87                        return name.matches("^([0-9]+-)?site.*\\.txt$");
88                    }
89                }
90        );
91        if (siteCacheFiles == null || siteCacheFiles.length == 0)
92            return;
93        monitor.subTask(tr("Processing plugin site cache files..."));
94        monitor.setTicksCount(siteCacheFiles.length);
95        for (File f: siteCacheFiles) {
96            String fname = f.getName();
97            monitor.setCustomText(tr("Processing file ''{0}''", fname));
98            try {
99                processLocalPluginInformationFile(f);
100            } catch(PluginListParseException e) {
101                System.err.println(tr("Warning: Failed to scan file ''{0}'' for plugin information. Skipping.", fname));
102                e.printStackTrace();
103            }
104            monitor.worked(1);
105        }
106    }
107
108    protected void scanIconCacheFiles(ProgressMonitor monitor, File pluginsDirectory) {
109        File[] siteCacheFiles = pluginsDirectory.listFiles(
110                new FilenameFilter() {
111                    public boolean accept(File dir, String name) {
112                        return name.matches("^([0-9]+-)?site.*plugin-icons\\.zip$");
113                    }
114                }
115        );
116        if (siteCacheFiles == null || siteCacheFiles.length == 0)
117            return;
118        monitor.subTask(tr("Processing plugin site cache icon files..."));
119        monitor.setTicksCount(siteCacheFiles.length);
120        for (File f: siteCacheFiles) {
121            String fname = f.getName();
122            monitor.setCustomText(tr("Processing file ''{0}''", fname));
123            for (PluginInformation pi : availablePlugins.values()) {
124                if (pi.icon == null && pi.iconPath != null) {
125                    pi.icon = new ImageProvider(pi.name+".jar/"+pi.iconPath)
126                                    .setArchive(f)
127                                    .setMaxWidth(24)
128                                    .setMaxHeight(24)
129                                    .setOptional(true).get();
130                }
131            }
132            monitor.worked(1);
133        }
134    }
135
136    protected void scanPluginFiles(ProgressMonitor monitor, File pluginsDirectory) {
137        File[] pluginFiles = pluginsDirectory.listFiles(
138                new FilenameFilter() {
139                    public boolean accept(File dir, String name) {
140                        return name.endsWith(".jar") || name.endsWith(".jar.new");
141                    }
142                }
143        );
144        if (pluginFiles == null || pluginFiles.length == 0)
145            return;
146        monitor.subTask(tr("Processing plugin files..."));
147        monitor.setTicksCount(pluginFiles.length);
148        for (File f: pluginFiles) {
149            String fname = f.getName();
150            monitor.setCustomText(tr("Processing file ''{0}''", fname));
151            try {
152                if (fname.endsWith(".jar")) {
153                    String pluginName = fname.substring(0, fname.length() - 4);
154                    processJarFile(f, pluginName);
155                } else if (fname.endsWith(".jar.new")) {
156                    String pluginName = fname.substring(0, fname.length() - 8);
157                    processJarFile(f, pluginName);
158                }
159            } catch(PluginException e){
160                System.err.println(tr("Warning: Failed to scan file ''{0}'' for plugin information. Skipping.", fname));
161                e.printStackTrace();
162            }
163            monitor.worked(1);
164        }
165    }
166
167    protected void scanLocalPluginRepository(ProgressMonitor monitor, File pluginsDirectory) {
168        if (pluginsDirectory == null) return;
169        try {
170            monitor.beginTask("");
171            scanSiteCacheFiles(monitor, pluginsDirectory);
172            scanIconCacheFiles(monitor, pluginsDirectory);
173            scanPluginFiles(monitor, pluginsDirectory);
174        } finally {
175            monitor.setCustomText("");
176            monitor.finishTask();
177        }
178    }
179
180    protected void processLocalPluginInformationFile(File file) throws PluginListParseException{
181        FileInputStream fin = null;
182        try {
183            fin = new FileInputStream(file);
184            List<PluginInformation> pis = new PluginListParser().parse(fin);
185            for (PluginInformation pi : pis) {
186                // we always keep plugin information from a plugin site because it
187                // includes information not available in the plugin jars Manifest, i.e.
188                // the download link or localized descriptions
189                //
190                availablePlugins.put(pi.name, pi);
191            }
192        } catch(IOException e) {
193            throw new PluginListParseException(e);
194        } finally {
195            Utils.close(fin);
196        }
197    }
198
199    protected void analyseInProcessPlugins() {
200        for (PluginProxy proxy : PluginHandler.pluginList) {
201            PluginInformation info = proxy.getPluginInformation();
202            if (canceled)return;
203            if (!availablePlugins.containsKey(info.name)) {
204                availablePlugins.put(info.name, info);
205            } else {
206                availablePlugins.get(info.name).localversion = info.localversion;
207            }
208        }
209    }
210
211    protected void filterOldPlugins() {
212        for (PluginHandler.DeprecatedPlugin p : PluginHandler.DEPRECATED_PLUGINS) {
213            if (canceled)return;
214            if (availablePlugins.containsKey(p.name)) {
215                availablePlugins.remove(p.name);
216            }
217        }
218    }
219
220    @Override
221    protected void realRun() throws SAXException, IOException, OsmTransferException {
222        Collection<String> pluginLocations = PluginInformation.getPluginLocations();
223        getProgressMonitor().setTicksCount(pluginLocations.size() + 2);
224        if (canceled) return;
225        for (String location : pluginLocations) {
226            scanLocalPluginRepository(
227                    getProgressMonitor().createSubTaskMonitor(1, false),
228                    new File(location)
229            );
230            getProgressMonitor().worked(1);
231            if (canceled)return;
232        }
233        analyseInProcessPlugins();
234        getProgressMonitor().worked(1);
235        if (canceled)return;
236        filterOldPlugins();
237        getProgressMonitor().worked(1);
238    }
239
240    /**
241     * Replies information about available plugins detected by this task.
242     *
243     * @return information about available plugins detected by this task.
244     */
245    public List<PluginInformation> getAvailablePlugins() {
246        return new ArrayList<PluginInformation>(availablePlugins.values());
247    }
248
249    /**
250     * Replies true if the task was canceled by the user
251     *
252     * @return true if the task was canceled by the user
253     */
254    public boolean isCanceled() {
255        return canceled;
256    }
257}
Note: See TracBrowser for help on using the repository browser.