3c3709a5e3b86309240db5cfc1bba46c2abbeed5
[pub/Android/ownCloud.git] /
1 /* ownCloud webDAV Library for Android is available under MIT license
2 * Copyright (C) 2014 ownCloud (http://www.owncloud.org/)
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
18 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
19 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 * THE SOFTWARE.
22 *
23 */
24
25 package com.owncloud.android.oc_framework.network.webdav;
26
27 import java.io.File;
28 import java.io.IOException;
29 import java.io.OutputStream;
30 import java.nio.ByteBuffer;
31 import java.nio.channels.FileChannel;
32 import java.util.Collection;
33 import java.util.HashSet;
34 import java.util.Iterator;
35 import java.util.Set;
36
37 import org.apache.commons.httpclient.methods.RequestEntity;
38
39 import com.owncloud.android.oc_framework.network.ProgressiveDataTransferer;
40
41 import android.util.Log;
42
43
44 /**
45 * A RequestEntity that represents a PIECE of a file.
46 *
47 * @author David A. Velasco
48 */
49 public class ChunkFromFileChannelRequestEntity implements RequestEntity, ProgressiveDataTransferer {
50
51 private static final String TAG = ChunkFromFileChannelRequestEntity.class.getSimpleName();
52
53 //private final File mFile;
54 private final FileChannel mChannel;
55 private final String mContentType;
56 private final long mChunkSize;
57 private final File mFile;
58 private long mOffset;
59 private long mTransferred;
60 Set<OnDatatransferProgressListener> mDataTransferListeners = new HashSet<OnDatatransferProgressListener>();
61 private ByteBuffer mBuffer = ByteBuffer.allocate(4096);
62
63 public ChunkFromFileChannelRequestEntity(final FileChannel channel, final String contentType, long chunkSize, final File file) {
64 super();
65 if (channel == null) {
66 throw new IllegalArgumentException("File may not be null");
67 }
68 if (chunkSize <= 0) {
69 throw new IllegalArgumentException("Chunk size must be greater than zero");
70 }
71 mChannel = channel;
72 mContentType = contentType;
73 mChunkSize = chunkSize;
74 mFile = file;
75 mOffset = 0;
76 mTransferred = 0;
77 }
78
79 public void setOffset(long offset) {
80 mOffset = offset;
81 }
82
83 public long getContentLength() {
84 try {
85 return Math.min(mChunkSize, mChannel.size() - mChannel.position());
86 } catch (IOException e) {
87 return mChunkSize;
88 }
89 }
90
91 public String getContentType() {
92 return mContentType;
93 }
94
95 public boolean isRepeatable() {
96 return true;
97 }
98
99 @Override
100 public void addDatatransferProgressListener(OnDatatransferProgressListener listener) {
101 synchronized (mDataTransferListeners) {
102 mDataTransferListeners.add(listener);
103 }
104 }
105
106 @Override
107 public void addDatatransferProgressListeners(Collection<OnDatatransferProgressListener> listeners) {
108 synchronized (mDataTransferListeners) {
109 mDataTransferListeners.addAll(listeners);
110 }
111 }
112
113 @Override
114 public void removeDatatransferProgressListener(OnDatatransferProgressListener listener) {
115 synchronized (mDataTransferListeners) {
116 mDataTransferListeners.remove(listener);
117 }
118 }
119
120
121 public void writeRequest(final OutputStream out) throws IOException {
122 int readCount = 0;
123 Iterator<OnDatatransferProgressListener> it = null;
124
125 try {
126 mChannel.position(mOffset);
127 long size = mFile.length();
128 if (size == 0) size = -1;
129 long maxCount = Math.min(mOffset + mChunkSize, mChannel.size());
130 while (mChannel.position() < maxCount) {
131 readCount = mChannel.read(mBuffer);
132 out.write(mBuffer.array(), 0, readCount);
133 mBuffer.clear();
134 if (mTransferred < maxCount) { // condition to avoid accumulate progress for repeated chunks
135 mTransferred += readCount;
136 }
137 synchronized (mDataTransferListeners) {
138 it = mDataTransferListeners.iterator();
139 while (it.hasNext()) {
140 it.next().onTransferProgress(readCount, mTransferred, size, mFile.getAbsolutePath());
141 }
142 }
143 }
144
145 } catch (IOException io) {
146 Log.e(TAG, io.getMessage());
147 throw new RuntimeException("Ugly solution to workaround the default policy of retries when the server falls while uploading ; temporal fix; really", io);
148
149 }
150 }
151
152 }