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.hc.core5.http.nio.entity;
28
29 import java.io.IOException;
30 import java.nio.ByteBuffer;
31 import java.nio.CharBuffer;
32 import java.nio.charset.Charset;
33 import java.nio.charset.StandardCharsets;
34 import java.util.Collections;
35 import java.util.Set;
36 import java.util.concurrent.atomic.AtomicReference;
37
38 import org.apache.hc.core5.http.ContentType;
39 import org.apache.hc.core5.http.nio.AsyncEntityProducer;
40 import org.apache.hc.core5.http.nio.DataStreamChannel;
41 import org.apache.hc.core5.util.Args;
42
43
44
45
46
47
48
49 public class BasicAsyncEntityProducer implements AsyncEntityProducer {
50
51 private final ByteBuffer bytebuf;
52 private final int length;
53 private final ContentType contentType;
54 private final boolean chunked;
55 private final AtomicReference<Exception> exception;
56
57 public BasicAsyncEntityProducer(final byte[] content, final ContentType contentType, final boolean chunked) {
58 Args.notNull(content, "Content");
59 this.bytebuf = ByteBuffer.wrap(content);
60 this.length = this.bytebuf.remaining();
61 this.contentType = contentType;
62 this.chunked = chunked;
63 this.exception = new AtomicReference<>();
64 }
65
66 public BasicAsyncEntityProducer(final byte[] content, final ContentType contentType) {
67 this(content, contentType, false);
68 }
69
70 public BasicAsyncEntityProducer(final byte[] content) {
71 this(content, ContentType.APPLICATION_OCTET_STREAM);
72 }
73
74 public BasicAsyncEntityProducer(final CharSequence content, final ContentType contentType, final boolean chunked) {
75 Args.notNull(content, "Content");
76 this.contentType = contentType;
77 final Charset charset = ContentType.getCharset(contentType, StandardCharsets.UTF_8);
78 this.bytebuf = charset.encode(CharBuffer.wrap(content));
79 this.length = this.bytebuf.remaining();
80 this.chunked = chunked;
81 this.exception = new AtomicReference<>();
82 }
83
84 public BasicAsyncEntityProducer(final CharSequence content, final ContentType contentType) {
85 this(content, contentType, false);
86 }
87
88 public BasicAsyncEntityProducer(final CharSequence content) {
89 this(content, ContentType.TEXT_PLAIN);
90 }
91
92 @Override
93 public boolean isRepeatable() {
94 return true;
95 }
96
97 @Override
98 public final String getContentType() {
99 return contentType != null ? contentType.toString() : null;
100 }
101
102 @Override
103 public long getContentLength() {
104 return length;
105 }
106
107 @Override
108 public int available() {
109 return Integer.MAX_VALUE;
110 }
111
112 @Override
113 public String getContentEncoding() {
114 return null;
115 }
116
117 @Override
118 public boolean isChunked() {
119 return chunked;
120 }
121
122 @Override
123 public Set<String> getTrailerNames() {
124 return Collections.emptySet();
125 }
126
127 @Override
128 public final void produce(final DataStreamChannel channel) throws IOException {
129 if (bytebuf.hasRemaining()) {
130 channel.write(bytebuf);
131 }
132 if (!bytebuf.hasRemaining()) {
133 channel.endStream();
134 }
135 }
136
137 @Override
138 public final void failed(final Exception cause) {
139 if (exception.compareAndSet(null, cause)) {
140 releaseResources();
141 }
142 }
143
144 public final Exception getException() {
145 return exception.get();
146 }
147
148 @Override
149 public void releaseResources() {
150 bytebuf.clear();
151 bytebuf.limit(length);
152 }
153
154 }