1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.xnap.pkg;
21
22 import java.io.File;
23 import java.io.FileOutputStream;
24 import java.io.IOException;
25 import java.io.InputStream;
26 import java.io.OutputStream;
27 import java.net.URL;
28 import java.util.Enumeration;
29 import java.util.zip.ZipEntry;
30 import java.util.zip.ZipFile;
31
32 import org.apache.log4j.Logger;
33 import org.xnap.XNap;
34 import org.xnap.loader.XNapClassLoader;
35 import org.xnap.net.NetHelper;
36 import org.xnap.util.FileHelper;
37 import org.xnap.util.Formatter;
38 import org.xnap.util.StringHelper;
39
40 public class PackageInstaller {
41
42
43
44
45
46 private static Logger logger = Logger.getLogger(PackageInstaller.class);
47
48 privatePackageInfo[] packages/package-summary.html">ong> PackageInfo[] packages;
49 private DownloadRunner dlRunner;
50
51 private PackageInstallerListener listener;
52 private boolean successful = false;
53
54
55
56 publicPackageInstaller(PackageInfo[] packages,/package-summary.html">ong> PackageInstaller(PackageInfo[] packages,
57 PackageInstallerListener listener)
58 {
59 this.packages = packages;
60 this.listener = listener;
61
62 int totalSize = 0;
63 for (int i = 0; i < packages.length; i++) {
64 totalSize += packages[i].getSize();
65 }
66 listener.setTotalMinimum(0);
67 listener.setTotalValue(0);
68 listener.setTotalMaximum(totalSize);
69 listener.setText(XNap.tr("Need to download {0} in {1} packages.",
70 Formatter.formatSize(totalSize),
71 new Integer(packages.length)));
72
73 }
74
75
76
77 public PackageInfo[] getPackageInfos()
78 {
79 returng> packages;
80 }
81
82 public boolean isSuccessful()
83 {
84 return successful;
85 }
86
87 public void start()
88 {
89 dlRunner = new DownloadRunner();
90 Thread t = new Thread(dlRunner, "PluginDownload");
91 t.start();
92 }
93
94
95
96 private class DownloadRunner implements Runnable
97 {
98
99 private long totalTransferred = 0;
100
101 public File createTempFile(String filename) throws IOException
102 {
103 File pathes[] = XNapClassLoader.getSearchPath();
104 for (int i = 0; i < pathes.length; i++) {
105 File f = new File(pathes[i], filename);
106 logger.debug("trying " + f.getAbsolutePath());
107 if (f.exists() && f.canWrite()) {
108 return f;
109 }
110 else if ((f.getParentFile().exists()
111 || f.getParentFile().mkdirs())
112 && f.createNewFile()) {
113 return f;
114 }
115 }
116
117 return null;
118 }
119
120 public File download(InputStream in, String filename)
121 throws IOException
122 {
123 File tempFile = createTempFile(filename + ".part");
124 if (tempFile == null) {
125 throw new IOException(XNap.tr("Could not create file."));
126 }
127
128 File target = new File(tempFile.getParentFile(), filename);
129 if (target.exists() && !target.delete()) {
130 throw new IOException
131 (XNap.tr("A file with this name already exists."));
132 }
133
134 OutputStream out = null;
135 try {
136 out = new FileOutputStream(tempFile.getAbsolutePath(), false);
137
138 listener.setText(XNap.tr("Downloading {0}", filename));
139
140 long transferred = 0;
141 int c = 0;
142 byte[] b = new byte[500];
143 while (c != -1 && !listener.isCancelled()) {
144 c = in.read(b);
145 if (c != -1) {
146 out.write(b, 0, c);
147
148 transferred += c;
149 totalTransferred += c;
150
151 listener.setValue((int)transferred);
152 listener.setTotalValue((int)totalTransferred);
153 }
154 }
155 out.close();
156 }
157 catch (IOException e) {
158 if (out != null) {
159 try {
160 out.close();
161 tempFile.delete();
162 }
163 catch (IOException e2) {
164 }
165 }
166 throw e;
167 }
168
169 if (!tempFile.renameTo(target)) {
170 throw new IOException(XNap.tr("Could not rename file."));
171 }
172
173 return target;
174 }
175
176 public File downloadPackage(PackageInfo info)
177 {
178 String filename = info.getDownloadFilename();
179 if (filename != null) {
180 File file = new File(filename);
181 if (file.exists() && file.length() == info.getSize()) {
182 return file;
183 }
184 }
185
186 String[] urls = info.getDownloadURLs();
187
188 if (
189 (urls.length > 0
190 && (urls[0].indexOf("sf.net") > 0
191 || urls[0].indexOf("sourceforge.net") > 0))) {
192
193
194 try {
195 URL url = new URL("http://prdownloads.sourceforge.net/xnap/"
196 + info.getFilename() + "?use_mirror=unc");
197 InputStream in = url.openStream();
198 try {
199 in.read();
200 }
201 finally {
202 in.close();
203 }
204 }
205 catch (IOException e) {
206 }
207 }
208
209 for (int i = 0; i < urls.length; i++) {
210 String location = urls[i] + info.getFilename();
211
212 listener.setText(XNap.tr("Getting {0}", location));
213 listener.setMinimum(0);
214 listener.setValue(0);
215 listener.setMaximum((int)info.getSize());
216
217 long value = totalTransferred;
218 try {
219 URL url = new URL(location);
220
221
222 filename = StringHelper.lastToken(info.getFilename(), "/");
223 if (filename.length() == 0) {
224 filename = info.getFilename();
225 }
226
227 return download(url.openStream(), filename);
228 }
229 catch (IOException e) {
230
231 listener.setTotalValue((int)value);
232 logger.info("Download failed", e);
233 }
234 }
235
236
237 return null;
238 }
239
240 public String unzip(File file) throws IOException
241 {
242 listener.setText(XNap.tr("Unzipping {0}", file.getName()));
243
244 String controlPath = null;
245 File base = file.getParentFile();
246 ZipFile zip = new ZipFile(file);
247
248 int i = 0;
249 for (Enumeration it = zip.entries();
250 it.hasMoreElements(); i++) {
251 ZipEntry entry = (ZipEntry)it.nextElement();
252 File target = new File(base.getAbsolutePath()
253 + File.separatorChar + entry.getName());
254 if (entry.isDirectory()) {
255 logger.debug("creating directory: "
256 + target.getAbsolutePath());
257 target.mkdirs();
258 }
259 else {
260 logger.debug("unzipping file: "
261 + target.getAbsolutePath());
262
263 InputStream in = zip.getInputStream(entry);
264 try {
265 FileHelper.copy(in, new FileOutputStream(target));
266 }
267 finally {
268 try {
269 in.close();
270 }
271 catch (IOException e) {
272 }
273 }
274
275 if (target.getName().equals("control")) {
276 controlPath = target.getParentFile().getAbsolutePath();
277 }
278 }
279 }
280 file.delete();
281
282 return controlPath;
283 }
284
285 public void run()
286 {
287 try {
288 for (int i = 0; i < packages.length
289 && !listener.isCancelled(); i++) {
290
291 File target = downloadPackage(packages[i]);
292 if (target != null) {
293 try {
294 String path = unzip(target);
295 if (path == null) {
296 throw new IOException
297 (XNap.tr("Invalid package, control file is missing."));
298 }
299
300 packages[i].getProperties().setProperty
301 ("Control-Path", path);
302 }
303 catch (IOException e) {
304 logger.debug("Error unziping plugin", e);
305 listener.setText(NetHelper.getErrorMessage(e));
306 return;
307 }
308
309
310
311
312
313 packages[i].setDownloadFilename
314 (target.getAbsolutePath());
315 }
316 else {
317 listener.setText
318 (XNap.tr("Unable to download package {0}.",
319 packages[i].getName()));
320 return;
321 }
322 }
323
324 successful = !listener.isCancelled();
325 if (successful) {
326 for (int i = 0; i < packages.length; i++) {
327 packages[i].setInstalled(true);
328 File file
329 = new File(packages[i].getDownloadFilename());
330 file.delete();
331 }
332 listener.setText(XNap.tr("Finished successfully."));
333 }
334 else {
335 listener.setText(XNap.tr("Cancelled by user."));
336 }
337
338 listener.setPercent(1.0);
339 listener.setTotalPercent(1.0);
340 }
341 finally {
342 listener.done();
343 }
344 }
345 }
346 }