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