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

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

fixed #2851: Proxy caching problem

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