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.jsp;
031:
032: import com.caucho.log.Log;
033: import com.caucho.util.CharBuffer;
034: import com.caucho.util.FreeList;
035: import com.caucho.util.L10N;
036: import com.caucho.vfs.TempCharBuffer;
037: import com.caucho.vfs.TempCharReader;
038: import com.caucho.vfs.TempCharStream;
039:
040: import javax.servlet.jsp.JspWriter;
041: import java.io.IOException;
042: import java.io.PrintWriter;
043: import java.io.Reader;
044: import java.io.Writer;
045: import java.util.logging.Logger;
046:
047: /**
048: * Implementation of the JSP BodyContent interface.
049: */
050: public class BodyContentImpl extends AbstractBodyContent {
051: static final L10N L = new L10N(BodyContentImpl.class);
052: static final Logger log = Log.open(BodyContentImpl.class);
053:
054: private static final FreeList<BodyContentImpl> _freeList = new FreeList<BodyContentImpl>(
055: 32);
056:
057: private TempCharStream _tempStream = new TempCharStream();
058: private TempCharReader _charReader;
059: private JspPrintWriter _printWriter;
060: private JspWriter _prev;
061:
062: /**
063: * Creates a new QBodyContent instance.
064: *
065: * @param prev the encloding writer.
066: */
067: private BodyContentImpl(JspWriter prev) {
068: setParent(prev);
069: }
070:
071: /**
072: * Allocates a new BodyContent instance.
073: */
074: static BodyContentImpl allocate() {
075: BodyContentImpl body = (BodyContentImpl) _freeList.allocate();
076:
077: if (body == null)
078: body = new BodyContentImpl(null);
079:
080: return body;
081: }
082:
083: /**
084: * Initializes the BodyContent object.
085: *
086: * @param prev the enclosing writer
087: */
088: void init(JspWriter prev) {
089: setParent(prev);
090:
091: _tempStream.openWrite();
092: }
093:
094: /**
095: * Writes characters to the stream.
096: *
097: * @param buf character buffer
098: * @param off starting offset into the buffer
099: * @param len length of valid bytes in the buffer.
100: */
101: final public void write(char[] buf, int off, int len)
102: throws IOException {
103: _tempStream.write(buf, off, len);
104: }
105:
106: /**
107: * Writes characters to the stream.
108: *
109: * @param s string
110: * @param off starting offset into the buffer
111: * @param len length of valid bytes in the buffer.
112: */
113: final public void write(String s, int off, int len)
114: throws IOException {
115: _tempStream.write(s, off, len);
116: }
117:
118: /**
119: * Writes characters to the stream.
120: *
121: * @param ch character to write.
122: */
123: final public void write(int ch) throws IOException {
124: _tempStream.write(ch);
125: }
126:
127: final public void clear() throws IOException {
128: _tempStream.clearWrite();
129: }
130:
131: final public void clearBuffer() throws IOException {
132: clear();
133: }
134:
135: final public void flush() throws IOException {
136: // jsp/18kg
137: throw new IOException(L
138: .l("flush() may not be called in a body"));
139: }
140:
141: final public void close() throws IOException {
142: }
143:
144: final public int getBufferSize() {
145: return -1;
146: }
147:
148: final public int getRemaining() {
149: return 0;
150: }
151:
152: /**
153: * Clears the body contents.
154: */
155: public void clearBody() {
156: _tempStream.clearWrite();
157: }
158:
159: /**
160: * Returns a reader to the body content.
161: */
162: public Reader getReader() {
163: _charReader = new TempCharReader();
164: _charReader.init(_tempStream.getHead());
165:
166: return _charReader;
167: }
168:
169: public CharBuffer getCharBuffer() {
170: CharBuffer cb = new CharBuffer();
171:
172: TempCharBuffer head = _tempStream.getHead();
173:
174: for (; head != null; head = head.getNext()) {
175: char[] cbuf = head.getBuffer();
176:
177: cb.append(cbuf, 0, head.getLength());
178: }
179:
180: return cb;
181: }
182:
183: /**
184: * Returns a string representing the body content.
185: */
186: public String getString() {
187: TempCharBuffer head = _tempStream.getHead();
188:
189: if (head == null)
190: return "";
191:
192: if (head.getNext() == null)
193: return new String(head.getBuffer(), 0, head.getLength());
194:
195: int length = 0;
196: for (; head != null; head = head.getNext())
197: length += head.getLength();
198:
199: char[] buf = new char[length];
200:
201: int offset = 0;
202: for (head = _tempStream.getHead(); head != null; head = head
203: .getNext()) {
204: char[] cbuf = head.getBuffer();
205: int sublen = head.getLength();
206:
207: System.arraycopy(cbuf, 0, buf, offset, sublen);
208:
209: offset += sublen;
210: }
211:
212: return new String(buf, 0, length);
213: }
214:
215: /**
216: * Returns a string representing the body content.
217: */
218: public String getTrimString() {
219: TempCharBuffer head = _tempStream.getHead();
220:
221: boolean hasData = false;
222:
223: char[] buf = null;
224: int totalLength = 0;
225: for (; head != null; head = head.getNext()) {
226: char[] cbuf = head.getBuffer();
227: int end = head.getLength();
228: int offset = 0;
229:
230: if (!hasData) {
231: for (offset = 0; offset < end; offset++) {
232: if (!Character.isWhitespace(cbuf[offset])) {
233: hasData = true;
234: break;
235: }
236: }
237: }
238:
239: if (head.getNext() == null) {
240: for (; offset < end; end--) {
241: if (!Character.isWhitespace(cbuf[end - 1]))
242: break;
243: }
244:
245: if (buf != null) {
246: System.arraycopy(cbuf, offset, buf, totalLength,
247: end - offset);
248: totalLength += end - offset;
249:
250: return new String(buf, 0, totalLength);
251: } else if (offset == end)
252: return "";
253: else
254: return new String(cbuf, offset, end - offset);
255:
256: } else if (buf == null) {
257: int length = 0;
258:
259: for (TempCharBuffer ptr = head; ptr != null; ptr = ptr
260: .getNext())
261: length += ptr.getLength();
262:
263: buf = new char[length];
264:
265: System.arraycopy(cbuf, offset, buf, 0, end - offset);
266: totalLength += end - offset;
267: } else {
268: System.arraycopy(cbuf, offset, buf, totalLength, end
269: - offset);
270: totalLength += end - offset;
271: }
272: }
273:
274: return "";
275: }
276:
277: /**
278: * Writes the body contents out to the named writer.
279: */
280: public void writeOut(Writer out) throws IOException {
281: try {
282: TempCharBuffer head = _tempStream.getHead();
283: boolean isFirst = true;
284:
285: for (; head != null; head = head.getNext()) {
286: int offset = 0;
287: int length = head.getLength();
288: char[] cbuf = head.getBuffer();
289:
290: if (isFirst && length > 0 && cbuf[0] == 0xfeff) {
291: // skip byte-order-mark
292: offset = 1;
293: length--;
294: }
295:
296: out.write(cbuf, offset, length);
297:
298: isFirst = false;
299: }
300: } catch (IOException e) {
301: }
302: }
303:
304: /**
305: * Writes the body contents out to the named writer.
306: */
307: public void flushBuffer() throws IOException {
308: }
309:
310: /**
311: * Returns the print writer.
312: */
313: public PrintWriter getWriter() {
314: if (_printWriter == null)
315: _printWriter = new JspPrintWriter(this );
316:
317: _printWriter.init(this );
318:
319: return _printWriter;
320: }
321:
322: /**
323: * Releases the body content at the end of the tag.
324: */
325: public void release() {
326: releaseNoFree();
327:
328: _freeList.free(this );
329: }
330:
331: void releaseNoFree() {
332: if (_charReader != null && !_charReader.isEmpty()) {
333: _charReader.setFree(true);
334: _tempStream.discard();
335: } else
336: _tempStream.destroy();
337:
338: _charReader = null;
339: _prev = null;
340: }
341:
342: AbstractJspWriter popWriter() {
343: AbstractJspWriter parent = super.popWriter();
344:
345: release();
346:
347: return parent;
348: }
349: }
|