package org.diretto.api.client.main.storage.download; import java.io.IOException; import java.io.OutputStream; import java.net.URL; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import org.apache.http.HttpResponse; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DefaultHttpClient; import org.diretto.api.client.main.core.CoreService; import org.diretto.api.client.main.core.entities.AttachmentID; import org.diretto.api.client.main.core.entities.CoreServiceEntityIDFactory; import org.diretto.api.client.main.core.entities.DocumentID; /** * This class is the implementation class of the {@link DownloadProcess} * interface. * * @author Tobias Schlecht */ final class DownloadProcessImpl implements DownloadProcess, Future<DownloadReport>, Runnable { private final URL fileURL; private final OutputStream outputStream; private final CoreService coreService; private final URL serviceURL; private final DefaultHttpClient httpClient; private final AttachmentID attachmentID; private final CountDownLatch countDownLatch = new CountDownLatch(1); private volatile DownloadHttpEntity downloadHttpEntity; private volatile boolean done = false; private volatile DownloadState downloadState = DownloadState.INIT; private volatile long downloadProcessStartTime = 0L; private volatile long downloadProcessEndTime = 0L; private volatile DownloadReport downloadReport = null; /** * Constructs an object of the {@link DownloadProcess} interface. * * @param downloadManager The corresponding {@code DownloadManager} * @param fileURL The {@code URL} of the resource to be downloaded * @param outputStream outputStream The {@code OutputStream} to which the * resource content should be written */ DownloadProcessImpl(DownloadManager downloadManager, URL fileURL, OutputStream outputStream) { this.fileURL = fileURL; this.outputStream = outputStream; coreService = downloadManager.getCoreService(); serviceURL = downloadManager.getServiceURL(); httpClient = downloadManager.getHttpClient(); String documentIDString = downloadManager.getAPIBaseURL().toExternalForm() + "/document/"; String fileURLString = fileURL.toExternalForm(); fileURLString = fileURLString.substring(serviceURL.toExternalForm().length() + 1, fileURLString.length()); documentIDString = documentIDString + fileURLString.substring(0, fileURLString.indexOf("/")); fileURLString = fileURLString.substring(fileURLString.indexOf("/") + 1, fileURLString.length()); String attachmentIDString = documentIDString + "/attachment/" + fileURLString.substring(0, fileURLString.indexOf(".")); DocumentID documentID = CoreServiceEntityIDFactory.getDocumentIDInstance(documentIDString); attachmentID = CoreServiceEntityIDFactory.getAttachmentIDInstance(attachmentIDString, documentID, documentID); } @Override public boolean cancel(boolean mayInterruptIfRunning) { throw new UnsupportedOperationException(); } @Override public DownloadReport get() throws InterruptedException, ExecutionException { countDownLatch.await(); return downloadReport; } @Override public DownloadReport get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { countDownLatch.await(timeout, unit); return downloadReport; } @Override public boolean isCancelled() { return false; } @Override public boolean isDone() { return done; } @Override public void run() { try { downloadProcessStartTime = System.nanoTime(); HttpGet httpGet = new HttpGet(fileURL.toExternalForm()); downloadState = DownloadState.DOWNLOADING; HttpResponse httpResponse = httpClient.execute(httpGet); System.out.println("[StorageService DownloadProcessImpl] " + fileURL.toExternalForm()); if(httpResponse.getStatusLine().getStatusCode() != 200 && httpResponse.getStatusLine().getStatusCode() != 202) { System.err.println("[StorageService DownloadProcessImpl] " + httpResponse.getStatusLine().getStatusCode()); return; } downloadHttpEntity = new DownloadHttpEntity(httpResponse.getEntity(), coreService.getPlatformMediaType(httpResponse.getEntity().getContentType().getValue())); downloadHttpEntity.writeTo(outputStream); downloadProcessEndTime = System.nanoTime(); downloadReport = new DownloadReport(downloadHttpEntity, fileURL, attachmentID, downloadProcessStartTime, downloadProcessEndTime, downloadProcessStartTime, downloadProcessEndTime); downloadState = DownloadState.FINISHED; downloadHttpEntity.consumeContent(); } catch(ClientProtocolException e) { return; } catch(IOException e) { return; } finally { done = true; if(downloadProcessEndTime == 0L) { downloadProcessEndTime = System.nanoTime(); } if(downloadState != DownloadState.FINISHED) { downloadState = DownloadState.ABORTED; } countDownLatch.countDown(); } } @Override public synchronized int getProgress() { switch(getCurrentState()) { case INIT: return 0; case DOWNLOADING: if(downloadHttpEntity == null) { return 0; } return (int) ((double) (downloadHttpEntity.getByteCount() * 100L) / (double) downloadHttpEntity.getContentLength()); case FINISHED: return 100; case ABORTED: return 100; default: return 0; } } @Override public synchronized long getElapsedTime() { if(downloadProcessStartTime == 0L) { return 0L; } else if(downloadProcessEndTime != 0L) { return Math.round(((double) (downloadProcessEndTime - downloadProcessStartTime)) / 1000000.0d); } return Math.round(((double) (System.nanoTime() - downloadProcessStartTime)) / 1000000.0d); } @Override public synchronized DownloadState getCurrentState() { return downloadState; } }