1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.handler.codec.http2;
17
18 import io.netty.util.internal.ThrowableUtil;
19
20 import java.util.ArrayList;
21 import java.util.Arrays;
22 import java.util.Iterator;
23 import java.util.List;
24
25 import static io.netty.handler.codec.http2.Http2CodecUtil.CONNECTION_STREAM_ID;
26 import static io.netty.util.internal.ObjectUtil.checkNotNull;
27
28
29
30
31 public class Http2Exception extends Exception {
32 private static final long serialVersionUID = -6941186345430164209L;
33 private final Http2Error error;
34 private final ShutdownHint shutdownHint;
35
36 public Http2Exception(Http2Error error) {
37 this(error, ShutdownHint.HARD_SHUTDOWN);
38 }
39
40 public Http2Exception(Http2Error error, ShutdownHint shutdownHint) {
41 this.error = checkNotNull(error, "error");
42 this.shutdownHint = checkNotNull(shutdownHint, "shutdownHint");
43 }
44
45 public Http2Exception(Http2Error error, String message) {
46 this(error, message, ShutdownHint.HARD_SHUTDOWN);
47 }
48
49 public Http2Exception(Http2Error error, String message, ShutdownHint shutdownHint) {
50 super(message);
51 this.error = checkNotNull(error, "error");
52 this.shutdownHint = checkNotNull(shutdownHint, "shutdownHint");
53 }
54
55 public Http2Exception(Http2Error error, String message, Throwable cause) {
56 this(error, message, cause, ShutdownHint.HARD_SHUTDOWN);
57 }
58
59 public Http2Exception(Http2Error error, String message, Throwable cause, ShutdownHint shutdownHint) {
60 super(message, cause);
61 this.error = checkNotNull(error, "error");
62 this.shutdownHint = checkNotNull(shutdownHint, "shutdownHint");
63 }
64
65 static Http2Exception newStatic(Http2Error error, String message, ShutdownHint shutdownHint,
66 Class<?> clazz, String method) {
67 final Http2Exception exception = new StacklessHttp2Exception(error, message, shutdownHint, true);
68 return ThrowableUtil.unknownStackTrace(exception, clazz, method);
69 }
70
71 private Http2Exception(Http2Error error, String message, ShutdownHint shutdownHint, boolean shared) {
72 super(message, null, false, true);
73 assert shared;
74 this.error = checkNotNull(error, "error");
75 this.shutdownHint = checkNotNull(shutdownHint, "shutdownHint");
76 }
77
78 public Http2Error error() {
79 return error;
80 }
81
82
83
84
85 public ShutdownHint shutdownHint() {
86 return shutdownHint;
87 }
88
89
90
91
92
93
94
95
96
97 public static Http2Exception connectionError(Http2Error error, String fmt, Object... args) {
98 return new Http2Exception(error, formatErrorMessage(fmt, args));
99 }
100
101
102
103
104
105
106
107
108
109
110 public static Http2Exception connectionError(Http2Error error, Throwable cause,
111 String fmt, Object... args) {
112 return new Http2Exception(error, formatErrorMessage(fmt, args), cause);
113 }
114
115
116
117
118
119
120
121
122
123 public static Http2Exception closedStreamError(Http2Error error, String fmt, Object... args) {
124 return new ClosedStreamCreationException(error, formatErrorMessage(fmt, args));
125 }
126
127
128
129
130
131
132
133
134
135
136
137
138
139 public static Http2Exception streamError(int id, Http2Error error, String fmt, Object... args) {
140 return CONNECTION_STREAM_ID == id ?
141 connectionError(error, fmt, args) :
142 new StreamException(id, error, formatErrorMessage(fmt, args));
143 }
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158 public static Http2Exception streamError(int id, Http2Error error, Throwable cause,
159 String fmt, Object... args) {
160 return CONNECTION_STREAM_ID == id ?
161 connectionError(error, cause, fmt, args) :
162 new StreamException(id, error, formatErrorMessage(fmt, args), cause);
163 }
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180 public static Http2Exception headerListSizeError(int id, Http2Error error, boolean onDecode,
181 String fmt, Object... args) {
182 return CONNECTION_STREAM_ID == id ?
183 connectionError(error, fmt, args) :
184 new HeaderListSizeException(id, error, formatErrorMessage(fmt, args), onDecode);
185 }
186
187 private static String formatErrorMessage(String fmt, Object[] args) {
188 if (fmt == null) {
189 if (args == null || args.length == 0) {
190 return "Unexpected error";
191 }
192 return "Unexpected error: " + Arrays.toString(args);
193 }
194 return String.format(fmt, args);
195 }
196
197
198
199
200
201
202
203 public static boolean isStreamError(Http2Exception e) {
204 return e instanceof StreamException;
205 }
206
207
208
209
210
211
212
213 public static int streamId(Http2Exception e) {
214 return isStreamError(e) ? ((StreamException) e).streamId() : CONNECTION_STREAM_ID;
215 }
216
217
218
219
220 public enum ShutdownHint {
221
222
223
224 NO_SHUTDOWN,
225
226
227
228
229 GRACEFUL_SHUTDOWN,
230
231
232
233 HARD_SHUTDOWN
234 }
235
236
237
238
239 public static final class ClosedStreamCreationException extends Http2Exception {
240 private static final long serialVersionUID = -6746542974372246206L;
241
242 public ClosedStreamCreationException(Http2Error error) {
243 super(error);
244 }
245
246 public ClosedStreamCreationException(Http2Error error, String message) {
247 super(error, message);
248 }
249
250 public ClosedStreamCreationException(Http2Error error, String message, Throwable cause) {
251 super(error, message, cause);
252 }
253 }
254
255
256
257
258 public static class StreamException extends Http2Exception {
259 private static final long serialVersionUID = 602472544416984384L;
260 private final int streamId;
261
262 StreamException(int streamId, Http2Error error, String message) {
263 super(error, message, ShutdownHint.NO_SHUTDOWN);
264 this.streamId = streamId;
265 }
266
267 StreamException(int streamId, Http2Error error, String message, Throwable cause) {
268 super(error, message, cause, ShutdownHint.NO_SHUTDOWN);
269 this.streamId = streamId;
270 }
271
272 public int streamId() {
273 return streamId;
274 }
275 }
276
277 public static final class HeaderListSizeException extends StreamException {
278 private static final long serialVersionUID = -8807603212183882637L;
279
280 private final boolean decode;
281
282 HeaderListSizeException(int streamId, Http2Error error, String message, boolean decode) {
283 super(streamId, error, message);
284 this.decode = decode;
285 }
286
287 public boolean duringDecode() {
288 return decode;
289 }
290 }
291
292
293
294
295 public static final class CompositeStreamException extends Http2Exception implements Iterable<StreamException> {
296 private static final long serialVersionUID = 7091134858213711015L;
297 private final List<StreamException> exceptions;
298
299 public CompositeStreamException(Http2Error error, int initialCapacity) {
300 super(error, ShutdownHint.NO_SHUTDOWN);
301 exceptions = new ArrayList<StreamException>(initialCapacity);
302 }
303
304 public void add(StreamException e) {
305 exceptions.add(e);
306 }
307
308 @Override
309 public Iterator<StreamException> iterator() {
310 return exceptions.iterator();
311 }
312 }
313
314 private static final class StacklessHttp2Exception extends Http2Exception {
315
316 private static final long serialVersionUID = 1077888485687219443L;
317
318 StacklessHttp2Exception(Http2Error error, String message, ShutdownHint shutdownHint) {
319 super(error, message, shutdownHint);
320 }
321
322 StacklessHttp2Exception(Http2Error error, String message, ShutdownHint shutdownHint, boolean shared) {
323 super(error, message, shutdownHint, shared);
324 }
325
326
327
328 @Override
329 public Throwable fillInStackTrace() {
330 return this;
331 }
332 }
333 }