source: josm/trunk/src/org/openstreetmap/josm/plugins/ReadRemotePluginInformationTask.java@ 3084

Last change on this file since 3084 was 3084, checked in by Gubaer, 14 years ago

fixed #4660: Local plugin list does not display umlauts
Local cache now encoded in UTF-8 too. You have to remove your cached plugin lists or download the plugin list in the plugin preferences.

  • Property svn:eol-style set to native
File size: 9.0 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.BufferedReader;
7import java.io.ByteArrayInputStream;
8import java.io.File;
9import java.io.FileOutputStream;
10import java.io.IOException;
11import java.io.InputStream;
12import java.io.InputStreamReader;
13import java.io.OutputStreamWriter;
14import java.io.PrintWriter;
15import java.io.UnsupportedEncodingException;
16import java.net.HttpURLConnection;
17import java.net.MalformedURLException;
18import java.net.URL;
19import java.util.ArrayList;
20import java.util.Arrays;
21import java.util.Collection;
22import java.util.Collections;
23import java.util.HashSet;
24import java.util.LinkedList;
25import java.util.List;
26
27import org.openstreetmap.josm.Main;
28import org.openstreetmap.josm.data.Version;
29import org.openstreetmap.josm.gui.PleaseWaitRunnable;
30import org.openstreetmap.josm.gui.progress.ProgressMonitor;
31import org.openstreetmap.josm.io.OsmTransferException;
32import org.xml.sax.SAXException;
33
34/**
35 * An asynchronous task for downloading plugin lists from the configured plugin download
36 * sites.
37 *
38 */
39public class ReadRemotePluginInformationTask extends PleaseWaitRunnable{
40
41 private Collection<String> sites;
42 private boolean canceled;
43 private HttpURLConnection connection;
44 private List<PluginInformation> availabePlugins;
45
46 /**
47 * Creates the task
48 *
49 * @param sites the collection of download sites. Defaults to the empty collection if null.
50 */
51 public ReadRemotePluginInformationTask(Collection<String> sites) {
52 super(tr("Download plugin list..."), false /* don't ignore exceptions */);
53 this.sites = sites;
54 if (sites == null) {
55 this.sites = Collections.emptySet();
56 }
57 availabePlugins = new LinkedList<PluginInformation>();
58 }
59
60 @Override
61 protected void cancel() {
62 canceled = true;
63 synchronized(this) {
64 if (connection != null) {
65 connection.disconnect();
66 }
67 }
68 }
69
70 @Override
71 protected void finish() {}
72
73 /**
74 * Creates the file name for the cached plugin list.
75 *
76 * @param site the name of the site
77 * @return the file name for the cache file
78 */
79 protected String createSiteCacheFileName(String site) {
80 try {
81 URL url = new URL(site);
82 StringBuilder sb = new StringBuilder();
83 sb.append("site-");
84 sb.append(url.getHost()).append("-");
85 if (url.getPort() != -1) {
86 sb.append(url.getPort()).append("-");
87 }
88 String path = url.getPath();
89 for (int i =0;i<path.length(); i++) {
90 char c = path.charAt(i);
91 if (Character.isLetterOrDigit(c)) {
92 sb.append(c);
93 } else {
94 sb.append("_");
95 }
96 }
97 sb.append(".txt");
98 return sb.toString();
99 } catch(MalformedURLException e) {
100 return "site-unknown.txt";
101 }
102 }
103
104 /**
105 * Downloads the list from a remote location
106 *
107 * @param site the site URL
108 * @param monitor a progress monitor
109 * @return the downloaded list
110 */
111 protected String downloadPluginList(String site, ProgressMonitor monitor) {
112 BufferedReader in = null;
113 StringBuilder sb = new StringBuilder();
114 try {
115 monitor.beginTask("");
116 monitor.indeterminateSubTask(tr("Downloading plugin list from ''{0}''", site));
117
118 URL url = new URL(site);
119 synchronized(this) {
120 connection = (HttpURLConnection)url.openConnection();
121 connection.setRequestProperty("Cache-Control", "no-cache");
122 connection.setRequestProperty("User-Agent",Version.getInstance().getAgentString());
123 connection.setRequestProperty("Host", url.getHost());
124 connection.setRequestProperty("Accept-Charset", "utf-8");
125 }
126 in = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
127 String line;
128 while((line = in.readLine()) != null) {
129 sb.append(line).append("\n");
130 }
131 return sb.toString();
132 } catch(MalformedURLException e) {
133 if (canceled) return null;
134 e.printStackTrace();
135 return null;
136 } catch(IOException e) {
137 if (canceled) return null;
138 e.printStackTrace();
139 return null;
140 } finally {
141 synchronized(this) {
142 if (connection != null) {
143 connection.disconnect();
144 }
145 connection = null;
146 }
147 if (in != null) {
148 try {
149 in.close();
150 } catch(IOException e){/* ignore */}
151 }
152 monitor.finishTask();
153 }
154 }
155
156 /**
157 * Writes the list of plugins to a cache file
158 *
159 * @param site the site from where the list was downloaded
160 * @param list the downloaded list
161 */
162 protected void cachePluginList(String site, String list) {
163 PrintWriter writer = null;
164 try {
165 File pluginDir = Main.pref.getPluginsDirectory();
166 if (!pluginDir.exists()) {
167 if (! pluginDir.mkdirs()) {
168 System.err.println(tr("Warning: failed to create plugin directory ''{0}''. Cannot cache plugin list from plugin site ''{1}''.", pluginDir.toString(), site));
169 }
170 }
171 File cacheFile = new File(pluginDir, createSiteCacheFileName(site));
172 getProgressMonitor().subTask(tr("Writing plugin list to local cache ''{0}''", cacheFile.toString()));
173 writer = new PrintWriter(new OutputStreamWriter(new FileOutputStream(cacheFile), "utf-8"));
174 writer.write(list);
175 } catch(IOException e) {
176 // just failed to write the cache file. No big deal, but log the exception anyway
177 e.printStackTrace();
178 } finally {
179 if (writer != null) {
180 writer.flush();
181 writer.close();
182 }
183 }
184 }
185
186 /**
187 * Filter information about deprecated plugins from the list of downloaded
188 * plugins
189 *
190 * @param plugins the plugin informations
191 * @return the plugin informations, without deprecated plugins
192 */
193 protected List<PluginInformation> filterDeprecatedPlugins(List<PluginInformation> plugins) {
194 List<PluginInformation> ret = new ArrayList<PluginInformation>(plugins.size());
195 HashSet<String> deprecatedPluginNames = new HashSet<String>(Arrays.asList(PluginHandler.DEPRECATED_PLUGINS));
196 for (PluginInformation plugin: plugins) {
197 if (deprecatedPluginNames.contains(plugin.name)) {
198 continue;
199 }
200 ret.add(plugin);
201 }
202 return ret;
203 }
204
205 /**
206 * Parses the plugin list
207 *
208 * @param site the site from where the list was downloaded
209 * @param doc the document with the plugin list
210 */
211 protected void parsePluginListDocument(String site, String doc) {
212 try {
213 getProgressMonitor().subTask(tr("Parsing plugin list from site ''{0}''", site));
214 InputStream in = new ByteArrayInputStream(doc.getBytes("UTF-8"));
215 List<PluginInformation> pis = new PluginListParser().parse(in);
216 availabePlugins.addAll(filterDeprecatedPlugins(pis));
217 } catch(UnsupportedEncodingException e) {
218 System.err.println(tr("Failed to parse plugin list document from site ''{0}''. Skipping site. Exception was: {1}", site, e.toString()));
219 e.printStackTrace();
220 } catch(PluginListParseException e) {
221 System.err.println(tr("Failed to parse plugin list document from site ''{0}''. Skipping site. Exception was: {1}", site, e.toString()));
222 e.printStackTrace();
223 }
224 }
225
226 @Override
227 protected void realRun() throws SAXException, IOException, OsmTransferException {
228 if (sites == null) return;
229 getProgressMonitor().setTicksCount(sites.size() * 3);
230 for (String site: sites) {
231 getProgressMonitor().subTask(tr("Processing plugin list from site ''{0}''", site));
232 String list = downloadPluginList(site, getProgressMonitor().createSubTaskMonitor(0, false));
233 if (canceled) return;
234 getProgressMonitor().worked(1);
235 cachePluginList(site, list);
236 if (canceled) return;
237 getProgressMonitor().worked(1);
238 parsePluginListDocument(site, list);
239 if (canceled) return;
240 getProgressMonitor().worked(1);
241 }
242 }
243
244 /**
245 * Replies true if the task was canceled
246 * @return
247 */
248 public boolean isCanceled() {
249 return canceled;
250 }
251
252 /**
253 * Replies the list of plugins described in the downloaded plugin lists
254 *
255 * @return the list of plugins
256 */
257 public List<PluginInformation> getAvailabePlugins() {
258 return availabePlugins;
259 }
260}
Note: See TracBrowser for help on using the repository browser.