001: /*
002: * Copyright 2002-2006 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.directwebremoting.util;
018:
019: import java.io.ByteArrayOutputStream;
020: import java.io.IOException;
021: import java.io.OutputStreamWriter;
022: import java.io.PrintWriter;
023: import java.io.UnsupportedEncodingException;
024: import java.io.Writer;
025: import java.util.ArrayList;
026: import java.util.Collections;
027: import java.util.HashMap;
028: import java.util.List;
029: import java.util.Locale;
030: import java.util.Map;
031: import java.util.Set;
032:
033: import javax.servlet.ServletOutputStream;
034: import javax.servlet.http.Cookie;
035: import javax.servlet.http.HttpServletResponse;
036:
037: /**
038: * Mock implementation of the HttpServletResponse interface.
039: * @author Rod Johnson
040: * @author Juergen Hoeller
041: * @author Joe Walker [joe at getahead dot ltd dot uk]
042: */
043: public class FakeHttpServletResponse implements HttpServletResponse {
044: /* (non-Javadoc)
045: * @see javax.servlet.ServletResponse#setCharacterEncoding(java.lang.String)
046: */
047: public void setCharacterEncoding(String characterEncoding) {
048: this .characterEncoding = characterEncoding;
049: }
050:
051: /* (non-Javadoc)
052: * @see javax.servlet.ServletResponse#getCharacterEncoding()
053: */
054: public String getCharacterEncoding() {
055: return characterEncoding;
056: }
057:
058: /* (non-Javadoc)
059: * @see javax.servlet.ServletResponse#getOutputStream()
060: */
061: public ServletOutputStream getOutputStream() {
062: return outputStream;
063: }
064:
065: /* (non-Javadoc)
066: * @see javax.servlet.ServletResponse#getWriter()
067: */
068: public PrintWriter getWriter() throws UnsupportedEncodingException {
069: if (writer == null) {
070: Writer targetWriter = (characterEncoding != null ? new OutputStreamWriter(
071: content, characterEncoding)
072: : new OutputStreamWriter(content));
073: writer = new PrintWriter(targetWriter);
074: }
075:
076: return writer;
077: }
078:
079: /* (non-Javadoc)
080: * @see javax.servlet.ServletResponse#flushBuffer()
081: */
082: public void flushBuffer() {
083: if (writer != null) {
084: writer.flush();
085: }
086:
087: if (outputStream != null) {
088: try {
089: outputStream.flush();
090: } catch (IOException ex) {
091: throw new IllegalStateException(
092: "Could not flush OutputStream: "
093: + ex.getMessage());
094: }
095: }
096:
097: committed = true;
098: }
099:
100: /* (non-Javadoc)
101: * @see javax.servlet.http.HttpServletResponse#sendError(int, java.lang.String)
102: */
103: public void sendError(int newStatus, String newErrorMessage)
104: throws IOException {
105: if (committed) {
106: throw new IllegalStateException(
107: "Cannot set error status - response is already committed");
108: }
109:
110: status = newStatus;
111: errorMessage = newErrorMessage;
112: committed = true;
113: }
114:
115: /* (non-Javadoc)
116: * @see javax.servlet.http.HttpServletResponse#sendError(int)
117: */
118: public void sendError(int newStatus) throws IOException {
119: if (committed) {
120: throw new IllegalStateException(
121: "Cannot set error status - response is already committed");
122: }
123:
124: status = newStatus;
125: committed = true;
126: }
127:
128: /**
129: * Accessor for any error messages set using {@link #sendError(int)} or
130: * {@link #sendError(int, String)}
131: * @return The current error message
132: */
133: public String getErrorMessage() {
134: return errorMessage;
135: }
136:
137: /* (non-Javadoc)
138: * @see javax.servlet.http.HttpServletResponse#sendRedirect(java.lang.String)
139: */
140: public void sendRedirect(String url) throws IOException {
141: if (committed) {
142: throw new IllegalStateException(
143: "Cannot send redirect - response is already committed");
144: }
145:
146: redirectedUrl = url;
147: committed = true;
148: }
149:
150: /**
151: * Accessor for the redirect URL set using {@link #sendRedirect(String)}
152: * @return The redirect URL
153: */
154: public String getRedirectedUrl() {
155: return redirectedUrl;
156: }
157:
158: /* (non-Javadoc)
159: * @see javax.servlet.http.HttpServletResponse#setStatus(int)
160: */
161: public void setStatus(int status) {
162: this .status = status;
163: }
164:
165: /* (non-Javadoc)
166: * @see javax.servlet.http.HttpServletResponse#setStatus(int, java.lang.String)
167: */
168: @Deprecated
169: public void setStatus(int status, String errorMessage) {
170: this .status = status;
171: this .errorMessage = errorMessage;
172: }
173:
174: /**
175: * What HTTP status code should be returned?
176: * @return The current http status code
177: */
178: public int getStatus() {
179: return status;
180: }
181:
182: /**
183: * Accessor for the content of output body
184: * @return A byte array of the output body
185: */
186: public byte[] getContentAsByteArray() {
187: flushBuffer();
188: return content.toByteArray();
189: }
190:
191: /**
192: * Accessor for the content of output body
193: * @return A string of the output body
194: * @throws UnsupportedEncodingException If the internal characterEncoding is incorrect
195: */
196: public String getContentAsString()
197: throws UnsupportedEncodingException {
198: flushBuffer();
199: return (characterEncoding != null) ? content
200: .toString(characterEncoding) : content.toString();
201: }
202:
203: /* (non-Javadoc)
204: * @see javax.servlet.ServletResponse#setContentLength(int)
205: */
206: public void setContentLength(int contentLength) {
207: this .contentLength = contentLength;
208: }
209:
210: /**
211: * Accessor for the content length of the output
212: * @return The content length of the output
213: */
214: public int getContentLength() {
215: return contentLength;
216: }
217:
218: /* (non-Javadoc)
219: * @see javax.servlet.ServletResponse#setContentType(java.lang.String)
220: */
221: public void setContentType(String contentType) {
222: this .contentType = contentType;
223: if (contentType != null) {
224: int charsetIndex = contentType.toLowerCase().indexOf(
225: CHARSET_PREFIX);
226:
227: if (charsetIndex != -1) {
228: String encoding = contentType.substring(charsetIndex
229: + CHARSET_PREFIX.length());
230: setCharacterEncoding(encoding);
231: }
232: }
233: }
234:
235: /* (non-Javadoc)
236: * @see javax.servlet.ServletResponse#getContentType()
237: */
238: public String getContentType() {
239: return contentType;
240: }
241:
242: /* (non-Javadoc)
243: * @see javax.servlet.ServletResponse#setBufferSize(int)
244: */
245: public void setBufferSize(int bufferSize) {
246: this .bufferSize = bufferSize;
247: }
248:
249: /* (non-Javadoc)
250: * @see javax.servlet.ServletResponse#getBufferSize()
251: */
252: public int getBufferSize() {
253: return bufferSize;
254: }
255:
256: /**
257: * @param committed Set the comitted flag
258: */
259: public void setCommitted(boolean committed) {
260: this .committed = committed;
261: }
262:
263: /* (non-Javadoc)
264: * @see javax.servlet.ServletResponse#isCommitted()
265: */
266: public boolean isCommitted() {
267: return committed;
268: }
269:
270: /* (non-Javadoc)
271: * @see javax.servlet.ServletResponse#resetBuffer()
272: */
273: public void resetBuffer() {
274: if (committed) {
275: throw new IllegalStateException(
276: "Cannot reset buffer - response is already committed");
277: }
278:
279: content.reset();
280: }
281:
282: /* (non-Javadoc)
283: * @see javax.servlet.ServletResponse#reset()
284: */
285: public void reset() {
286: resetBuffer();
287:
288: characterEncoding = null;
289: contentLength = 0;
290: contentType = null;
291: locale = null;
292: cookies.clear();
293: headers.clear();
294: status = HttpServletResponse.SC_OK;
295: errorMessage = null;
296: }
297:
298: /* (non-Javadoc)
299: * @see javax.servlet.ServletResponse#setLocale(java.util.Locale)
300: */
301: public void setLocale(Locale locale) {
302: this .locale = locale;
303: }
304:
305: /* (non-Javadoc)
306: * @see javax.servlet.ServletResponse#getLocale()
307: */
308: public Locale getLocale() {
309: return locale;
310: }
311:
312: /* (non-Javadoc)
313: * @see javax.servlet.http.HttpServletResponse#addCookie(javax.servlet.http.Cookie)
314: */
315: public void addCookie(Cookie cookie) {
316: cookies.add(cookie);
317: }
318:
319: /**
320: * Accessor for the array of current cookies
321: * @return The current set of output cookies
322: */
323: public Cookie[] getCookies() {
324: return cookies.toArray(new Cookie[cookies.size()]);
325: }
326:
327: /**
328: * Get a cookie by a given name
329: * @param name The name of the cookie to fetch
330: * @return A matching cookie or null if there was no match
331: */
332: public Cookie getCookie(String name) {
333: for (Cookie cookie : cookies) {
334: if (name.equals(cookie.getName())) {
335: return cookie;
336: }
337: }
338:
339: return null;
340: }
341:
342: /* (non-Javadoc)
343: * @see javax.servlet.http.HttpServletResponse#encodeUrl(java.lang.String)
344: */
345: @Deprecated
346: public String encodeUrl(String url) {
347: return url;
348: }
349:
350: /* (non-Javadoc)
351: * @see javax.servlet.http.HttpServletResponse#encodeURL(java.lang.String)
352: */
353: public String encodeURL(String url) {
354: return url;
355: }
356:
357: /* (non-Javadoc)
358: * @see javax.servlet.http.HttpServletResponse#encodeRedirectUrl(java.lang.String)
359: */
360: @Deprecated
361: public String encodeRedirectUrl(String url) {
362: return url;
363: }
364:
365: /* (non-Javadoc)
366: * @see javax.servlet.http.HttpServletResponse#encodeRedirectURL(java.lang.String)
367: */
368: public String encodeRedirectURL(String url) {
369: return url;
370: }
371:
372: /* (non-Javadoc)
373: * @see javax.servlet.http.HttpServletResponse#addHeader(java.lang.String, java.lang.String)
374: */
375: public void addHeader(String name, String value) {
376: doAddHeader(name, value);
377: }
378:
379: /* (non-Javadoc)
380: * @see javax.servlet.http.HttpServletResponse#setHeader(java.lang.String, java.lang.String)
381: */
382: public void setHeader(String name, String value) {
383: doSetHeader(name, value);
384: }
385:
386: /* (non-Javadoc)
387: * @see javax.servlet.http.HttpServletResponse#addDateHeader(java.lang.String, long)
388: */
389: public void addDateHeader(String name, long value) {
390: doAddHeader(name, value);
391: }
392:
393: /* (non-Javadoc)
394: * @see javax.servlet.http.HttpServletResponse#setDateHeader(java.lang.String, long)
395: */
396: public void setDateHeader(String name, long value) {
397: doSetHeader(name, value);
398: }
399:
400: /* (non-Javadoc)
401: * @see javax.servlet.http.HttpServletResponse#addIntHeader(java.lang.String, int)
402: */
403: public void addIntHeader(String name, int value) {
404: doAddHeader(name, value);
405: }
406:
407: /* (non-Javadoc)
408: * @see javax.servlet.http.HttpServletResponse#setIntHeader(java.lang.String, int)
409: */
410: public void setIntHeader(String name, int value) {
411: doSetHeader(name, value);
412: }
413:
414: /**
415: * Internal method to remove all previous values and replace with new
416: * @param name The header name
417: * @param value The replacement value
418: */
419: private void doSetHeader(String name, Object value) {
420: List<Object> values = new ArrayList<Object>();
421: values.add(value);
422: headers.put(name, values);
423: }
424:
425: /**
426: * Internal method to add a value to those under a name
427: * @param name The header name
428: * @param value The extra value
429: */
430: private void doAddHeader(String name, Object value) {
431: List<Object> values = headers.get(name);
432: if (values == null) {
433: values = new ArrayList<Object>();
434: headers.put(name, values);
435: }
436: values.add(value);
437: }
438:
439: /* (non-Javadoc)
440: * @see javax.servlet.http.HttpServletResponse#containsHeader(java.lang.String)
441: */
442: public boolean containsHeader(String name) {
443: return headers.containsKey(name);
444: }
445:
446: /**
447: * Accessor for the current set of headers
448: * @return The current set of headers
449: */
450: public Set<String> getHeaderNames() {
451: return headers.keySet();
452: }
453:
454: /**
455: * Accessor for a header by a given name
456: * @param name The header name to lookup
457: * @return The data behind this header
458: */
459: public Object getHeader(String name) {
460: return headers.get(name);
461: }
462:
463: /**
464: * If there are multiple values for a given header, get them as a list
465: * @param name The header name to lookup
466: * @return The data behind this header
467: */
468: @SuppressWarnings("unchecked")
469: public List<Object> getHeaders(String name) {
470: Object value = headers.get(name);
471: if (value instanceof List) {
472: return (List<Object>) value;
473: } else if (value != null) {
474: return Collections.singletonList(value);
475: } else {
476: return Collections.EMPTY_LIST;
477: }
478: }
479:
480: //---------------------------------------------------------------------
481: // Methods for FakeRequestDispatcher
482: //---------------------------------------------------------------------
483:
484: /**
485: * What URL are we forwarding to?
486: * @param forwardedUrl What URL are we forwarding to?
487: */
488: public void setForwardedUrl(String forwardedUrl) {
489: this .forwardedUrl = forwardedUrl;
490: }
491:
492: /**
493: * What URL are we forwarding to?
494: * @return What URL are we forwarding to?
495: */
496: public String getForwardedUrl() {
497: return forwardedUrl;
498: }
499:
500: /**
501: * What URL are we including?
502: * @param includedUrl What URL are we including?
503: */
504: public void setIncludedUrl(String includedUrl) {
505: this .includedUrl = includedUrl;
506: }
507:
508: /**
509: * What URL are we including?
510: * @return What URL are we including?
511: */
512: public String getIncludedUrl() {
513: return includedUrl;
514: }
515:
516: private static final String CHARSET_PREFIX = "charset=";
517:
518: private String characterEncoding = "ISO-8859-1";
519:
520: private final ByteArrayOutputStream content = new ByteArrayOutputStream();
521:
522: private final DelegatingServletOutputStream outputStream = new DelegatingServletOutputStream(
523: this .content);
524:
525: private PrintWriter writer = null;
526:
527: private int contentLength = 0;
528:
529: private String contentType = null;
530:
531: private int bufferSize = 4096;
532:
533: private boolean committed = false;
534:
535: private Locale locale = Locale.getDefault();
536:
537: private final List<Cookie> cookies = new ArrayList<Cookie>();
538:
539: private final Map<String, List<Object>> headers = new HashMap<String, List<Object>>();
540:
541: private int status = HttpServletResponse.SC_OK;
542:
543: private String errorMessage = null;
544:
545: private String redirectedUrl = null;
546:
547: private String forwardedUrl = null;
548:
549: private String includedUrl = null;
550: }
|