1
17 package org.apache.catalina.connector;
18
19 import java.io.IOException;
20 import java.io.PrintWriter;
21 import java.security.AccessController;
22 import java.security.PrivilegedAction;
23 import java.security.PrivilegedActionException;
24 import java.security.PrivilegedExceptionAction;
25 import java.util.Collection;
26 import java.util.Locale;
27 import java.util.Map;
28 import java.util.function.Supplier;
29
30 import javax.servlet.ServletOutputStream;
31 import javax.servlet.http.Cookie;
32 import javax.servlet.http.HttpServletResponse;
33
34 import org.apache.catalina.Globals;
35 import org.apache.catalina.security.SecurityUtil;
36 import org.apache.tomcat.util.res.StringManager;
37
38
44 @SuppressWarnings("deprecation")
45 public class ResponseFacade implements HttpServletResponse {
46
47
48
49 private final class SetContentTypePrivilegedAction
50 implements PrivilegedAction<Void> {
51
52 private final String contentType;
53
54 public SetContentTypePrivilegedAction(String contentType){
55 this.contentType = contentType;
56 }
57
58 @Override
59 public Void run() {
60 response.setContentType(contentType);
61 return null;
62 }
63 }
64
65 private final class DateHeaderPrivilegedAction
66 implements PrivilegedAction<Void> {
67
68 private final String name;
69 private final long value;
70 private final boolean add;
71
72 DateHeaderPrivilegedAction(String name, long value, boolean add) {
73 this.name = name;
74 this.value = value;
75 this.add = add;
76 }
77
78 @Override
79 public Void run() {
80 if(add) {
81 response.addDateHeader(name, value);
82 } else {
83 response.setDateHeader(name, value);
84 }
85 return null;
86 }
87 }
88
89 private static class FlushBufferPrivilegedAction implements PrivilegedExceptionAction<Void> {
90
91 private final Response response;
92
93 public FlushBufferPrivilegedAction(Response response) {
94 this.response = response;
95 }
96
97 @Override
98 public Void run() throws IOException {
99 response.setAppCommitted(true);
100 response.flushBuffer();
101 return null;
102 }
103 }
104
105
106
107
108
113 public ResponseFacade(Response response) {
114
115 this.response = response;
116 }
117
118
119
120
121
122
125 protected static final StringManager sm = StringManager.getManager(ResponseFacade.class);
126
127
128
131 protected Response response = null;
132
133
134
135
136
137
140 public void clear() {
141 response = null;
142 }
143
144
145
148 @Override
149 protected Object clone()
150 throws CloneNotSupportedException {
151 throw new CloneNotSupportedException();
152 }
153
154
155 public void finish() {
156
157 if (response == null) {
158 throw new IllegalStateException(
159 sm.getString("responseFacade.nullResponse"));
160 }
161
162 response.setSuspended(true);
163 }
164
165
166 public boolean isFinished() {
167
168 if (response == null) {
169 throw new IllegalStateException(
170 sm.getString("responseFacade.nullResponse"));
171 }
172
173 return response.isSuspended();
174 }
175
176
177 public long getContentWritten() {
178
179 if (response == null) {
180 throw new IllegalStateException(
181 sm.getString("responseFacade.nullResponse"));
182 }
183
184 return response.getContentWritten();
185 }
186
187
188
189
190 @Override
191 public String getCharacterEncoding() {
192
193 if (response == null) {
194 throw new IllegalStateException(
195 sm.getString("responseFacade.nullResponse"));
196 }
197
198 return response.getCharacterEncoding();
199 }
200
201
202 @Override
203 public ServletOutputStream getOutputStream()
204 throws IOException {
205
206
207
208
209
210 ServletOutputStream sos = response.getOutputStream();
211 if (isFinished()) {
212 response.setSuspended(true);
213 }
214 return sos;
215
216 }
217
218
219 @Override
220 public PrintWriter getWriter()
221 throws IOException {
222
223
224
225
226
227 PrintWriter writer = response.getWriter();
228 if (isFinished()) {
229 response.setSuspended(true);
230 }
231 return writer;
232
233 }
234
235
236 @Override
237 public void setContentLength(int len) {
238 if (isCommitted()) {
239 return;
240 }
241 response.setContentLength(len);
242 }
243
244
245 @Override
246 public void setContentLengthLong(long length) {
247 if (isCommitted()) {
248 return;
249 }
250 response.setContentLengthLong(length);
251 }
252
253
254 @Override
255 public void setContentType(String type) {
256
257 if (isCommitted()) {
258 return;
259 }
260
261 if (SecurityUtil.isPackageProtectionEnabled()){
262 AccessController.doPrivileged(new SetContentTypePrivilegedAction(type));
263 } else {
264 response.setContentType(type);
265 }
266 }
267
268
269 @Override
270 public void setBufferSize(int size) {
271
272 if (isCommitted()) {
273 throw new IllegalStateException
274 (sm.getString("coyoteResponse.setBufferSize.ise"));
275 }
276
277 response.setBufferSize(size);
278
279 }
280
281
282 @Override
283 public int getBufferSize() {
284
285 if (response == null) {
286 throw new IllegalStateException(
287 sm.getString("responseFacade.nullResponse"));
288 }
289
290 return response.getBufferSize();
291 }
292
293
294 @Override
295 public void flushBuffer() throws IOException {
296
297 if (isFinished()) {
298 return;
299 }
300
301 if (SecurityUtil.isPackageProtectionEnabled()) {
302 try{
303 AccessController.doPrivileged(new FlushBufferPrivilegedAction(response));
304 } catch(PrivilegedActionException e) {
305 Exception ex = e.getException();
306 if (ex instanceof IOException) {
307 throw (IOException)ex;
308 }
309 }
310 } else {
311 response.setAppCommitted(true);
312 response.flushBuffer();
313 }
314 }
315
316
317 @Override
318 public void resetBuffer() {
319
320 if (isCommitted()) {
321 throw new IllegalStateException
322 (sm.getString("coyoteResponse.resetBuffer.ise"));
323 }
324
325 response.resetBuffer();
326
327 }
328
329
330 @Override
331 public boolean isCommitted() {
332
333 if (response == null) {
334 throw new IllegalStateException(
335 sm.getString("responseFacade.nullResponse"));
336 }
337
338 return response.isAppCommitted();
339 }
340
341
342 @Override
343 public void reset() {
344
345 if (isCommitted()) {
346 throw new IllegalStateException
347 (sm.getString("coyoteResponse.reset.ise"));
348 }
349
350 response.reset();
351
352 }
353
354
355 @Override
356 public void setLocale(Locale loc) {
357
358 if (isCommitted()) {
359 return;
360 }
361
362 response.setLocale(loc);
363 }
364
365
366 @Override
367 public Locale getLocale() {
368
369 if (response == null) {
370 throw new IllegalStateException(
371 sm.getString("responseFacade.nullResponse"));
372 }
373
374 return response.getLocale();
375 }
376
377
378 @Override
379 public void addCookie(Cookie cookie) {
380
381 if (isCommitted()) {
382 return;
383 }
384
385 response.addCookie(cookie);
386
387 }
388
389
390 @Override
391 public boolean containsHeader(String name) {
392
393 if (response == null) {
394 throw new IllegalStateException(
395 sm.getString("responseFacade.nullResponse"));
396 }
397
398 return response.containsHeader(name);
399 }
400
401
402 @Override
403 public String encodeURL(String url) {
404
405 if (response == null) {
406 throw new IllegalStateException(
407 sm.getString("responseFacade.nullResponse"));
408 }
409
410 return response.encodeURL(url);
411 }
412
413
414 @Override
415 public String encodeRedirectURL(String url) {
416
417 if (response == null) {
418 throw new IllegalStateException(
419 sm.getString("responseFacade.nullResponse"));
420 }
421
422 return response.encodeRedirectURL(url);
423 }
424
425
426 @Override
427 public String encodeUrl(String url) {
428
429 if (response == null) {
430 throw new IllegalStateException(
431 sm.getString("responseFacade.nullResponse"));
432 }
433
434 return response.encodeURL(url);
435 }
436
437
438 @Override
439 public String encodeRedirectUrl(String url) {
440
441 if (response == null) {
442 throw new IllegalStateException(
443 sm.getString("responseFacade.nullResponse"));
444 }
445
446 return response.encodeRedirectURL(url);
447 }
448
449
450 @Override
451 public void sendError(int sc, String msg)
452 throws IOException {
453
454 if (isCommitted()) {
455 throw new IllegalStateException
456 (sm.getString("coyoteResponse.sendError.ise"));
457 }
458
459 response.setAppCommitted(true);
460
461 response.sendError(sc, msg);
462
463 }
464
465
466 @Override
467 public void sendError(int sc)
468 throws IOException {
469
470 if (isCommitted()) {
471 throw new IllegalStateException
472 (sm.getString("coyoteResponse.sendError.ise"));
473 }
474
475 response.setAppCommitted(true);
476
477 response.sendError(sc);
478
479 }
480
481
482 @Override
483 public void sendRedirect(String location)
484 throws IOException {
485
486 if (isCommitted()) {
487 throw new IllegalStateException
488 (sm.getString("coyoteResponse.sendRedirect.ise"));
489 }
490
491 response.setAppCommitted(true);
492
493 response.sendRedirect(location);
494
495 }
496
497
498 @Override
499 public void setDateHeader(String name, long date) {
500
501 if (isCommitted()) {
502 return;
503 }
504
505 if(Globals.IS_SECURITY_ENABLED) {
506 AccessController.doPrivileged(new DateHeaderPrivilegedAction
507 (name, date, false));
508 } else {
509 response.setDateHeader(name, date);
510 }
511
512 }
513
514
515 @Override
516 public void addDateHeader(String name, long date) {
517
518 if (isCommitted()) {
519 return;
520 }
521
522 if(Globals.IS_SECURITY_ENABLED) {
523 AccessController.doPrivileged(new DateHeaderPrivilegedAction
524 (name, date, true));
525 } else {
526 response.addDateHeader(name, date);
527 }
528
529 }
530
531
532 @Override
533 public void setHeader(String name, String value) {
534
535 if (isCommitted()) {
536 return;
537 }
538
539 response.setHeader(name, value);
540
541 }
542
543
544 @Override
545 public void addHeader(String name, String value) {
546
547 if (isCommitted()) {
548 return;
549 }
550
551 response.addHeader(name, value);
552
553 }
554
555
556 @Override
557 public void setIntHeader(String name, int value) {
558
559 if (isCommitted()) {
560 return;
561 }
562
563 response.setIntHeader(name, value);
564
565 }
566
567
568 @Override
569 public void addIntHeader(String name, int value) {
570
571 if (isCommitted()) {
572 return;
573 }
574
575 response.addIntHeader(name, value);
576
577 }
578
579
580 @Override
581 public void setStatus(int sc) {
582
583 if (isCommitted()) {
584 return;
585 }
586
587 response.setStatus(sc);
588
589 }
590
591
592 @Override
593 public void setStatus(int sc, String sm) {
594
595 if (isCommitted()) {
596 return;
597 }
598
599 response.setStatus(sc, sm);
600 }
601
602
603 @Override
604 public String getContentType() {
605
606 if (response == null) {
607 throw new IllegalStateException(
608 sm.getString("responseFacade.nullResponse"));
609 }
610
611 return response.getContentType();
612 }
613
614
615 @Override
616 public void setCharacterEncoding(String arg0) {
617
618 if (response == null) {
619 throw new IllegalStateException(
620 sm.getString("responseFacade.nullResponse"));
621 }
622
623 response.setCharacterEncoding(arg0);
624 }
625
626 @Override
627 public int getStatus() {
628 return response.getStatus();
629 }
630
631 @Override
632 public String getHeader(String name) {
633 return response.getHeader(name);
634 }
635
636 @Override
637 public Collection<String> getHeaderNames() {
638 return response.getHeaderNames();
639 }
640
641 @Override
642 public Collection<String> getHeaders(String name) {
643 return response.getHeaders(name);
644 }
645
646
647 @Override
648 public void setTrailerFields(Supplier<Map<String, String>> supplier) {
649 response.setTrailerFields(supplier);
650 }
651
652
653 @Override
654 public Supplier<Map<String, String>> getTrailerFields() {
655 return response.getTrailerFields();
656 }
657 }
658