1 /* ownCloud webDAV Library for Android is available under MIT license
2 * Copyright (C) 2014 ownCloud (http://www.owncloud.org/)
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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
25 package com.owncloud.android.oc_framework.network.webdav;
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;
37 import org.apache.commons.httpclient.methods.RequestEntity;
39 import com.owncloud.android.oc_framework.network.ProgressiveDataTransferer;
41 import android.util.Log;
45 * A RequestEntity that represents a PIECE of a file.
47 * @author David A. Velasco
49 public class ChunkFromFileChannelRequestEntity implements RequestEntity, ProgressiveDataTransferer {
51 private static final String TAG = ChunkFromFileChannelRequestEntity.class.getSimpleName();
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;
59 private long mTransferred;
60 Set<OnDatatransferProgressListener> mDataTransferListeners = new HashSet<OnDatatransferProgressListener>();
61 private ByteBuffer mBuffer = ByteBuffer.allocate(4096);
63 public ChunkFromFileChannelRequestEntity(final FileChannel channel, final String contentType, long chunkSize, final File file) {
65 if (channel == null) {
66 throw new IllegalArgumentException("File may not be null");
69 throw new IllegalArgumentException("Chunk size must be greater than zero");
72 mContentType = contentType;
73 mChunkSize = chunkSize;
79 public void setOffset(long offset) {
83 public long getContentLength() {
85 return Math.min(mChunkSize, mChannel.size() - mChannel.position());
86 } catch (IOException e) {
91 public String getContentType() {
95 public boolean isRepeatable() {
100 public void addDatatransferProgressListener(OnDatatransferProgressListener listener) {
101 synchronized (mDataTransferListeners) {
102 mDataTransferListeners.add(listener);
107 public void addDatatransferProgressListeners(Collection<OnDatatransferProgressListener> listeners) {
108 synchronized (mDataTransferListeners) {
109 mDataTransferListeners.addAll(listeners);
114 public void removeDatatransferProgressListener(OnDatatransferProgressListener listener) {
115 synchronized (mDataTransferListeners) {
116 mDataTransferListeners.remove(listener);
121 public void writeRequest(final OutputStream out) throws IOException {
123 Iterator<OnDatatransferProgressListener> it = null;
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);
134 if (mTransferred < maxCount) { // condition to avoid accumulate progress for repeated chunks
135 mTransferred += readCount;
137 synchronized (mDataTransferListeners) {
138 it = mDataTransferListeners.iterator();
139 while (it.hasNext()) {
140 it.next().onTransferProgress(readCount, mTransferred, size, mFile.getAbsolutePath());
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);