/* * Copyright (c) 1998-2011 Caucho Technology -- all rights reserved * * This file is part of Resin(R) Open Source * * Each copy or derived work must preserve the copyright notice and this * notice unmodified. * * Resin Open Source is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Resin Open Source is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty * of NON-INFRINGEMENT. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with Resin Open Source; if not, write to the * * Free Software Foundation, Inc. * 59 Temple Place, Suite 330 * Boston, MA 02111-1307 USA * * @author Scott Ferguson */ package com.caucho.jsp; import com.caucho.util.CharBuffer; import com.caucho.util.FreeList; import com.caucho.util.L10N; import com.caucho.vfs.TempCharBuffer; import com.caucho.vfs.TempCharReader; import com.caucho.vfs.TempCharStream; import javax.servlet.jsp.JspWriter; import java.io.IOException; import java.io.PrintWriter; import java.io.Reader; import java.io.Writer; import java.util.logging.Logger; /** * Implementation of the JSP BodyContent interface. */ public class BodyContentImpl extends AbstractBodyContent { static final L10N L = new L10N(BodyContentImpl.class); private static final Logger log = Logger.getLogger(BodyContentImpl.class.getName()); private static final FreeList<BodyContentImpl> _freeList = new FreeList<BodyContentImpl>(32); private TempCharStream _tempStream = new TempCharStream(); private TempCharReader _charReader; private JspPrintWriter _printWriter; private JspWriter _prev; /** * Creates a new QBodyContent instance. * * @param prev the encloding writer. */ private BodyContentImpl(JspWriter prev) { setParent(prev); } /** * Allocates a new BodyContent instance. */ static BodyContentImpl allocate() { BodyContentImpl body = (BodyContentImpl) _freeList.allocate(); if (body == null) body = new BodyContentImpl(null); return body; } /** * Initializes the BodyContent object. * * @param prev the enclosing writer */ void init(JspWriter prev) { setParent(prev); _tempStream.openWrite(); } /** * Writes characters to the stream. * * @param buf character buffer * @param off starting offset into the buffer * @param len length of valid bytes in the buffer. */ final public void write(char []buf, int off, int len) throws IOException { _tempStream.write(buf, off, len); } /** * Writes characters to the stream. * * @param s string * @param off starting offset into the buffer * @param len length of valid bytes in the buffer. */ final public void write(String s, int off, int len) throws IOException { _tempStream.write(s, off, len); } /** * Writes characters to the stream. * * @param ch character to write. */ final public void write(int ch) throws IOException { _tempStream.write(ch); } final public void clear() throws IOException { _tempStream.clearWrite(); } final public void clearBuffer() throws IOException { clear(); } final public void flush() throws IOException { // jsp/18kg throw new IOException(L.l("flush() may not be called in a body")); } final public void close() throws IOException { } final public int getBufferSize() { return -1; } final public int getRemaining() { return 0; } /** * Clears the body contents. */ public void clearBody() { _tempStream.clearWrite(); } /** * Returns a reader to the body content. */ public Reader getReader() { _charReader = new TempCharReader(); _charReader.init(_tempStream.getHead()); return _charReader; } public CharBuffer getCharBuffer() { CharBuffer cb = new CharBuffer(); TempCharBuffer head = _tempStream.getHead(); for (; head != null; head = head.getNext()) { char []cbuf = head.getBuffer(); cb.append(cbuf, 0, head.getLength()); } return cb; } /** * Returns a string representing the body content. */ public String getString() { TempCharBuffer head = _tempStream.getHead(); if (head == null || head.getBuffer().length == 0) return ""; int bomLength = 0; if (head.getBuffer()[0] == 0xfeff) bomLength = 1; if (head.getNext() == null) return new String(head.getBuffer(), bomLength, head.getLength() - bomLength); int length = 0; for (; head != null; head = head.getNext()) length += head.getLength(); char []buf = new char[length]; int offset = 0; for (head = _tempStream.getHead(); head != null; head = head.getNext()) { char []cbuf = head.getBuffer(); int sublen = head.getLength(); System.arraycopy(cbuf, 0, buf, offset, sublen); offset += sublen; } return new String(buf, bomLength, length - bomLength); } /** * Returns a string representing the body content. */ public String getTrimString() { TempCharBuffer head = _tempStream.getHead(); boolean hasData = false; char []buf = null; int totalLength = 0; for (; head != null; head = head.getNext()) { char []cbuf = head.getBuffer(); int end = head.getLength(); int offset = 0; if (! hasData) { for (offset = 0; offset < end; offset++) { if (! Character.isWhitespace(cbuf[offset])) { hasData = true; break; } } } if (head.getNext() == null) { for (; offset < end; end--) { if (! Character.isWhitespace(cbuf[end - 1])) break; } if (buf != null) { System.arraycopy(cbuf, offset, buf, totalLength, end - offset); totalLength += end - offset; return new String(buf, 0, totalLength); } else if (offset == end) return ""; else return new String(cbuf, offset, end - offset); } else if (buf == null) { int length = 0; for (TempCharBuffer ptr = head; ptr != null; ptr = ptr.getNext()) length += ptr.getLength(); buf = new char[length]; System.arraycopy(cbuf, offset, buf, 0, end - offset); totalLength += end - offset; } else { System.arraycopy(cbuf, offset, buf, totalLength, end - offset); totalLength += end - offset; } } return ""; } /** * Writes the body contents out to the named writer. */ public void writeOut(Writer out) throws IOException { try { TempCharBuffer head = _tempStream.getHead(); boolean isFirst = true; for (; head != null; head = head.getNext()) { int offset = 0; int length = head.getLength(); char []cbuf = head.getBuffer(); if (isFirst && length > 0 && cbuf[0] == 0xfeff) { // skip byte-order-mark offset = 1; length--; } out.write(cbuf, offset, length); isFirst = false; } } catch (IOException e) { } } /** * Writes the body contents out to the named writer. */ public void flushBuffer() throws IOException { } /** * Returns the print writer. */ public PrintWriter getWriter() { if (_printWriter == null) _printWriter = new JspPrintWriter(this); _printWriter.init(this); return _printWriter; } /** * Releases the body content at the end of the tag. */ public void release() { releaseNoFree(); _freeList.free(this); } void releaseNoFree() { if (_charReader != null && ! _charReader.isEmpty()) { _charReader.setFree(true); _tempStream.discard(); } else _tempStream.destroy(); _charReader = null; _prev = null; } AbstractJspWriter popWriter() { AbstractJspWriter parent = super.popWriter(); release(); return parent; } }