001: /*
002: * The Apache Software License, Version 1.1
003: *
004: * Copyright (c) 2001-2004 Caucho Technology, Inc. All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: *
010: * 1. Redistributions of source code must retain the above copyright
011: * notice, this list of conditions and the following disclaimer.
012: *
013: * 2. Redistributions in binary form must reproduce the above copyright
014: * notice, this list of conditions and the following disclaimer in
015: * the documentation and/or other materials provided with the
016: * distribution.
017: *
018: * 3. The end-user documentation included with the redistribution, if
019: * any, must include the following acknowlegement:
020: * "This product includes software developed by the
021: * Caucho Technology (http://www.caucho.com/)."
022: * Alternately, this acknowlegement may appear in the software itself,
023: * if and wherever such third-party acknowlegements normally appear.
024: *
025: * 4. The names "Hessian", "Resin", and "Caucho" must not be used to
026: * endorse or promote products derived from this software without prior
027: * written permission. For written permission, please contact
028: * info@caucho.com.
029: *
030: * 5. Products derived from this software may not be called "Resin"
031: * nor may "Resin" appear in their names without prior written
032: * permission of Caucho Technology.
033: *
034: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
035: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
036: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
037: * DISCLAIMED. IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS
038: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
039: * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
040: * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
041: * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
042: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
043: * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
044: * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
045: *
046: * @author Sam
047: */
048:
049: package com.caucho.portal.generic.context;
050:
051: import com.caucho.portal.generic.FastPrintWriter;
052:
053: import java.io.IOException;
054: import java.io.OutputStream;
055: import java.io.PrintWriter;
056: import java.io.UnsupportedEncodingException;
057: import java.util.Locale;
058: import java.util.logging.Level;
059: import java.util.logging.Logger;
060:
061: /**
062: * A ResponseHandler that wraps another ResponseHandler. Derived classes
063: * override the print() and write() methods to intercept the output.
064: *
065: * flushBuffer(), reset(), and resetBuffer() DO NOT propagate to the
066: * wrapped stream (they do nothing in the implementations for this class)
067: */
068: public class AbstractResponseHandler implements ResponseHandler {
069: protected static final Logger log = Logger
070: .getLogger(AbstractResponseHandler.class.getName());
071:
072: private PrintWriter _internalWriter;
073: private OutputStream _internalOutputStream;
074:
075: private ResponseHandler _successor;
076:
077: protected PrintWriter _writer;
078: protected OutputStream _outputStream;
079:
080: protected PrintWriter _writerOut;
081: protected OutputStream _outputStreamOut;
082:
083: private Exception _errorCause;
084:
085: public AbstractResponseHandler() {
086: }
087:
088: public AbstractResponseHandler(ResponseHandler successor) {
089: open(successor);
090: }
091:
092: public void open(ResponseHandler successor) {
093: if (_successor != null)
094: throw new IllegalStateException("already open");
095:
096: _successor = successor;
097: }
098:
099: public void finish() throws IOException {
100: Exception errorCause = _errorCause;
101:
102: _writerOut = null;
103: _outputStreamOut = null;
104: _successor = null;
105: _errorCause = null;
106:
107: if (errorCause != null) {
108: if (errorCause instanceof IOException)
109: throw (IOException) errorCause;
110: else {
111: IOException ex = new IOException();
112: ex.initCause(errorCause);
113: throw ex;
114: }
115: }
116:
117: }
118:
119: public ResponseHandler getSuccessor() {
120: return _successor;
121: }
122:
123: public void setProperty(String name, String value) {
124: _successor.setProperty(name, value);
125: }
126:
127: public void addProperty(String name, String value) {
128: _successor.addProperty(name, value);
129: }
130:
131: public void setCharacterEncoding(String enc)
132: throws UnsupportedEncodingException {
133: if (_writer == null && _outputStream == null)
134: _successor.setCharacterEncoding(enc);
135: }
136:
137: public String getCharacterEncoding() {
138: return _successor.getCharacterEncoding();
139: }
140:
141: public void setContentType(String contentType) {
142: if (_writer == null && _outputStream == null)
143: _successor.setContentType(contentType);
144: }
145:
146: public String getContentType() {
147: return _successor.getContentType();
148: }
149:
150: public void setLocale(Locale locale) {
151: if (_writer == null && _outputStream == null)
152: _successor.setLocale(locale);
153: }
154:
155: public Locale getLocale() {
156: return _successor.getLocale();
157: }
158:
159: public boolean isCommitted() {
160: return _successor.isCommitted();
161: }
162:
163: public PrintWriter getWriter() throws IOException {
164: checkErrorOrFail();
165:
166: if (_writer != null)
167: return _writer;
168:
169: if (_outputStream != null)
170: throw new IllegalStateException(
171: "getOutputStream() already called");
172:
173: if (getContentType() == null)
174: throw new IllegalStateException(
175: "response.setContentType() must be called before getWriter()");
176:
177: try {
178: PrintWriter writerOut = _successor.getWriter();
179:
180: if (_internalWriter == null)
181: _internalWriter = new GenericPrintWriter(this );
182:
183: _writerOut = writerOut;
184: _writer = _internalWriter;
185:
186: } catch (Exception ex) {
187: setError(ex);
188: }
189:
190: checkErrorOrFail();
191:
192: return _writer;
193: }
194:
195: protected PrintWriter getUnderlyingWriter() {
196: return _writerOut;
197: }
198:
199: public OutputStream getOutputStream() throws IOException {
200: checkErrorOrFail();
201:
202: if (_outputStream != null)
203: return _outputStream;
204:
205: if (_writer != null)
206: throw new IllegalStateException(
207: "getWriter() already called");
208:
209: if (getContentType() == null)
210: throw new IllegalStateException(
211: "response.setContentType() must be called before getOutputStream()");
212:
213: boolean fail = true;
214:
215: try {
216: OutputStream outputStreamOut = _successor.getOutputStream();
217:
218: if (_internalOutputStream == null)
219: _internalOutputStream = new GenericOutputStream(this );
220:
221: _outputStreamOut = outputStreamOut;
222: _outputStream = _internalOutputStream;
223:
224: fail = false;
225: } catch (Exception ex) {
226: setError(ex);
227: }
228:
229: checkErrorOrFail();
230:
231: return _outputStream;
232: }
233:
234: protected OutputStream getUnderlyingOutputStream() {
235: return _outputStreamOut;
236: }
237:
238: /**
239: * Set an error with a cause.
240: */
241: protected void setError(Exception cause) {
242: if (cause == null)
243: throw new NullPointerException();
244:
245: if (_errorCause != null) {
246: _errorCause = cause;
247: log.log(Level.FINEST, _errorCause.toString(), cause);
248: }
249: }
250:
251: /**
252: * Return an exception if this ResponseHandler has failed.
253: */
254: public Exception getErrorCause() {
255: return _errorCause;
256: }
257:
258: public boolean isError() {
259: return _errorCause != null;
260: }
261:
262: protected void checkErrorOrFail() throws IOException {
263: if (_errorCause != null) {
264: if (_errorCause instanceof IOException)
265: throw (IOException) _errorCause;
266: else {
267: IOException ex = new IOException();
268: ex.initCause(_errorCause);
269: throw ex;
270: }
271: }
272: }
273:
274: public void setBufferSize(int bufferSize) {
275: _successor.setBufferSize(bufferSize);
276: }
277:
278: public int getBufferSize() {
279: return _successor.getBufferSize();
280: }
281:
282: /**
283: * flushBuffer(), reset(), and resetBuffer() DO NOT propagate to the
284: * wrapped stream (they do nothing in the implementations for this class)
285: */
286: public void reset() {
287: }
288:
289: /**
290: * flushBuffer(), reset(), and resetBuffer() DO NOT propagate to the
291: * wrapped stream (they do nothing in the implementations for this class)
292: */
293: public void resetBuffer() {
294: }
295:
296: /**
297: * flushBuffer(), reset(), and resetBuffer() DO NOT propagate to the
298: * wrapped stream (they do nothing in the implementations for this class)
299: */
300: public void flushBuffer() throws IOException {
301: checkErrorOrFail();
302: }
303:
304: /**
305: * Write chars out to the underlying Writer
306: */
307: protected void print(char buf[], int off, int len)
308: throws IOException {
309: if (len == 0)
310: return;
311:
312: checkErrorOrFail();
313:
314: _writerOut.write(buf, off, len);
315: }
316:
317: /**
318: * Write chars out to the underlying Writer
319: */
320: protected void print(String str, int off, int len)
321: throws IOException {
322: if (len == 0)
323: return;
324:
325: checkErrorOrFail();
326:
327: _writerOut.write(str, off, len);
328: }
329:
330: /**
331: * Write a char out to the underlying Writer
332: */
333: protected void print(char c) throws IOException {
334: checkErrorOrFail();
335:
336: _writerOut.write((int) c);
337: }
338:
339: /**
340: * Write bytes out to the underlying OutputStream
341: */
342: protected void write(byte[] buf, int off, int len)
343: throws IOException {
344: checkErrorOrFail();
345:
346: _outputStreamOut.write(buf, off, len);
347: }
348:
349: /**
350: * Write a byte out to the underlying OutputStream
351: */
352: protected void write(byte b) throws IOException {
353: checkErrorOrFail();
354:
355: _outputStreamOut.write((int) b);
356: }
357:
358: private static class GenericPrintWriter extends FastPrintWriter {
359: private AbstractResponseHandler _successor;
360:
361: public GenericPrintWriter(AbstractResponseHandler successor) {
362: _successor = successor;
363: }
364:
365: protected void setError() {
366: _successor.setError(new IOException());
367: }
368:
369: protected void setError(Exception errorCause) {
370: _successor.setError(errorCause);
371: }
372:
373: public boolean checkError() {
374: return _successor.getErrorCause() != null;
375: }
376:
377: public Exception getErrorCause() {
378: return _successor.getErrorCause();
379: }
380:
381: public void writeOut(char buf[], int off, int len)
382: throws IOException {
383: _successor.print(buf, off, len);
384: }
385:
386: public void writeOut(String str, int off, int len)
387: throws IOException {
388: _successor.print(str, off, len);
389: }
390:
391: public void writeOut(char c) throws IOException {
392: _successor.print((char) c);
393: }
394:
395: public void close() {
396: }
397: }
398:
399: static private class GenericOutputStream extends OutputStream {
400: private AbstractResponseHandler _successor;
401:
402: public GenericOutputStream(AbstractResponseHandler successor) {
403: _successor = successor;
404: }
405:
406: public void flush() throws IOException {
407: _successor.flushBuffer();
408: }
409:
410: public void write(byte[] buf) throws IOException {
411: _successor.write(buf, 0, buf.length);
412: }
413:
414: public void write(byte[] buf, int off, int len)
415: throws IOException {
416: _successor.write(buf, off, len);
417: }
418:
419: public void write(int b) throws IOException {
420: _successor.write((byte) b);
421: }
422:
423: public void close() {
424: }
425: }
426: }
|