001
014
015 package com.liferay.portal.kernel.servlet;
016
017 import com.liferay.portal.kernel.util.CharPool;
018 import com.liferay.portal.kernel.util.StringBundler;
019 import com.liferay.portal.kernel.util.StringPool;
020
021 import java.io.IOException;
022 import java.io.PrintWriter;
023 import java.io.Serializable;
024
025 import java.util.ArrayList;
026 import java.util.Collection;
027 import java.util.Collections;
028 import java.util.HashMap;
029 import java.util.HashSet;
030 import java.util.List;
031 import java.util.Locale;
032 import java.util.Map;
033 import java.util.Set;
034
035 import javax.servlet.ServletOutputStream;
036 import javax.servlet.ServletResponse;
037 import javax.servlet.http.Cookie;
038 import javax.servlet.http.HttpServletResponse;
039 import javax.servlet.http.HttpServletResponseWrapper;
040
041
044 public class MetaInfoCacheServletResponse extends HttpServletResponseWrapper {
045
046 @SuppressWarnings("deprecation")
047 public static void finishResponse(
048 MetaData metaInfoDataBag, HttpServletResponse response)
049 throws IOException {
050
051 if (response.isCommitted()) {
052 return;
053 }
054
055 resetThrough(response);
056
057 for (Map.Entry<String, Set<Header>> entry :
058 metaInfoDataBag._headers.entrySet()) {
059
060 String key = entry.getKey();
061
062 boolean first = true;
063
064 for (Header header : entry.getValue()) {
065 if (first) {
066 header.setToResponse(key, response);
067
068 first = false;
069 }
070 else {
071 header.addToResponse(key, response);
072 }
073 }
074 }
075
076 if (metaInfoDataBag._location != null) {
077 response.sendRedirect(metaInfoDataBag._location);
078 }
079 else if (metaInfoDataBag._error) {
080 response.sendError(
081 metaInfoDataBag._status, metaInfoDataBag._errorMessage);
082 }
083 else {
084 if (metaInfoDataBag._charsetName != null) {
085 response.setCharacterEncoding(metaInfoDataBag._charsetName);
086 }
087
088 if (metaInfoDataBag._contentLength != -1) {
089 response.setContentLength(metaInfoDataBag._contentLength);
090 }
091
092 if (metaInfoDataBag._contentType != null) {
093 response.setContentType(metaInfoDataBag._contentType);
094 }
095
096 if (metaInfoDataBag._locale != null) {
097 response.setLocale(metaInfoDataBag._locale);
098 }
099
100 if (metaInfoDataBag._status != SC_OK) {
101 response.setStatus(
102 metaInfoDataBag._status, metaInfoDataBag._statusMessage);
103 }
104 }
105 }
106
107 public MetaInfoCacheServletResponse(HttpServletResponse response) {
108 super(response);
109 }
110
111 @Override
112 public void addCookie(Cookie cookie) {
113
114
115
116
117
118 Set<Header> values = _metaData._headers.get(HttpHeaders.SET_COOKIE);
119
120 if (values == null) {
121 values = new HashSet<>();
122
123 _metaData._headers.put(HttpHeaders.SET_COOKIE, values);
124 }
125
126 Header header = new Header(cookie);
127
128 values.add(header);
129
130 super.addCookie(cookie);
131 }
132
133 @Override
134 public void addDateHeader(String name, long value) {
135 Set<Header> values = _metaData._headers.get(name);
136
137 if (values == null) {
138 values = new HashSet<>();
139
140 _metaData._headers.put(name, values);
141 }
142
143 Header header = new Header(value);
144
145 values.add(header);
146
147 super.addDateHeader(name, value);
148 }
149
150 @Override
151 public void addHeader(String name, String value) {
152 if (name.equals(HttpHeaders.CONTENT_TYPE)) {
153 setContentType(value);
154
155 return;
156 }
157
158 Set<Header> values = _metaData._headers.get(name);
159
160 if (values == null) {
161 values = new HashSet<>();
162
163 _metaData._headers.put(name, values);
164 }
165
166 Header header = new Header(value);
167
168 values.add(header);
169
170 super.addHeader(name, value);
171 }
172
173 @Override
174 public void addIntHeader(String name, int value) {
175 Set<Header> values = _metaData._headers.get(name);
176
177 if (values == null) {
178 values = new HashSet<>();
179
180 _metaData._headers.put(name, values);
181 }
182
183 Header header = new Header(value);
184
185 values.add(header);
186
187 super.addIntHeader(name, value);
188 }
189
190 @Override
191 public boolean containsHeader(String name) {
192 return _metaData._headers.containsKey(name);
193 }
194
195 public void finishResponse(boolean reapplyMetaData) throws IOException {
196 HttpServletResponse response = (HttpServletResponse)getResponse();
197
198 if (reapplyMetaData) {
199 finishResponse(_metaData, response);
200 }
201
202 _committed = true;
203 }
204
205 @Override
206 @SuppressWarnings("unused")
207 public void flushBuffer() throws IOException {
208 _committed = true;
209 }
210
211 @Override
212 public int getBufferSize() {
213 return _metaData._bufferSize;
214 }
215
216 @Override
217 public String getCharacterEncoding() {
218
219
220
221
222
223
224 if (_metaData._charsetName == null) {
225 return StringPool.DEFAULT_CHARSET_NAME;
226 }
227
228 return _metaData._charsetName;
229 }
230
231 @Override
232 public String getContentType() {
233 String contentType = _metaData._contentType;
234
235 if ((contentType != null) && (_metaData._charsetName != null)) {
236 contentType = contentType.concat("; charset=").concat(
237 _metaData._charsetName);
238 }
239
240 return contentType;
241 }
242
243
249 @Override
250 public String getHeader(String name) {
251 Set<Header> values = _metaData._headers.get(name);
252
253 if (values == null) {
254 return null;
255 }
256
257 Header header = values.iterator().next();
258
259 return header.toString();
260 }
261
262 @Override
263 public Collection<String> getHeaderNames() {
264 return _metaData._headers.keySet();
265 }
266
267 public Map<String, Set<Header>> getHeaders() {
268 return _metaData._headers;
269 }
270
271
277 @Override
278 public Collection<String> getHeaders(String name) {
279 Set<Header> values = _metaData._headers.get(name);
280
281 if (values == null) {
282 return Collections.emptyList();
283 }
284
285 List<String> stringValues = new ArrayList<>();
286
287 for (Header header : values) {
288 stringValues.add(header.toString());
289 }
290
291 return stringValues;
292 }
293
294 @Override
295 public Locale getLocale() {
296 return _metaData._locale;
297 }
298
299 public MetaData getMetaData() {
300 return _metaData;
301 }
302
303 @Override
304 public ServletOutputStream getOutputStream() throws IOException {
305 calledGetOutputStream = true;
306
307 return super.getOutputStream();
308 }
309
310 @Override
311 public int getStatus() {
312 return _metaData._status;
313 }
314
315 @Override
316 public PrintWriter getWriter() throws IOException {
317 calledGetWriter = true;
318
319 return super.getWriter();
320 }
321
322 @Override
323 public boolean isCommitted() {
324 ServletResponse servletResponse = getResponse();
325
326 return _committed || servletResponse.isCommitted();
327 }
328
329 @Override
330 public void reset() {
331 if (isCommitted()) {
332 throw new IllegalStateException("Reset after commit");
333 }
334
335
336
337
338 _metaData._charsetName = null;
339 _metaData._contentLength = -1;
340 _metaData._contentType = null;
341 _metaData._headers.clear();
342 _metaData._locale = null;
343 _metaData._status = SC_OK;
344 _metaData._statusMessage = null;
345
346
347
348
349 resetBuffer();
350
351 super.reset();
352 }
353
354 @Override
355 public void resetBuffer() {
356 if (isCommitted()) {
357 throw new IllegalStateException("Reset buffer after commit");
358 }
359
360 resetBuffer(false);
361 }
362
363 @Override
364 public void sendError(int status) throws IOException {
365 if (isCommitted()) {
366 throw new IllegalStateException("Send error after commit");
367 }
368
369 _metaData._error = true;
370 _metaData._status = status;
371
372 resetBuffer();
373
374 _committed = true;
375
376 super.sendError(status);
377 }
378
379 @Override
380 public void sendError(int status, String errorMessage) throws IOException {
381 if (isCommitted()) {
382 throw new IllegalStateException("Send error after commit");
383 }
384
385 _metaData._error = true;
386 _metaData._errorMessage = errorMessage;
387 _metaData._status = status;
388
389 resetBuffer();
390
391 _committed = true;
392
393 super.sendError(status, errorMessage);
394 }
395
396 @Override
397 public void sendRedirect(String location) throws IOException {
398 if (isCommitted()) {
399 throw new IllegalStateException("Send redirect after commit");
400 }
401
402 resetBuffer(true);
403
404 setStatus(SC_FOUND);
405
406 _metaData._location = location;
407
408 _committed = true;
409
410 super.sendRedirect(location);
411 }
412
413 @Override
414 public void setBufferSize(int bufferSize) {
415 if (isCommitted()) {
416 throw new IllegalStateException("Set buffer size after commit");
417 }
418
419 _metaData._bufferSize = bufferSize;
420
421 super.setBufferSize(bufferSize);
422 }
423
424 @Override
425 public void setCharacterEncoding(String charsetName) {
426 if (isCommitted()) {
427 return;
428 }
429
430 if (calledGetWriter) {
431 return;
432 }
433
434 if (charsetName == null) {
435 return;
436 }
437
438 _metaData._charsetName = charsetName;
439
440 super.setCharacterEncoding(charsetName);
441 }
442
443 @Override
444 public void setContentLength(int contentLength) {
445 if (isCommitted()) {
446 return;
447 }
448
449 _metaData._contentLength = contentLength;
450
451 super.setContentLength(contentLength);
452 }
453
454 @Override
455 public void setContentType(String contentType) {
456 if (isCommitted()) {
457 return;
458 }
459
460 if (contentType == null) {
461 return;
462 }
463
464 int index = contentType.indexOf(CharPool.SEMICOLON);
465
466 if (index != -1) {
467 String firstPart = contentType.substring(0, index);
468
469 _metaData._contentType = firstPart.trim();
470
471 index = contentType.indexOf("charset=");
472
473 if (index != -1) {
474 String charsetName = contentType.substring(index + 8);
475
476 charsetName = charsetName.trim();
477
478 setCharacterEncoding(charsetName);
479 }
480 else {
481 _metaData._charsetName = null;
482 }
483 }
484 else {
485 _metaData._contentType = contentType;
486
487 _metaData._charsetName = null;
488 }
489
490 super.setContentType(contentType);
491 }
492
493 @Override
494 public void setDateHeader(String name, long value) {
495 Set<Header> values = new HashSet<>();
496
497 _metaData._headers.put(name, values);
498
499 Header header = new Header(value);
500
501 values.add(header);
502
503 super.setDateHeader(name, value);
504 }
505
506 @Override
507 public void setHeader(String name, String value) {
508 if (name.equals(HttpHeaders.CONTENT_TYPE)) {
509 setContentType(value);
510
511 return;
512 }
513
514 Set<Header> values = new HashSet<>();
515
516 _metaData._headers.put(name, values);
517
518 Header header = new Header(value);
519
520 values.add(header);
521
522 super.setHeader(name, value);
523 }
524
525 @Override
526 public void setIntHeader(String name, int value) {
527 Set<Header> values = new HashSet<>();
528
529 _metaData._headers.put(name, values);
530
531 Header header = new Header(value);
532
533 values.add(header);
534
535 super.setIntHeader(name, value);
536 }
537
538 @Override
539 public void setLocale(Locale locale) {
540 if (isCommitted()) {
541 return;
542 }
543
544 _metaData._locale = locale;
545
546 super.setLocale(locale);
547 }
548
549 @Override
550 public void setStatus(int status) {
551 if (isCommitted()) {
552 return;
553 }
554
555 _metaData._status = status;
556
557 super.setStatus(status);
558 }
559
560 @Override
561 @SuppressWarnings("deprecation")
562 public void setStatus(int status, String statusMessage) {
563 if (isCommitted()) {
564 return;
565 }
566
567 _metaData._status = status;
568 _metaData._statusMessage = statusMessage;
569
570 super.setStatus(status, statusMessage);
571 }
572
573 @Override
574 public String toString() {
575 StringBundler sb = new StringBundler(23);
576
577 sb.append("{bufferSize=");
578 sb.append(_metaData._bufferSize);
579 sb.append(", charsetName=");
580 sb.append(_metaData._charsetName);
581 sb.append(", committed=");
582 sb.append(_committed);
583 sb.append(", contentLength=");
584 sb.append(_metaData._contentLength);
585 sb.append(", contentType=");
586 sb.append(_metaData._contentType);
587 sb.append(", error=");
588 sb.append(_metaData._error);
589 sb.append(", errorMessage=");
590 sb.append(_metaData._errorMessage);
591 sb.append(", headers=");
592 sb.append(_metaData._headers);
593 sb.append(", location=");
594 sb.append(_metaData._location);
595 sb.append(", locale=");
596 sb.append(_metaData._locale);
597 sb.append(", status=");
598 sb.append(_metaData._status);
599 sb.append("}");
600
601 return sb.toString();
602 }
603
604 public static class MetaData implements Serializable {
605
606 private int _bufferSize;
607 private String _charsetName;
608 private int _contentLength = -1;
609 private String _contentType;
610 private boolean _error;
611 private String _errorMessage;
612 private final Map<String, Set<Header>> _headers = new HashMap<>();
613 private Locale _locale;
614 private String _location;
615 private int _status = SC_OK;
616 private String _statusMessage;
617
618 }
619
620 protected static void resetThrough(HttpServletResponse response) {
621 if (response instanceof MetaInfoCacheServletResponse) {
622 MetaInfoCacheServletResponse metaInfoCacheServletResponse =
623 (MetaInfoCacheServletResponse)response;
624
625 resetThrough(
626 (HttpServletResponse)
627 metaInfoCacheServletResponse.getResponse());
628 }
629 else {
630 response.reset();
631 }
632 }
633
634
641 protected void resetBuffer(boolean nullOutReferences) {
642 super.resetBuffer();
643 }
644
645 protected boolean calledGetOutputStream;
646 protected boolean calledGetWriter;
647
648 private boolean _committed;
649 private final MetaData _metaData = new MetaData();
650
651 }