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<Header>();
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<Header>();
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<Header>();
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<Header>();
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
198 @Deprecated
199 public void finishResponse() throws IOException {
200 finishResponse(false);
201 }
202
203 public void finishResponse(boolean reapplyMetaData) throws IOException {
204 HttpServletResponse response = (HttpServletResponse)getResponse();
205
206 if (reapplyMetaData) {
207 finishResponse(_metaData, response);
208 }
209
210 _committed = true;
211 }
212
213 @Override
214 @SuppressWarnings("unused")
215 public void flushBuffer() throws IOException {
216 _committed = true;
217 }
218
219 @Override
220 public int getBufferSize() {
221 return _metaData._bufferSize;
222 }
223
224 @Override
225 public String getCharacterEncoding() {
226
227
228
229
230
231
232 if (_metaData._charsetName == null) {
233 return StringPool.DEFAULT_CHARSET_NAME;
234 }
235
236 return _metaData._charsetName;
237 }
238
239 @Override
240 public String getContentType() {
241 String contentType = _metaData._contentType;
242
243 if ((contentType != null) && (_metaData._charsetName != null)) {
244 contentType = contentType.concat("; charset=").concat(
245 _metaData._charsetName);
246 }
247
248 return contentType;
249 }
250
251
257 @Override
258 public String getHeader(String name) {
259 Set<Header> values = _metaData._headers.get(name);
260
261 if (values == null) {
262 return null;
263 }
264
265 Header header = values.iterator().next();
266
267 return header.toString();
268 }
269
270 @Override
271 public Collection<String> getHeaderNames() {
272 return _metaData._headers.keySet();
273 }
274
275 public Map<String, Set<Header>> getHeaders() {
276 return _metaData._headers;
277 }
278
279
285 @Override
286 public Collection<String> getHeaders(String name) {
287 Set<Header> values = _metaData._headers.get(name);
288
289 if (values == null) {
290 return Collections.emptyList();
291 }
292
293 List<String> stringValues = new ArrayList<String>();
294
295 for (Header header : values) {
296 stringValues.add(header.toString());
297 }
298
299 return stringValues;
300 }
301
302 @Override
303 public Locale getLocale() {
304 return _metaData._locale;
305 }
306
307 public MetaData getMetaData() {
308 return _metaData;
309 }
310
311 @Override
312 public ServletOutputStream getOutputStream() throws IOException {
313 calledGetOutputStream = true;
314
315 return super.getOutputStream();
316 }
317
318 @Override
319 public int getStatus() {
320 return _metaData._status;
321 }
322
323 @Override
324 public PrintWriter getWriter() throws IOException {
325 calledGetWriter = true;
326
327 return super.getWriter();
328 }
329
330 @Override
331 public boolean isCommitted() {
332 ServletResponse servletResponse = getResponse();
333
334 return _committed || servletResponse.isCommitted();
335 }
336
337 @Override
338 public void reset() {
339 if (isCommitted()) {
340 throw new IllegalStateException("Reset after commit");
341 }
342
343
344
345
346 _metaData._charsetName = null;
347 _metaData._contentLength = -1;
348 _metaData._contentType = null;
349 _metaData._headers.clear();
350 _metaData._locale = null;
351 _metaData._status = SC_OK;
352 _metaData._statusMessage = null;
353
354
355
356
357 resetBuffer();
358
359 super.reset();
360 }
361
362 @Override
363 public void resetBuffer() {
364 if (isCommitted()) {
365 throw new IllegalStateException("Reset buffer after commit");
366 }
367
368 resetBuffer(false);
369 }
370
371 @Override
372 public void sendError(int status) throws IOException {
373 if (isCommitted()) {
374 throw new IllegalStateException("Send error after commit");
375 }
376
377 _metaData._error = true;
378 _metaData._status = status;
379
380 resetBuffer();
381
382 _committed = true;
383
384 super.sendError(status);
385 }
386
387 @Override
388 public void sendError(int status, String errorMessage) throws IOException {
389 if (isCommitted()) {
390 throw new IllegalStateException("Send error after commit");
391 }
392
393 _metaData._error = true;
394 _metaData._errorMessage = errorMessage;
395 _metaData._status = status;
396
397 resetBuffer();
398
399 _committed = true;
400
401 super.sendError(status, errorMessage);
402 }
403
404 @Override
405 public void sendRedirect(String location) throws IOException {
406 if (isCommitted()) {
407 throw new IllegalStateException("Send redirect after commit");
408 }
409
410 resetBuffer(true);
411
412 setStatus(SC_FOUND);
413
414 _metaData._location = location;
415
416 _committed = true;
417
418 super.sendRedirect(location);
419 }
420
421 @Override
422 public void setBufferSize(int bufferSize) {
423 if (isCommitted()) {
424 throw new IllegalStateException("Set buffer size after commit");
425 }
426
427 _metaData._bufferSize = bufferSize;
428
429 super.setBufferSize(bufferSize);
430 }
431
432 @Override
433 public void setCharacterEncoding(String charsetName) {
434 if (isCommitted()) {
435 return;
436 }
437
438 if (calledGetWriter) {
439 return;
440 }
441
442 if (charsetName == null) {
443 return;
444 }
445
446 _metaData._charsetName = charsetName;
447
448 super.setCharacterEncoding(charsetName);
449 }
450
451 @Override
452 public void setContentLength(int contentLength) {
453 if (isCommitted()) {
454 return;
455 }
456
457 _metaData._contentLength = contentLength;
458
459 super.setContentLength(contentLength);
460 }
461
462 @Override
463 public void setContentType(String contentType) {
464 if (isCommitted()) {
465 return;
466 }
467
468 if (contentType == null) {
469 return;
470 }
471
472 int index = contentType.indexOf(CharPool.SEMICOLON);
473
474 if (index != -1) {
475 String firstPart = contentType.substring(0, index);
476
477 _metaData._contentType = firstPart.trim();
478
479 index = contentType.indexOf("charset=");
480
481 if (index != -1) {
482 String charsetName = contentType.substring(index + 8);
483
484 charsetName = charsetName.trim();
485
486 setCharacterEncoding(charsetName);
487 }
488 else {
489 _metaData._charsetName = null;
490 }
491 }
492 else {
493 _metaData._contentType = contentType;
494
495 _metaData._charsetName = null;
496 }
497
498 super.setContentType(contentType);
499 }
500
501 @Override
502 public void setDateHeader(String name, long value) {
503 Set<Header> values = new HashSet<Header>();
504
505 _metaData._headers.put(name, values);
506
507 Header header = new Header(value);
508
509 values.add(header);
510
511 super.setDateHeader(name, value);
512 }
513
514 @Override
515 public void setHeader(String name, String value) {
516 if (name.equals(HttpHeaders.CONTENT_TYPE)) {
517 setContentType(value);
518
519 return;
520 }
521
522 Set<Header> values = new HashSet<Header>();
523
524 _metaData._headers.put(name, values);
525
526 Header header = new Header(value);
527
528 values.add(header);
529
530 super.setHeader(name, value);
531 }
532
533 @Override
534 public void setIntHeader(String name, int value) {
535 Set<Header> values = new HashSet<Header>();
536
537 _metaData._headers.put(name, values);
538
539 Header header = new Header(value);
540
541 values.add(header);
542
543 super.setIntHeader(name, value);
544 }
545
546 @Override
547 public void setLocale(Locale locale) {
548 if (isCommitted()) {
549 return;
550 }
551
552 _metaData._locale = locale;
553
554 super.setLocale(locale);
555 }
556
557 @Override
558 public void setStatus(int status) {
559 if (isCommitted()) {
560 return;
561 }
562
563 _metaData._status = status;
564
565 super.setStatus(status);
566 }
567
568 @Override
569 @SuppressWarnings("deprecation")
570 public void setStatus(int status, String statusMessage) {
571 if (isCommitted()) {
572 return;
573 }
574
575 _metaData._status = status;
576 _metaData._statusMessage = statusMessage;
577
578 super.setStatus(status, statusMessage);
579 }
580
581 @Override
582 public String toString() {
583 StringBundler sb = new StringBundler(23);
584
585 sb.append("{bufferSize=");
586 sb.append(_metaData._bufferSize);
587 sb.append(", charsetName=");
588 sb.append(_metaData._charsetName);
589 sb.append(", committed=");
590 sb.append(_committed);
591 sb.append(", contentLength=");
592 sb.append(_metaData._contentLength);
593 sb.append(", contentType=");
594 sb.append(_metaData._contentType);
595 sb.append(", error=");
596 sb.append(_metaData._error);
597 sb.append(", errorMessage=");
598 sb.append(_metaData._errorMessage);
599 sb.append(", headers=");
600 sb.append(_metaData._headers);
601 sb.append(", location=");
602 sb.append(_metaData._location);
603 sb.append(", locale=");
604 sb.append(_metaData._locale);
605 sb.append(", status=");
606 sb.append(_metaData._status);
607 sb.append("}");
608
609 return sb.toString();
610 }
611
612 public static class MetaData implements Serializable {
613
614 private int _bufferSize;
615 private String _charsetName;
616 private int _contentLength = -1;
617 private String _contentType;
618 private boolean _error;
619 private String _errorMessage;
620 private Map<String, Set<Header>> _headers =
621 new HashMap<String, Set<Header>>();
622 private Locale _locale;
623 private String _location;
624 private int _status = SC_OK;
625 private String _statusMessage;
626
627 }
628
629 protected static void resetThrough(HttpServletResponse response) {
630 if (response instanceof MetaInfoCacheServletResponse) {
631 MetaInfoCacheServletResponse metaInfoCacheServletResponse =
632 (MetaInfoCacheServletResponse)response;
633
634 resetThrough(
635 (HttpServletResponse)
636 metaInfoCacheServletResponse.getResponse());
637 }
638 else {
639 response.reset();
640 }
641 }
642
643
650 protected void resetBuffer(boolean nullOutReferences) {
651 super.resetBuffer();
652 }
653
654 protected boolean calledGetOutputStream;
655 protected boolean calledGetWriter;
656
657 private boolean _committed;
658 private MetaData _metaData = new MetaData();
659
660 }