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.support.classic;
28
29 import java.io.IOException;
30 import java.io.OutputStream;
31 import java.util.Set;
32 import java.util.concurrent.Executor;
33 import java.util.concurrent.atomic.AtomicReference;
34
35 import org.apache.hc.core5.http.ContentType;
36 import org.apache.hc.core5.http.nio.AsyncEntityProducer;
37 import org.apache.hc.core5.http.nio.DataStreamChannel;
38 import org.apache.hc.core5.util.Args;
39
40
41
42
43
44
45
46
47 public abstract class AbstractClassicEntityProducer implements AsyncEntityProducer {
48
49 private enum State { IDLE, ACTIVE, COMPLETED }
50
51 private final SharedOutputBuffer buffer;
52 private final ContentType contentType;
53 private final Executor executor;
54 private final AtomicReference<State> state;
55 private final AtomicReference<Exception> exception;
56
57 public AbstractClassicEntityProducer(final int initialBufferSize, final ContentType contentType, final Executor executor) {
58 this.buffer = new SharedOutputBuffer(initialBufferSize);
59 this.contentType = contentType;
60 this.executor = Args.notNull(executor, "Executor");
61 this.state = new AtomicReference<>(State.IDLE);
62 this.exception = new AtomicReference<>();
63 }
64
65
66
67
68
69
70
71 protected abstract void produceData(ContentType contentType, OutputStream outputStream) throws IOException;
72
73 @Override
74 public final boolean isRepeatable() {
75 return false;
76 }
77
78 @Override
79 public final int available() {
80 return buffer.length();
81 }
82
83 @Override
84 public final void produce(final DataStreamChannel channel) throws IOException {
85 if (state.compareAndSet(State.IDLE, State.ACTIVE)) {
86 executor.execute(() -> {
87 try {
88 produceData(contentType, new ContentOutputStream(buffer));
89 buffer.writeCompleted();
90 } catch (final Exception ex) {
91 buffer.abort();
92 } finally {
93 state.set(State.COMPLETED);
94 }
95 });
96 }
97 buffer.flush(channel);
98 }
99
100 @Override
101 public final long getContentLength() {
102 return -1;
103 }
104
105 @Override
106 public final String getContentType() {
107 return contentType != null ? contentType.toString() : null;
108 }
109
110 @Override
111 public String getContentEncoding() {
112 return null;
113 }
114
115 @Override
116 public final boolean isChunked() {
117 return false;
118 }
119
120 @Override
121 public final Set<String> getTrailerNames() {
122 return null;
123 }
124
125 @Override
126 public final void failed(final Exception cause) {
127 if (exception.compareAndSet(null, cause)) {
128 releaseResources();
129 }
130 }
131
132 public final Exception getException() {
133 return exception.get();
134 }
135
136 @Override
137 public void releaseResources() {
138 }
139
140 }