package loon.net; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.URL; import java.util.Observable; import loon.core.LRelease; import loon.utils.collection.ArrayByte; /** * Copyright 2008 - 2011 * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. * * @project loonframework * @author chenpeng * @email:ceponline@yahoo.com.cn * @version 0.1 */ public class HttpDownload extends Observable implements LRelease, Runnable { private static final int MAX_BUFFER_SIZE = 2048; public static final String STATUSES[] = { "Downloading", "Paused", "Complete", "Cancelled", "Error" }; public static final int DOWNLOADING = 0; public static final int PAUSED = 1; public static final int COMPLETE = 2; public static final int CANCELLED = 3; public static final int ERROR = 4; public static interface HttpDownloadListener { public void downloading(float progress); public void error(Exception ex); public void completed(); public void paused(); public void cancel(); } private boolean daemon; private float size; private float downloaded; private int status, priority; private ByteArrayOutputStream out; private HttpClientAbstract client; private HttpDownloadListener listener; private Exception exception; HttpDownload(HttpClientAbstract client) { this.client = client; this.daemon = false; this.out = new ByteArrayOutputStream(MAX_BUFFER_SIZE); this.size = -1; this.downloaded = 0; this.priority = Thread.NORM_PRIORITY; this.status = DOWNLOADING; } public URL getURL() { return client.getURL(); } public String getURLString() { return client.getURLString(); } public synchronized ArrayByte getArrayByte() { return new ArrayByte(out.toByteArray()); } public synchronized byte[] getBytes() { return out.toByteArray(); } public synchronized OutputStream getOutputStream() { return out; } public synchronized boolean save(File file) { boolean result = false; if (status != COMPLETE) { return result; } try { if (!file.exists()) { result = file.createNewFile(); } FileOutputStream output = new FileOutputStream(file); output.write(out.toByteArray()); output.close(); result = true; } catch (Exception e) { result = false; } return result; } public boolean save(String fileName) { return save(new File(fileName)); } public float getSize() { return size; } public float getProgressValue() { return downloaded / size; } public float getProgress() { return (downloaded / size) * 100; } public int getStatus() { return status; } public void pause() { status = PAUSED; stateChanged(); } public void resume() { status = DOWNLOADING; stateChanged(); start(); } public void cancel() { status = CANCELLED; stateChanged(); } private void error() { status = ERROR; stateChanged(); } public void reset() { out.reset(); size = 0; downloaded = 0; status = CANCELLED; stateChanged(); } public void stop() { reset(); client.stop(); } public void start() { Thread thread = new Thread(this); thread.setPriority(priority); thread.setDaemon(daemon); thread.start(); } @Override public void run() { if (client == null) { return; } if (!client.isRunning) { client.start(); } try { if (client.connection.getResponseCode() / 100 != 2) { error(); } int contentLength = client.connection.getContentLength(); if (contentLength < 1) { error(); } if (size == -1) { size = contentLength; stateChanged(); } InputStream in = client.getInputStream(); if (in == null) { in = client.connection.getInputStream(); } if (in == null) { if (!client.isRunning) { client.start(); } in = client.getConnection().getInputStream(); } if (in == null) { error(); } byte[] buffer = new byte[MAX_BUFFER_SIZE]; for (; status == DOWNLOADING;) { int read = in.read(buffer); if (read == -1) { break; } out.write(buffer, 0, read); downloaded += read; stateChanged(); } if (status == DOWNLOADING) { status = COMPLETE; stateChanged(); } } catch (Exception e) { this.error(); this.exception = e; } finally { client.stop(); } } public boolean isDaemon() { return daemon; } public void setDaemon(boolean daemon) { this.daemon = daemon; } public synchronized HttpDownloadListener getListener() { return listener; } public synchronized void setListener(HttpDownloadListener listener) { this.listener = listener; } public int getPriority() { return priority; } public void setPriority(int priority) { this.priority = priority; } private synchronized void stateChanged() { if (listener != null) { switch (status) { case DOWNLOADING: listener.downloading(getProgress()); break; case PAUSED: listener.paused(); break; case COMPLETE: listener.completed(); break; case CANCELLED: listener.cancel(); break; case ERROR: if (exception == null) { exception = new Exception("404 Error !"); } listener.error(exception); break; default: break; } } setChanged(); notifyObservers(); } @Override public synchronized void dispose() { stop(); if (out != null) { try { out.close(); out = null; } catch (IOException e) { } } } }