001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: *
023: * Free Software Foundation, Inc.
024: * 59 Temple Place, Suite 330
025: * Boston, MA 02111-1307 USA
026: *
027: * @author Scott Ferguson
028: */
029:
030: package com.caucho.server.connection;
031:
032: import com.caucho.log.Log;
033: import com.caucho.util.L10N;
034:
035: import javax.servlet.ServletOutputStream;
036: import javax.servlet.ServletResponse;
037: import java.io.IOException;
038: import java.io.OutputStream;
039: import java.io.PrintWriter;
040: import java.io.Writer;
041: import java.util.logging.Level;
042: import java.util.logging.Logger;
043:
044: public class IncludeResponseStream extends ToByteResponseStream {
045: static final Logger log = Log.open(IncludeResponseStream.class);
046:
047: static final L10N L = new L10N(IncludeResponseStream.class);
048:
049: private final AbstractHttpResponse _response;
050:
051: private boolean _isCauchoResponseStream;
052: private AbstractResponseStream _nextResponseStream;
053:
054: private ServletResponse _next;
055: private ServletOutputStream _os;
056: private PrintWriter _writer;
057:
058: private OutputStream _cacheStream;
059: private Writer _cacheWriter;
060:
061: public IncludeResponseStream(AbstractHttpResponse response) {
062: _response = response;
063: }
064:
065: public void init(ServletResponse next) {
066: _next = next;
067:
068: if (_os != null || _writer != null)
069: throw new IllegalStateException();
070:
071: if (_next instanceof CauchoResponse) {
072: CauchoResponse response = (CauchoResponse) next;
073:
074: _isCauchoResponseStream = response.isCauchoResponseStream();
075:
076: if (_isCauchoResponseStream)
077: _nextResponseStream = response.getResponseStream();
078: } else
079: _isCauchoResponseStream = false;
080: }
081:
082: public void start() {
083: super .start();
084:
085: try {
086: setEncoding(_next.getCharacterEncoding());
087: } catch (Throwable e) {
088: log.log(Level.FINE, e.toString(), e);
089: }
090: }
091:
092: /**
093: * Returns true for a caucho response stream.
094: */
095: public boolean isCauchoResponseStream() {
096: return _isCauchoResponseStream;
097: }
098:
099: /**
100: * Set true for a caucho response stream.
101: */
102: public void setCauchoResponseStream(boolean isCaucho) {
103: _isCauchoResponseStream = isCaucho;
104: }
105:
106: /**
107: * Sets any cache stream.
108: */
109: public void setByteCacheStream(OutputStream cacheStream) {
110: _cacheStream = cacheStream;
111: }
112:
113: /**
114: * Sets any cache stream.
115: */
116: public void setCharCacheStream(Writer cacheWriter) {
117: _cacheWriter = cacheWriter;
118: }
119:
120: /**
121: * Converts the char buffer.
122: */
123: protected void flushCharBuffer() throws IOException {
124: if (_isCauchoResponseStream && _nextResponseStream == null) {
125: // jsp/18ek
126: super .flushCharBuffer();
127:
128: return;
129: }
130:
131: try {
132: if (_writer == null)
133: _writer = _next.getWriter();
134: } catch (Throwable e) {
135: log.log(Level.FINER, e.toString(), e);
136: }
137:
138: if (_writer != null) {
139: int charLength = getCharOffset();
140: setCharOffset(0);
141: char[] buffer = getCharBuffer();
142:
143: _response.startCaching(false);
144:
145: _writer.write(buffer, 0, charLength);
146:
147: if (_cacheWriter != null)
148: _cacheWriter.write(buffer, 0, charLength);
149: } else
150: super .flushCharBuffer();
151: }
152:
153: /**
154: * Sets the byte buffer offset.
155: */
156: public void setBufferOffset(int offset) throws IOException {
157: super .setBufferOffset(offset);
158:
159: if (!_isCauchoResponseStream)
160: flushByteBuffer();
161: }
162:
163: /**
164: * Writes the next chunk of data to the response stream.
165: *
166: * @param buf the buffer containing the data
167: * @param offset start offset into the buffer
168: * @param length length of the data in the buffer
169: */
170: public void write(int ch) throws IOException {
171: flushCharBuffer();
172:
173: if (_isCauchoResponseStream) {
174: super .write(ch);
175: } else {
176: if (_os == null)
177: _os = _next.getOutputStream();
178:
179: _os.write(ch);
180: }
181: }
182:
183: /**
184: * Writes the next chunk of data to the response stream.
185: *
186: * @param buf the buffer containing the data
187: * @param offset start offset into the buffer
188: * @param length length of the data in the buffer
189: */
190: public void write(byte[] buf, int offset, int length)
191: throws IOException {
192: flushCharBuffer();
193:
194: if (false && _isCauchoResponseStream) // jsp/15dv
195: super .write(buf, offset, length);
196: else {
197: if (_os == null)
198: _os = _next.getOutputStream();
199:
200: _os.write(buf, offset, length);
201: }
202: }
203:
204: /**
205: * Writes the next chunk of data to the response stream.
206: *
207: * @param buf the buffer containing the data
208: * @param offset start offset into the buffer
209: * @param length length of the data in the buffer
210: */
211: @Override
212: protected void writeNext(byte[] buf, int offset, int length,
213: boolean isEnd) throws IOException {
214: try {
215: if (_response != null)
216: _response.writeHeaders(null, -1);
217:
218: if (length == 0)
219: return;
220:
221: if (_cacheStream != null)
222: _cacheStream.write(buf, offset, length);
223:
224: if (_os == null)
225: _os = _next.getOutputStream();
226:
227: _os.write(buf, offset, length);
228: } catch (IOException e) {
229: if (_next instanceof CauchoResponse)
230: ((CauchoResponse) _next).killCache();
231:
232: if (_response != null)
233: _response.killCache();
234:
235: throw e;
236: }
237: }
238:
239: /**
240: * flushing
241: */
242: public void flushByte() throws IOException {
243: flushBuffer();
244:
245: if (_os == null)
246: _os = _next.getOutputStream();
247:
248: _os.flush();
249: }
250:
251: /**
252: * flushing
253: */
254: public void flushChar() throws IOException {
255: flushBuffer();
256:
257: if (_writer == null)
258: _writer = _next.getWriter();
259:
260: _writer.flush();
261: }
262:
263: /**
264: * Finish.
265: */
266: public void finish() throws IOException {
267: flushBuffer();
268:
269: /*
270: if (_writer != null)
271: _writer.flush();
272:
273: if (_os != null)
274: _os.flush();
275: */
276:
277: _os = null;
278: _writer = null;
279: _next = null;
280:
281: _cacheStream = null;
282: _cacheWriter = null;
283: }
284:
285: /**
286: * Close.
287: */
288: public void close() throws IOException {
289: super .close();
290:
291: /*
292: if (_writer != null)
293: _writer.close();
294:
295: if (_os != null)
296: _os.close();
297: */
298:
299: _os = null;
300: _writer = null;
301: _next = null;
302:
303: _cacheStream = null;
304: _cacheWriter = null;
305: }
306: }
|