/******************************************************************************* * Copyright (c) 2011-2012 Nokia Corporation * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Comarch team - initial API and implementation *******************************************************************************/ package org.ned.client.transfer; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Enumeration; import java.util.Vector; import javax.microedition.io.ConnectionNotFoundException; import javax.microedition.io.Connector; import javax.microedition.io.HttpConnection; import javax.microedition.io.file.FileConnection; import org.ned.client.MotdManager; import org.ned.client.NedConsts; import org.ned.client.NedConsts.NedLocalConst; import org.ned.client.NedMidlet; import org.ned.client.NedResources; import org.ned.client.statistics.StatisticsManager; import org.ned.client.utils.NedConnectionUtils; import org.ned.client.utils.NedIOUtils; public class DownloadTask implements Runnable { private IDownloadTaskManager downloadTaskManager; private Thread mTransferThread = null; private boolean stopped = false; private String title = null; private String filename = null; private String urlPath = null; private long bytesRead = 0; private long totalBytesDownloaded = 0; private float percentDownloaded = 0; private long downloadLength = 0; private boolean instantDownload = false; private final int counterUpdateViewInterval = 100000 / NedConnectionUtils.MTU; private int counterUpdateView = counterUpdateViewInterval; private String status = NedResources.TRA_WAITING_STATUS; private String percentDownloadItemLabel = "0"; private InputStream activeConnection; public DownloadTask( IDownloadTaskManager downloadTaskManager, String filename, String url, String title ) { this.downloadTaskManager = downloadTaskManager; downloadTaskManager.addNewDownloadTask( this ); this.filename = filename; this.urlPath = url; this.title = title; } public boolean isDownloading() { return (mTransferThread != null && mTransferThread.isAlive()); } public boolean getInstantDownload() { return instantDownload; } public void setInstantDownload( boolean _instantDownload ) { instantDownload = _instantDownload; } public String getTitle() { return title; } public String getFile() { return filename; } public String getUrlPath() { return urlPath; } public void setStatus( String _status ) { status = _status; downloadTaskManager.statusChanged( this ); } public String getStatus() { return status; } public void setBytesRead( long _bytesRead ) { bytesRead = _bytesRead; } public long getBytesRead() { return bytesRead; } public long getTotalBytesDownloaded() { return totalBytesDownloaded; } public void addTotalBytesDownloaded( long morebytes ) { totalBytesDownloaded += morebytes; } public void setDownloadLength( long _downloadLength ) { downloadLength = _downloadLength; } public void setPercentDownloaded( String initValue ) { percentDownloadItemLabel = initValue; } public String getPercentDownloaded() { return percentDownloadItemLabel; } public int getPercentDownloadedInt() { float percent = ((float) totalBytesDownloaded / (float) downloadLength) * 100; return downloadLength != 0 ? (int) percent : 0; } public void setPercentDownloaded() { if ( counterUpdateView < 0 || totalBytesDownloaded == downloadLength ) { counterUpdateView = counterUpdateViewInterval; percentDownloaded = ((float) totalBytesDownloaded / (float) downloadLength) * 100; int percent = (int) percentDownloaded; int percentDot = (int) (percentDownloaded * 100) - 100 * percent; String afterDot = String.valueOf( percentDot ); if ( percentDot < 10 ) { afterDot = "0" + afterDot; } percentDownloadItemLabel = String.valueOf( percent ) + "." + afterDot; downloadTaskManager.progresUpdate( this ); } else { counterUpdateView--; } } public long getDownloadLength() { return downloadLength; } public void run() { try { download(); if ( NedMidlet.getSettingsManager().getAutoStatSend() ) { StatisticsManager.uploadStats( true ); } MotdManager.getInstance().updateMotd(); } catch ( IOException ex ) { ex.printStackTrace(); } finally { if ( status.equals( NedResources.TRA_COMPLETED_STATUS ) ) { if ( downloadTaskManager != null ) { downloadTaskManager.taskCompleted( this ); downloadTaskManager = null; } } else if ( status.equals( NedResources.TRA_CANCELLING_STATUS ) ) { removeFile(); } } } private void download() throws IOException { HttpConnection hc = null; InputStream ic = null; FileConnection fc = null; OutputStream oc = null; long offset = 0; try { setStatus( NedResources.TRA_CHECKING_STATUS ); if ( NedIOUtils.fileExists( filename ) ) { setStatus( NedResources.TRA_COMPLETED_STATUS ); return; } fc = (FileConnection) Connector.open( filename + NedLocalConst.TMP, Connector.READ_WRITE ); if ( fc.exists() ) { offset = fc.fileSize(); } else { fc.create(); } setStatus( NedResources.TRA_CONNECTING_STATUS ); hc = (HttpConnection) Connector.open( urlPath ); hc.setRequestMethod( HttpConnection.GET ); hc.setRequestProperty( "Range", "bytes=" + String.valueOf( offset ) + "-" ); hc.setRequestProperty( NedConsts.HttpHeader.CACHECONTROL, NedConsts.HttpHeaderValue.NOCACHE ); ic = hc.openDataInputStream(); activeConnection = ic; int responseCode = hc.getResponseCode(); if ( responseCode == HttpConnection.HTTP_PARTIAL || responseCode == HttpConnection.HTTP_OK ) { setStatus( NedResources.TRA_CONNECTED_STATUS ); long length = hc.getLength(); setBytesRead( 0 ); totalBytesDownloaded = offset; setDownloadLength( length + offset ); //set length of download byte[] databyte = new byte[NedConnectionUtils.MTU]; oc = fc.openOutputStream( fc.fileSize() ); while ( true ) { if ( stopped ) { break; } setBytesRead( ic.read( databyte, 0, NedConnectionUtils.MTU ) ); if ( bytesRead == -1 ) { break;//transfer completed - end of file reached } addTotalBytesDownloaded( bytesRead ); setPercentDownloaded(); oc.write( databyte, 0, (int) bytesRead ); } } else { if ( fc != null && fc.exists() ) { fc.delete(); } } activeConnection = null; if ( stopped ) { NedMidlet.getInstance().getXmlManager().setProgress( filename, percentDownloaded, downloadLength ); } else { setStatus( NedResources.TRA_COMPLETED_STATUS ); String name = filename.substring( filename.lastIndexOf( '/' ) + 1 ); fc.rename( name ); } } catch ( ConnectionNotFoundException cnex ) { //TODO - add message } catch ( IOException ioe ) { } catch ( IllegalArgumentException iex ) { //TODO - add message //NedMidlet.getInstance().showMessageDialog(); } catch ( SecurityException sex ) { //TODO - add message } finally { if ( ic != null ) { ic.close(); } if ( hc != null ) { hc.close(); } if ( oc != null ) { oc.close(); } if ( fc != null ) { fc.close(); } } } public boolean startDownload( boolean aForceStart ) { boolean result = false; if ( NedMidlet.getInstance().getDownloadManager().countActiveDownload() < DownloadManager.MAX_DOWNLOADS ) { result = startDownload(); } if ( aForceStart ) { //pause active downalod Vector/*<DownloadTask>*/ queue = NedMidlet.getInstance().getDownloadManager().getMainDownloadQueue(); final Enumeration en = queue.elements(); while( en.hasMoreElements() ) { DownloadTask dt = (DownloadTask)en.nextElement(); if ( dt.isDownloading() ) { dt.stopDownload(); break; } } result = startDownload(); } return result; } private boolean startDownload() { boolean result; mTransferThread = new Thread( this ); mTransferThread.setPriority( Thread.MIN_PRIORITY ); stopped = false; mTransferThread.start(); result = true; return result; } public void stopDownload() { status = NedResources.TRA_WAITING_STATUS; stopped = true; } public void CancelAndRemove() { if ( activeConnection != null ) { try { activeConnection.close(); activeConnection = null; } catch ( IOException ex ) { ex.printStackTrace(); } } setStatus( NedResources.TRA_CANCELLING_STATUS ); stopped = true; if ( mTransferThread == null || !mTransferThread.isAlive() ) { removeFile(); } } private void removeFile() { if ( downloadTaskManager != null ) { downloadTaskManager.taskCancelled( this ); downloadTaskManager = null; } FileConnection fc = null; try { fc = (FileConnection) Connector.open( filename + NedLocalConst.TMP, Connector.READ_WRITE ); if ( fc.exists() ) { fc.delete(); } } catch ( IOException ex ) { } finally { if ( fc != null ) { try { fc.close(); } catch ( Exception ex ) { } } } } }