source: josm/trunk/src/org/openstreetmap/josm/plugins/PluginDownloadTask.java@ 6073

Last change on this file since 6073 was 6073, checked in by Don-vip, 11 years ago

fix #8886 - Allow to download plugin jars redirected from https to http, like those hosted on github

  • Property svn:eol-style set to native
File size: 7.9 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.awt.Component;
7import java.io.File;
8import java.io.FileOutputStream;
9import java.io.IOException;
10import java.io.InputStream;
11import java.io.OutputStream;
12import java.net.HttpURLConnection;
13import java.net.MalformedURLException;
14import java.net.URL;
15import java.util.Collection;
16import java.util.LinkedList;
17
18import org.openstreetmap.josm.Main;
19import org.openstreetmap.josm.data.Version;
20import org.openstreetmap.josm.gui.ExtendedDialog;
21import org.openstreetmap.josm.gui.PleaseWaitRunnable;
22import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
23import org.openstreetmap.josm.gui.progress.ProgressMonitor;
24import org.openstreetmap.josm.io.MirroredInputStream;
25import org.openstreetmap.josm.tools.CheckParameterUtil;
26import org.openstreetmap.josm.tools.Utils;
27import org.xml.sax.SAXException;
28
29
30/**
31 * Asynchronous task for downloading a collection of plugins.
32 *
33 * When the task is finished {@link #getDownloadedPlugins()} replies the list of downloaded plugins
34 * and {@link #getFailedPlugins()} replies the list of failed plugins.
35 *
36 */
37public class PluginDownloadTask extends PleaseWaitRunnable{
38 private final Collection<PluginInformation> toUpdate = new LinkedList<PluginInformation>();
39 private final Collection<PluginInformation> failed = new LinkedList<PluginInformation>();
40 private final Collection<PluginInformation> downloaded = new LinkedList<PluginInformation>();
41 private Exception lastException;
42 private boolean canceled;
43 private HttpURLConnection downloadConnection;
44
45 /**
46 * Creates the download task
47 *
48 * @param parent the parent component relative to which the {@link org.openstreetmap.josm.gui.PleaseWaitDialog} is displayed
49 * @param toUpdate a collection of plugin descriptions for plugins to update/download. Must not be null.
50 * @param title the title to display in the {@link org.openstreetmap.josm.gui.PleaseWaitDialog}
51 * @throws IllegalArgumentException thrown if toUpdate is null
52 */
53 public PluginDownloadTask(Component parent, Collection<PluginInformation> toUpdate, String title) throws IllegalArgumentException{
54 super(parent, title == null ? "" : title, false /* don't ignore exceptions */);
55 CheckParameterUtil.ensureParameterNotNull(toUpdate, "toUpdate");
56 this.toUpdate.addAll(toUpdate);
57 }
58
59 /**
60 * Creates the task
61 *
62 * @param monitor a progress monitor. Defaults to {@link NullProgressMonitor#INSTANCE} if null
63 * @param toUpdate a collection of plugin descriptions for plugins to update/download. Must not be null.
64 * @param title the title to display in the {@link org.openstreetmap.josm.gui.PleaseWaitDialog}
65 * @throws IllegalArgumentException thrown if toUpdate is null
66 */
67 public PluginDownloadTask(ProgressMonitor monitor, Collection<PluginInformation> toUpdate, String title) {
68 super(title, monitor == null? NullProgressMonitor.INSTANCE: monitor, false /* don't ignore exceptions */);
69 CheckParameterUtil.ensureParameterNotNull(toUpdate, "toUpdate");
70 this.toUpdate.addAll(toUpdate);
71 }
72
73 /**
74 * Sets the collection of plugins to update.
75 *
76 * @param toUpdate the collection of plugins to update. Must not be null.
77 * @throws IllegalArgumentException thrown if toUpdate is null
78 */
79 public void setPluginsToDownload(Collection<PluginInformation> toUpdate) throws IllegalArgumentException{
80 CheckParameterUtil.ensureParameterNotNull(toUpdate, "toUpdate");
81 this.toUpdate.clear();
82 this.toUpdate.addAll(toUpdate);
83 }
84
85 @Override protected void cancel() {
86 this.canceled = true;
87 synchronized(this) {
88 if (downloadConnection != null) {
89 downloadConnection.disconnect();
90 }
91 }
92 }
93
94 @Override protected void finish() {}
95
96 protected void download(PluginInformation pi, File file) throws PluginDownloadException{
97 if (pi.mainversion > Version.getInstance().getVersion()) {
98 ExtendedDialog dialog = new ExtendedDialog(
99 progressMonitor.getWindowParent(),
100 tr("Skip download"),
101 new String[] {
102 tr("Download Plugin"),
103 tr("Skip Download") }
104 );
105 dialog.setContent(tr("JOSM version {0} required for plugin {1}.", pi.mainversion, pi.name));
106 dialog.setButtonIcons(new String[] { "download.png", "cancel.png" });
107 dialog.showDialog();
108 int answer = dialog.getValue();
109 if (answer != 1)
110 throw new PluginDownloadException(tr("Download skipped"));
111 }
112 OutputStream out = null;
113 InputStream in = null;
114 try {
115 if (pi.downloadlink == null) {
116 String msg = tr("Warning: Cannot download plugin ''{0}''. Its download link is not known. Skipping download.", pi.name);
117 System.err.println(msg);
118 throw new PluginDownloadException(msg);
119 }
120 URL url = new URL(pi.downloadlink);
121 synchronized(this) {
122 downloadConnection = MirroredInputStream.connectFollowingRedirect(url);
123 }
124 in = downloadConnection.getInputStream();
125 out = new FileOutputStream(file);
126 byte[] buffer = new byte[8192];
127 for (int read = in.read(buffer); read != -1; read = in.read(buffer)) {
128 out.write(buffer, 0, read);
129 }
130 } catch(MalformedURLException e) {
131 String msg = tr("Warning: Cannot download plugin ''{0}''. Its download link ''{1}'' is not a valid URL. Skipping download.", pi.name, pi.downloadlink);
132 System.err.println(msg);
133 throw new PluginDownloadException(msg);
134 } catch (IOException e) {
135 if (canceled)
136 return;
137 throw new PluginDownloadException(e);
138 } finally {
139 Utils.close(in);
140 synchronized(this) {
141 downloadConnection = null;
142 }
143 Utils.close(out);
144 }
145 }
146
147 @Override protected void realRun() throws SAXException, IOException {
148 File pluginDir = Main.pref.getPluginsDirectory();
149 if (!pluginDir.exists()) {
150 if (!pluginDir.mkdirs()) {
151 lastException = new PluginDownloadException(tr("Failed to create plugin directory ''{0}''", pluginDir.toString()));
152 failed.addAll(toUpdate);
153 return;
154 }
155 }
156 getProgressMonitor().setTicksCount(toUpdate.size());
157 for (PluginInformation d : toUpdate) {
158 if (canceled) return;
159 progressMonitor.subTask(tr("Downloading Plugin {0}...", d.name));
160 progressMonitor.worked(1);
161 File pluginFile = new File(pluginDir, d.name + ".jar.new");
162 try {
163 download(d, pluginFile);
164 } catch(PluginDownloadException e) {
165 e.printStackTrace();
166 failed.add(d);
167 continue;
168 }
169 downloaded.add(d);
170 }
171 PluginHandler.installDownloadedPlugins(false);
172 }
173
174 /**
175 * Replies true if the task was canceled by the user
176 *
177 * @return <code>true</code> if the task was stopped by the user
178 */
179 public boolean isCanceled() {
180 return canceled;
181 }
182
183 /**
184 * Replies the list of successfully downloaded plugins
185 *
186 * @return the list of successfully downloaded plugins
187 */
188 public Collection<PluginInformation> getFailedPlugins() {
189 return failed;
190 }
191
192 /**
193 * Replies the list of plugins whose download has failed
194 *
195 * @return the list of plugins whose download has failed
196 */
197 public Collection<PluginInformation> getDownloadedPlugins() {
198 return downloaded;
199 }
200}
Note: See TracBrowser for help on using the repository browser.