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

Last change on this file since 10781 was 10616, checked in by Don-vip, 8 years ago

see #11390 - sonar - squid:S1604 - Java 8: Anonymous inner classes containing only one method should become lambdas

  • Property svn:eol-style set to native
File size: 8.1 KB
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.Main;
17import org.openstreetmap.josm.gui.PleaseWaitRunnable;
18import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
19import org.openstreetmap.josm.gui.progress.ProgressMonitor;
20import org.openstreetmap.josm.io.OsmTransferException;
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 {@link org.openstreetmap.josm.data.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="https://josm.openstreetmap.de/pluginicons">https://josm.openstreetmap.de/pluginicons</a></li>
34 * </ul>
35 *
36 */
37public class ReadLocalPluginInformationTask extends PleaseWaitRunnable {
38 private final Map<String, PluginInformation> availablePlugins;
39 private boolean canceled;
40
41 /**
42 * Constructs a new {@code ReadLocalPluginInformationTask}.
43 */
44 public ReadLocalPluginInformationTask() {
45 super(tr("Reading local plugin information.."), false);
46 availablePlugins = new HashMap<>();
47 }
48
49 /**
50 * Constructs a new {@code ReadLocalPluginInformationTask}.
51 * @param monitor progress monitor
52 */
53 public ReadLocalPluginInformationTask(ProgressMonitor monitor) {
54 super(tr("Reading local plugin information.."), monitor, false);
55 availablePlugins = new HashMap<>();
56 }
57
58 @Override
59 protected void cancel() {
60 canceled = true;
61 }
62
63 @Override
64 protected void finish() {
65 // Do nothing
66 }
67
68 protected void processJarFile(File f, String pluginName) throws PluginException {
69 PluginInformation info = new PluginInformation(
70 f,
71 pluginName
72 );
73 if (!availablePlugins.containsKey(info.getName())) {
74 info.updateLocalInfo(info);
75 availablePlugins.put(info.getName(), info);
76 } else {
77 PluginInformation current = availablePlugins.get(info.getName());
78 current.updateFromJar(info);
79 }
80 }
81
82 private static File[] listFiles(File pluginsDirectory, final String regex) {
83 return pluginsDirectory.listFiles((FilenameFilter) (dir, name) -> name.matches(regex));
84 }
85
86 protected void scanSiteCacheFiles(ProgressMonitor monitor, File pluginsDirectory) {
87 File[] siteCacheFiles = listFiles(pluginsDirectory, "^([0-9]+-)?site.*\\.txt$");
88 if (siteCacheFiles == null || siteCacheFiles.length == 0)
89 return;
90 monitor.subTask(tr("Processing plugin site cache files..."));
91 monitor.setTicksCount(siteCacheFiles.length);
92 for (File f: siteCacheFiles) {
93 String fname = f.getName();
94 monitor.setCustomText(tr("Processing file ''{0}''", fname));
95 try {
96 processLocalPluginInformationFile(f);
97 } catch (PluginListParseException e) {
98 Main.warn(tr("Failed to scan file ''{0}'' for plugin information. Skipping.", fname));
99 Main.error(e);
100 }
101 monitor.worked(1);
102 }
103 }
104
105 protected void scanPluginFiles(ProgressMonitor monitor, File pluginsDirectory) {
106 File[] pluginFiles = pluginsDirectory.listFiles(
107 (FilenameFilter) (dir, name) -> name.endsWith(".jar") || name.endsWith(".jar.new")
108 );
109 if (pluginFiles == null || pluginFiles.length == 0)
110 return;
111 monitor.subTask(tr("Processing plugin files..."));
112 monitor.setTicksCount(pluginFiles.length);
113 for (File f: pluginFiles) {
114 String fname = f.getName();
115 monitor.setCustomText(tr("Processing file ''{0}''", fname));
116 try {
117 if (fname.endsWith(".jar")) {
118 String pluginName = fname.substring(0, fname.length() - 4);
119 processJarFile(f, pluginName);
120 } else if (fname.endsWith(".jar.new")) {
121 String pluginName = fname.substring(0, fname.length() - 8);
122 processJarFile(f, pluginName);
123 }
124 } catch (PluginException e) {
125 Main.warn(e, "PluginException: ");
126 Main.warn(tr("Failed to scan file ''{0}'' for plugin information. Skipping.", fname));
127 }
128 monitor.worked(1);
129 }
130 }
131
132 protected void scanLocalPluginRepository(ProgressMonitor monitor, File pluginsDirectory) {
133 if (pluginsDirectory == null)
134 return;
135 if (monitor == null)
136 monitor = NullProgressMonitor.INSTANCE;
137 try {
138 monitor.beginTask("");
139 scanSiteCacheFiles(monitor, pluginsDirectory);
140 scanPluginFiles(monitor, pluginsDirectory);
141 } finally {
142 monitor.setCustomText("");
143 monitor.finishTask();
144 }
145 }
146
147 protected void processLocalPluginInformationFile(File file) throws PluginListParseException {
148 try (FileInputStream fin = new FileInputStream(file)) {
149 List<PluginInformation> pis = new PluginListParser().parse(fin);
150 for (PluginInformation pi : pis) {
151 // we always keep plugin information from a plugin site because it
152 // includes information not available in the plugin jars Manifest, i.e.
153 // the download link or localized descriptions
154 //
155 availablePlugins.put(pi.name, pi);
156 }
157 } catch (IOException e) {
158 throw new PluginListParseException(e);
159 }
160 }
161
162 protected void analyseInProcessPlugins() {
163 for (PluginProxy proxy : PluginHandler.pluginList) {
164 PluginInformation info = proxy.getPluginInformation();
165 if (canceled) return;
166 if (!availablePlugins.containsKey(info.name)) {
167 availablePlugins.put(info.name, info);
168 } else {
169 availablePlugins.get(info.name).localversion = info.localversion;
170 }
171 }
172 }
173
174 protected void filterOldPlugins() {
175 for (PluginHandler.DeprecatedPlugin p : PluginHandler.DEPRECATED_PLUGINS) {
176 if (canceled) return;
177 if (availablePlugins.containsKey(p.name)) {
178 availablePlugins.remove(p.name);
179 }
180 }
181 }
182
183 @Override
184 protected void realRun() throws SAXException, IOException, OsmTransferException {
185 Collection<String> pluginLocations = PluginInformation.getPluginLocations();
186 getProgressMonitor().setTicksCount(pluginLocations.size() + 2);
187 if (canceled) return;
188 for (String location : pluginLocations) {
189 scanLocalPluginRepository(
190 getProgressMonitor().createSubTaskMonitor(1, false),
191 new File(location)
192 );
193 getProgressMonitor().worked(1);
194 if (canceled) return;
195 }
196 analyseInProcessPlugins();
197 getProgressMonitor().worked(1);
198 if (canceled) return;
199 filterOldPlugins();
200 getProgressMonitor().worked(1);
201 }
202
203 /**
204 * Replies information about available plugins detected by this task.
205 *
206 * @return information about available plugins detected by this task.
207 */
208 public List<PluginInformation> getAvailablePlugins() {
209 return new ArrayList<>(availablePlugins.values());
210 }
211
212 /**
213 * Replies true if the task was canceled by the user
214 *
215 * @return true if the task was canceled by the user
216 */
217 public boolean isCanceled() {
218 return canceled;
219 }
220}
Note: See TracBrowser for help on using the repository browser.