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