1 /* ownCloud Android Library 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
.lib
.network
;
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
;
40 import android
.util
.Log
;
44 * A RequestEntity that represents a PIECE of a file.
46 * @author David A. Velasco
48 public class ChunkFromFileChannelRequestEntity
implements RequestEntity
, ProgressiveDataTransferer
{
50 private static final String TAG
= ChunkFromFileChannelRequestEntity
.class.getSimpleName();
52 //private final File mFile;
53 private final FileChannel mChannel
;
54 private final String mContentType
;
55 private final long mChunkSize
;
56 private final File mFile
;
58 private long mTransferred
;
59 Set
<OnDatatransferProgressListener
> mDataTransferListeners
= new HashSet
<OnDatatransferProgressListener
>();
60 private ByteBuffer mBuffer
= ByteBuffer
.allocate(4096);
62 public ChunkFromFileChannelRequestEntity(final FileChannel channel
, final String contentType
, long chunkSize
, final File file
) {
64 if (channel
== null
) {
65 throw new IllegalArgumentException("File may not be null");
68 throw new IllegalArgumentException("Chunk size must be greater than zero");
71 mContentType
= contentType
;
72 mChunkSize
= chunkSize
;
78 public void setOffset(long offset
) {
82 public long getContentLength() {
84 return Math
.min(mChunkSize
, mChannel
.size() - mChannel
.position());
85 } catch (IOException e
) {
90 public String
getContentType() {
94 public boolean isRepeatable() {
99 public void addDatatransferProgressListener(OnDatatransferProgressListener listener
) {
100 synchronized (mDataTransferListeners
) {
101 mDataTransferListeners
.add(listener
);
106 public void addDatatransferProgressListeners(Collection
<OnDatatransferProgressListener
> listeners
) {
107 synchronized (mDataTransferListeners
) {
108 mDataTransferListeners
.addAll(listeners
);
113 public void removeDatatransferProgressListener(OnDatatransferProgressListener listener
) {
114 synchronized (mDataTransferListeners
) {
115 mDataTransferListeners
.remove(listener
);
120 public void writeRequest(final OutputStream out
) throws IOException
{
122 Iterator
<OnDatatransferProgressListener
> it
= null
;
125 mChannel
.position(mOffset
);
126 long size
= mFile
.length();
127 if (size
== 0) size
= -1;
128 long maxCount
= Math
.min(mOffset
+ mChunkSize
, mChannel
.size());
129 while (mChannel
.position() < maxCount
) {
130 readCount
= mChannel
.read(mBuffer
);
131 out
.write(mBuffer
.array(), 0, readCount
);
133 if (mTransferred
< maxCount
) { // condition to avoid accumulate progress for repeated chunks
134 mTransferred
+= readCount
;
136 synchronized (mDataTransferListeners
) {
137 it
= mDataTransferListeners
.iterator();
138 while (it
.hasNext()) {
139 it
.next().onTransferProgress(readCount
, mTransferred
, size
, mFile
.getAbsolutePath());
144 } catch (IOException io
) {
145 Log
.e(TAG
, io
.getMessage());
146 throw new RuntimeException("Ugly solution to workaround the default policy of retries when the server falls while uploading ; temporal fix; really", io
);