d0d249e061c90cf1d5940ddd8d763e23ef611cbf
[pub/Android/ownCloud.git] / src / com / owncloud / android / operations / DownloadFileOperation.java
1 /* ownCloud Android client application
2 * Copyright (C) 2012-2013 ownCloud Inc.
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 */
17
18 package com.owncloud.android.operations;
19
20 import java.io.File;
21 import java.util.HashSet;
22 import java.util.Iterator;
23 import java.util.Set;
24 import java.util.concurrent.atomic.AtomicBoolean;
25
26 import com.owncloud.android.MainApp;
27 import com.owncloud.android.datamodel.OCFile;
28 import com.owncloud.android.lib.common.network.OnDatatransferProgressListener;
29 import com.owncloud.android.lib.common.OwnCloudClient;
30 import com.owncloud.android.lib.common.operations.OperationCancelledException;
31 import com.owncloud.android.lib.common.operations.RemoteOperation;
32 import com.owncloud.android.lib.common.operations.RemoteOperationResult;
33 import com.owncloud.android.lib.common.utils.Log_OC;
34 import com.owncloud.android.lib.resources.files.DownloadRemoteFileOperation;
35 import com.owncloud.android.utils.FileStorageUtils;
36
37 import android.accounts.Account;
38 import android.media.MediaScannerConnection;
39 import android.webkit.MimeTypeMap;
40
41 /**
42 * Remote mDownloadOperation performing the download of a file to an ownCloud server
43 *
44 * @author David A. Velasco
45 * @author masensio
46 */
47 public class DownloadFileOperation extends RemoteOperation {
48
49 private static final String TAG = DownloadFileOperation.class.getSimpleName();
50
51 private Account mAccount;
52 private OCFile mFile;
53 private Set<OnDatatransferProgressListener> mDataTransferListeners = new HashSet<OnDatatransferProgressListener>();
54 private long mModificationTimestamp = 0;
55 private final AtomicBoolean mCancellationRequested = new AtomicBoolean(false);
56
57 private DownloadRemoteFileOperation mDownloadOperation;
58
59
60 public DownloadFileOperation(Account account, OCFile file) {
61 if (account == null)
62 throw new IllegalArgumentException("Illegal null account in DownloadFileOperation creation");
63 if (file == null)
64 throw new IllegalArgumentException("Illegal null file in DownloadFileOperation creation");
65
66 mAccount = account;
67 mFile = file;
68
69 }
70
71
72 public Account getAccount() {
73 return mAccount;
74 }
75
76 public OCFile getFile() {
77 return mFile;
78 }
79
80 public String getSavePath() {
81 String path = mFile.getStoragePath(); // re-downloads should be done over the original file
82 if (path != null && path.length() > 0) {
83 return path;
84 }
85 return FileStorageUtils.getDefaultSavePathFor(mAccount.name, mFile);
86 }
87
88 public String getTmpPath() {
89 return FileStorageUtils.getTemporalPath(mAccount.name) + mFile.getRemotePath();
90 }
91
92 public String getTmpFolder() {
93 return FileStorageUtils.getTemporalPath(mAccount.name);
94 }
95
96 public String getRemotePath() {
97 return mFile.getRemotePath();
98 }
99
100 public String getMimeType() {
101 String mimeType = mFile.getMimetype();
102 if (mimeType == null || mimeType.length() <= 0) {
103 try {
104 mimeType = MimeTypeMap.getSingleton()
105 .getMimeTypeFromExtension(
106 mFile.getRemotePath().substring(mFile.getRemotePath().lastIndexOf('.') + 1));
107 } catch (IndexOutOfBoundsException e) {
108 Log_OC.e(TAG, "Trying to find out MIME type of a file without extension: " + mFile.getRemotePath());
109 }
110 }
111 if (mimeType == null) {
112 mimeType = "application/octet-stream";
113 }
114 return mimeType;
115 }
116
117 public long getSize() {
118 return mFile.getFileLength();
119 }
120
121 public long getModificationTimestamp() {
122 return (mModificationTimestamp > 0) ? mModificationTimestamp : mFile.getModificationTimestamp();
123 }
124
125 @Override
126 protected RemoteOperationResult run(OwnCloudClient client) {
127 RemoteOperationResult result = null;
128 File newFile = null;
129 boolean moved = true;
130
131 /// download will be performed to a temporal file, then moved to the final location
132 File tmpFile = new File(getTmpPath());
133
134 String tmpFolder = getTmpFolder();
135
136 /// perform the download
137 synchronized(mCancellationRequested) {
138 if (mCancellationRequested.get()) {
139 return new RemoteOperationResult(new OperationCancelledException());
140 }
141 }
142
143 mDownloadOperation = new DownloadRemoteFileOperation(mFile.getRemotePath(), tmpFolder);
144 Iterator<OnDatatransferProgressListener> listener = mDataTransferListeners.iterator();
145 while (listener.hasNext()) {
146 mDownloadOperation.addDatatransferProgressListener(listener.next());
147 }
148 result = mDownloadOperation.execute(client);
149
150 if (result.isSuccess()) {
151 mModificationTimestamp = mDownloadOperation.getModificationTimestamp();
152 newFile = new File(getSavePath());
153 newFile.getParentFile().mkdirs();
154 moved = tmpFile.renameTo(newFile);
155
156 MediaScannerConnection.scanFile(MainApp.getAppContext(),
157 new String[]{newFile.getAbsolutePath()}, null, null);
158
159
160 if (!moved)
161 result = new RemoteOperationResult(RemoteOperationResult.ResultCode.LOCAL_STORAGE_NOT_MOVED);
162 }
163 Log_OC.i(TAG, "Download of " + mFile.getRemotePath() + " to " + getSavePath() + ": " + result.getLogMessage());
164
165 return result;
166 }
167
168 public void cancel() {
169 mCancellationRequested.set(true); // atomic set; there is no need of synchronizing it
170 if (mDownloadOperation != null) {
171 mDownloadOperation.cancel();
172 }
173 }
174
175
176 public void addDatatransferProgressListener (OnDatatransferProgressListener listener) {
177 synchronized (mDataTransferListeners) {
178 mDataTransferListeners.add(listener);
179 }
180 }
181
182 public void removeDatatransferProgressListener(OnDatatransferProgressListener listener) {
183 synchronized (mDataTransferListeners) {
184 mDataTransferListeners.remove(listener);
185 }
186 }
187
188 }