1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 package org.apache.http.nio.client.methods;
28
29 import java.io.File;
30 import java.io.FileNotFoundException;
31 import java.io.IOException;
32 import java.io.RandomAccessFile;
33 import java.net.URI;
34 import java.nio.channels.FileChannel;
35
36 import org.apache.http.HttpEntity;
37 import org.apache.http.HttpEntityEnclosingRequest;
38 import org.apache.http.HttpException;
39 import org.apache.http.HttpHost;
40 import org.apache.http.HttpRequest;
41 import org.apache.http.client.utils.URIUtils;
42 import org.apache.http.entity.BasicHttpEntity;
43 import org.apache.http.entity.ContentType;
44 import org.apache.http.nio.ContentEncoder;
45 import org.apache.http.nio.ContentEncoderChannel;
46 import org.apache.http.nio.FileContentEncoder;
47 import org.apache.http.nio.IOControl;
48 import org.apache.http.nio.protocol.HttpAsyncRequestProducer;
49 import org.apache.http.protocol.HttpContext;
50 import org.apache.http.util.Args;
51
52 abstract class BaseZeroCopyRequestProducer implements HttpAsyncRequestProducer {
53
54 private final URI requestURI;
55 private final File file;
56 private final RandomAccessFile accessfile;
57 private final ContentType contentType;
58
59 private FileChannel fileChannel;
60 private long idx = -1;
61
62 protected BaseZeroCopyRequestProducer(
63 final URI requestURI,
64 final File file, final ContentType contentType) throws FileNotFoundException {
65 super();
66 Args.notNull(requestURI, "Request URI");
67 Args.notNull(file, "Source file");
68 this.requestURI = requestURI;
69 this.file = file;
70 this.accessfile = new RandomAccessFile(file, "r");
71 this.contentType = contentType;
72 }
73
74 private void closeChannel() throws IOException {
75 if (this.fileChannel != null) {
76 this.fileChannel.close();
77 this.fileChannel = null;
78 }
79 }
80
81 protected abstract HttpEntityEnclosingRequest createRequest(final URI requestURI, final HttpEntity entity);
82
83 @Override
84 public HttpRequest generateRequest() throws IOException, HttpException {
85 final BasicHttpEntity entity = new BasicHttpEntity();
86 entity.setChunked(false);
87 entity.setContentLength(this.file.length());
88 if (this.contentType != null) {
89 entity.setContentType(this.contentType.toString());
90 }
91 return createRequest(this.requestURI, entity);
92 }
93
94 @Override
95 public synchronized HttpHost getTarget() {
96 return URIUtils.extractHost(this.requestURI);
97 }
98
99 @Override
100 public synchronized void produceContent(
101 final ContentEncoder encoder, final IOControl ioctrl) throws IOException {
102 if (this.fileChannel == null) {
103 this.fileChannel = this.accessfile.getChannel();
104 this.idx = 0;
105 }
106 final long transferred;
107 if (encoder instanceof FileContentEncoder) {
108 transferred = ((FileContentEncoder)encoder).transfer(
109 this.fileChannel, this.idx, Integer.MAX_VALUE);
110 } else {
111 transferred = this.fileChannel.transferTo(
112 this.idx, Integer.MAX_VALUE, new ContentEncoderChannel(encoder));
113 }
114 if (transferred > 0) {
115 this.idx += transferred;
116 }
117
118 if (this.idx >= this.fileChannel.size()) {
119 encoder.complete();
120 closeChannel();
121 }
122 }
123
124 @Override
125 public void requestCompleted(final HttpContext context) {
126 }
127
128 @Override
129 public void failed(final Exception ex) {
130 }
131
132 @Override
133 public boolean isRepeatable() {
134 return true;
135 }
136
137 @Override
138 public synchronized void resetRequest() throws IOException {
139 closeChannel();
140 }
141
142 @Override
143 public synchronized void close() throws IOException {
144 try {
145 this.accessfile.close();
146 } catch (final IOException ignore) {
147 }
148 }
149
150 }