001: /*
002: * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
004: *
005: * This program is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU General Public License version
007: * 2 only, as published by the Free Software Foundation.
008: *
009: * This program is distributed in the hope that it will be useful, but
010: * WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012: * General Public License version 2 for more details (a copy is
013: * included at /legal/license.txt).
014: *
015: * You should have received a copy of the GNU General Public License
016: * version 2 along with this work; if not, write to the Free Software
017: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
018: * 02110-1301 USA
019: *
020: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
021: * Clara, CA 95054 or visit www.sun.com if you need additional
022: * information or have any questions.
023: */
024:
025: package com.sun.jumpimpl.module.download;
026:
027: import com.sun.jump.module.download.*;
028:
029: import java.io.InputStream;
030: import java.io.File;
031: import java.io.FileOutputStream;
032: import java.net.HttpURLConnection;
033: import java.net.URL;
034: import java.net.URLConnection;
035: import java.util.Vector;
036:
037: class DownloaderImpl implements JUMPDownloader {
038:
039: JUMPDownloadDescriptor descriptor;
040: boolean isCancelled = false;
041:
042: // Error codes.
043: public static final String ST_SUCCESS = "900";
044: public static final String ST_INSUFFICIENTMEMORY = "901";
045: public static final String ST_USERCANCELLED = "902";
046: public static final String ST_LOSSOFSERVICE = "903";
047: public static final String ST_SIZEMISMATCH = "904";
048: public static final String ST_ATTRIBUTEMISMATCH = "905";
049: public static final String ST_INVALIDDESCRIPTOR = "906";
050: public static final String ST_INVALIDDDVERSION = "951";
051: public static String ST_DEVICEABORTED = "952";
052: public static String ST_NONACCEPTABLECONTENT = "953";
053: public static String ST_LOADERERROR = "954";
054:
055: JUMPDownloadProgressNotifier report = new JUMPDownloadProgressNotifier();
056:
057: public DownloaderImpl(JUMPDownloadDescriptor descriptor) {
058: this .descriptor = descriptor;
059: }
060:
061: public void setProgressListener(
062: JUMPDownloadProgressListener listener) {
063: report.setListener(listener);
064: }
065:
066: public void setProgressListener(
067: JUMPDownloadProgressListener listener, int updatePercent) {
068: report.setListener(listener, updatePercent);
069: }
070:
071: public URL start(JUMPDownloadDestination destination)
072: throws JUMPDownloadException {
073:
074: boolean downloadSucceeded = startDownload(descriptor
075: .getObjectURI(), descriptor.getInstallNotifyURI(),
076: descriptor.getSize(), destination);
077:
078: String fileExtension = null;
079:
080: if (descriptor.getType() == JUMPDownloadDescriptor.TYPE_APPLICATION) {
081: fileExtension = ".jar";
082: }
083:
084: if (downloadSucceeded) {
085: try {
086: File jarFile = File.createTempFile("content",
087: fileExtension);
088: FileOutputStream fos = new FileOutputStream(jarFile);
089: fos.write(((DownloadDestinationImpl) destination)
090: .getBuffer());
091: fos.close();
092:
093: return jarFile.toURI().toURL();
094: } catch (Exception e) {
095: e.printStackTrace();
096: throw new JUMPDownloadException(e.toString());
097: }
098: }
099:
100: return null;
101:
102: }
103:
104: private String encode(String url) {
105: // Change spaces to %20
106: String encodedURL = "";
107: for (int i = 0; i < url.length(); i++) {
108: char c = url.charAt(i);
109: if (c == ' ') {
110: encodedURL += "%20";
111: } else {
112: encodedURL += c;
113: }
114: }
115: return encodedURL;
116: }
117:
118: public boolean startDownload(String url, String nfUri, int size,
119: JUMPDownloadDestination store) throws JUMPDownloadException {
120:
121: int gran = 0;
122: int pct = 0;
123:
124: try {
125: if (report != null) {
126: gran = report.getGranularity();
127: }
128:
129: URL objectUrl = new URL(encode(url));
130:
131: if (report != null) {
132: report.updatePercent(0);
133: }
134:
135: URLConnection conn = objectUrl.openConnection();
136:
137: if (objectUrl.getProtocol().equals("http")
138: && ((HttpURLConnection) conn).getResponseCode() != HttpURLConnection.HTTP_OK) {
139: if (nfUri != null) {
140: sendNotify(nfUri, ST_LOADERERROR,
141: "Can't process server response");
142: }
143:
144: throw new JUMPDownloadException(
145: "Http response is not OK: "
146: + ((HttpURLConnection) conn)
147: .getResponseCode());
148: }
149:
150: String mimeType = conn.getContentType();
151:
152: if (DownloadModuleFactoryImpl.verbose) {
153: System.err.println("debug : download : mimetype is "
154: + mimeType);
155: }
156:
157: /**
158: ** mimetype evaluation is currently missing from the public API.
159: **
160: ** try
161: ** {
162: ** store.acceptMimeType( mimeType );
163: ** }
164: ** catch ( JUMPDownloadException ee )
165: ** {
166: ** if ( nfUri != null )
167: ** {
168: ** sendNotify( nfUri,
169: ** ST_NONACCEPTABLECONTENT,
170: ** "Unknown MIME type" );
171: ** }
172: ** if ( report != null )
173: ** {
174: ** report.downloadDone();
175: ** }
176: ** throw ee;
177: ** }
178: **/
179:
180: InputStream in = conn.getInputStream();
181: store.start(objectUrl, mimeType);
182:
183: int bufferSize = store.getMaxChunkSize();
184: if (bufferSize <= 0) {
185: bufferSize = 8192;
186: }
187:
188: byte[] data = new byte[bufferSize];
189: int len = 0;
190:
191: while (true) {
192: int wantread = size - len;
193: if (size <= 0) {
194: wantread = bufferSize;
195: }
196:
197: if (wantread > bufferSize) {
198: wantread = bufferSize;
199: }
200:
201: int chunk = store.receive(in, wantread);
202: if (chunk <= 0) {
203: break;
204: }
205: len += chunk;
206:
207: // Report percentage complete, if appropriate.
208: if (report != null && size != 0) {
209: int current_pct = len * 100 / size;
210: if (current_pct - pct > gran) {
211: pct = current_pct;
212: report.updatePercent(pct);
213: }
214: }
215: }
216:
217: if ((size > 0) && (len != size)) {
218: if (nfUri != null) {
219: sendNotify(nfUri, ST_SIZEMISMATCH, (size - len)
220: + " bytes missing");
221: }
222: if (report != null) {
223: report.downloadDone();
224: }
225: throw new JUMPDownloadException("Could only read "
226: + len + " bytes");
227: }
228:
229: if ((size > 0) && (in.read() != -1)) {
230: if (nfUri != null) {
231: sendNotify(nfUri, ST_SIZEMISMATCH, "Too many bytes");
232: }
233: if (report != null) {
234: report.downloadDone();
235: }
236: throw new JUMPDownloadException("Read past " + len
237: + " bytes");
238: }
239:
240: in.close();
241: store.finish();
242: in = null;
243: if (report != null) {
244: report.updatePercent(100);
245: try {
246: Thread.sleep(300);
247: } catch (Exception e) {
248: // eat the exception
249: }
250: report.downloadDone();
251: }
252:
253: store = null;
254:
255: } catch (Exception e) {
256: System.out.println("download exception: " + e.getMessage());
257: e.printStackTrace();
258: if (store != null) {
259: store.abort();
260: }
261: if ((report != null) && (!isCancelled)) {
262: if (nfUri != null) {
263: sendNotify(nfUri, ST_LOADERERROR, "I/O error");
264: }
265: report.downloadDone();
266: throw new JUMPDownloadException("I/O trouble:\n"
267: + e.toString());
268: }
269: }
270:
271: if ((report != null) && (isCancelled)) {
272: report.downloadDone();
273: return false;
274: }
275: return true;
276: }
277:
278: public void cancel() {
279: isCancelled = true;
280: report.notifyCancelled();
281: }
282:
283: /**
284: * Returns the download descriptor that is associated with the
285: * download action.
286: */
287: public JUMPDownloadDescriptor getDescriptor() {
288: return descriptor;
289: }
290:
291: public boolean sendNotify(String uri, String statusCode,
292: String statusMsg) {
293: System.err.println("sendNotify() not supported " + statusMsg);
294:
295: return false;
296: }
297:
298: class JUMPDownloadProgressNotifier {
299:
300: JUMPDownloadProgressListener listener;
301: int granularity = 10;
302:
303: public void setListener(JUMPDownloadProgressListener listener) {
304: this .listener = listener;
305: }
306:
307: public void setListener(JUMPDownloadProgressListener listener,
308: int percent) {
309: this .listener = listener;
310: granularity = percent;
311: }
312:
313: public int getGranularity() {
314: return granularity;
315: }
316:
317: public void notifyCancelled() {
318: if (listener != null)
319: listener.downloadStarted();
320: }
321:
322: public void downloadDone() {
323: if (listener != null)
324: listener.downloadCompleted();
325: }
326:
327: public void updatePercent(int percent) {
328: if (listener != null) {
329: if (percent == 0) {
330: listener.downloadStarted();
331: }
332: listener.dataDownloaded(percent);
333: }
334: }
335: }
336: }
|