Java tutorial
/* * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is XML RenderKit for JSF. * * The Initial Developer of the Original Code is * Orbeon, Inc (info@orbeon.com) * Portions created by the Initial Developer are Copyright (C) 2002 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. */ package org.ajax4jsf.webapp; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.io.Reader; import java.io.UnsupportedEncodingException; import java.io.Writer; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; import javax.servlet.ServletOutputStream; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponseWrapper; import org.ajax4jsf.Messages; import org.ajax4jsf.io.FastBufferInputStream; import org.ajax4jsf.io.FastBufferOutputStream; import org.ajax4jsf.io.FastBufferReader; import org.ajax4jsf.io.FastBufferWriter; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.xml.sax.InputSource; /** * Base wrapper save JSF page response, for parse to XML with different parsers * @author shura (latest modification by $Author: alexsmirnov $) * @version $Revision: 1.1.2.1 $ $Date: 2007/01/09 18:58:17 $ * */ public class FilterServletResponseWrapper extends HttpServletResponseWrapper { private static final Log log = LogFactory.getLog(FilterServletResponseWrapper.class); public static final String DEFAULT_ENCODING = "UTF-8"; protected FastBufferOutputStream byteStream = null; private ServletOutputStream servletOutputStream; private boolean useStream = false; private FastBufferWriter stringWriter; private PrintWriter printWriter; private boolean useWriter = false; private String contentType; private String charterEncoding = null; private Map<String, Object> headers = new HashMap<String, Object>(); private int bufferSize = 2048; private int contentLength = Integer.MIN_VALUE; private String redirectLocation = null; private boolean useNullStream = false; private boolean error = false; private List<Cookie> cookies = new ArrayList<Cookie>(); public FilterServletResponseWrapper(HttpServletResponse response) { super(response); } /** * Convert saved context to stream for parsing * @return stream from saved content */ public InputStream getContentAsStream() { int length = 0; FastBufferInputStream result = null; String encoding = this.getCharacterEncoding(); /// byte[] content; if (isUseStream()) { try { servletOutputStream.flush(); } catch (IOException ex) { log.warn(Messages.getMessage(Messages.FLUSH_BUFFERED_STREAM_ERROR), ex); } /// content = byteStream.toByteArray(); result = new FastBufferInputStream(byteStream); } else if (isUseWriter()) { printWriter.flush(); printWriter.close(); length = stringWriter.getLength(); /// String stringContent = stringWriter.toString(); try { FastBufferOutputStream stream = stringWriter.convertToOutputStream(encoding); result = new FastBufferInputStream(stream); /// content = stringContent.getBytes(encoding); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block log.warn(Messages.getMessage(Messages.UNSUPPORTED_ENCODING_WARNING)); FastBufferOutputStream stream = stringWriter.convertToOutputStream(); result = new FastBufferInputStream(stream); /// content = stringContent.getBytes(); } } else { if (log.isDebugEnabled()) { log.debug(Messages.getMessage(Messages.NO_WRITER_CALLED_INFO)); } return null; } /// if (content.length > 0) { if (length > 0) { if (log.isDebugEnabled()) { log.debug(Messages.getMessage(Messages.PARSE_XML_DOCUMENT_INFO)); // try { // log.debug(new String(content, encoding)); // } catch (UnsupportedEncodingException e) { // } } } return result; /// return new ByteArrayInputStream(content); } /** * Convert saved context to stream for parsing * @return stream from saved content */ public Reader getContentAsReader() { FastBufferReader result = null; String encoding = this.getCharacterEncoding(); /// String content; if (isUseWriter()) { printWriter.flush(); printWriter.close(); result = new FastBufferReader(stringWriter); /// content = stringWriter.toString(); } else if (isUseStream()) { try { servletOutputStream.flush(); } catch (IOException ex) { log.warn(Messages.getMessage(Messages.FLUSH_BUFFERED_STREAM_ERROR), ex); } try { FastBufferWriter writer = byteStream.convertToWriter(encoding); result = new FastBufferReader(writer); /// content = byteStream.toString(encoding); } catch (UnsupportedEncodingException e) { log.warn(Messages.getMessage(Messages.UNSUPPORTED_ENCODING_WARNING_2), e); FastBufferWriter writer = byteStream.convertToWriter(); result = new FastBufferReader(writer); /// content = byteStream.toString(); } } else { if (log.isDebugEnabled()) { log.debug(Messages.getMessage(Messages.NO_WRITER_CALLED_INFO)); } return null; } // if (content.length() > 0) { // if (log.isDebugEnabled()) { // log.debug("XML document to parse in filter, return as Reader: "); // log.debug(content); // } // } /// return new StringReader(content); return result; } public PrintWriter getWriter() throws IOException { if (useStream) { throw new IllegalStateException(Messages.getMessage(Messages.NO_WRITER_POSSIBLE_ERROR)); } if (printWriter == null) { if (log.isDebugEnabled()) { log.debug(Messages.getMessage(Messages.CREATE_WRITER_INFO)); } printWriter = new PrintWriter(new ServletStringWriter()); useWriter = true; } return printWriter; } public ServletOutputStream getOutputStream() throws IOException { if (useWriter) { if (isUseNullStream()) { return new NullServletOutputStream(); } throw new IllegalStateException(Messages.getMessage(Messages.NO_STREAM_POSSIBLE_ERROR)); } if (servletOutputStream == null) { // byteStream = new ByteArrayOutputStream(); servletOutputStream = new ByteArrayServletOutputStream(); } if (log.isDebugEnabled()) { log.debug(Messages.getMessage(Messages.CREATE_STREAM_INFO)); } useStream = true; return servletOutputStream; } public class ByteArrayServletOutputStream extends ServletOutputStream { private boolean opened = true; /* (non-Javadoc) * @see java.io.OutputStream#close() */ public void close() throws IOException { flush(); opened = false; } /* (non-Javadoc) * @see java.io.OutputStream#write(byte[]) */ public void write(byte[] b) throws IOException { // TODO Auto-generated method stub if (opened) { byteStream.write(b); } } public ByteArrayServletOutputStream() { byteStream = new FastBufferOutputStream(bufferSize); } public void write(int b) throws IOException { if (opened) { byteStream.write(b); } } /* (non-Javadoc) * @see java.io.OutputStream#write(byte[], int, int) */ public void write(byte[] b, int off, int len) throws IOException { if (opened) { byteStream.write(b, off, len); } } } public static class NullServletOutputStream extends ServletOutputStream { /* (non-Javadoc) * @see java.io.OutputStream#write(byte[], int, int) */ public void write(byte[] b, int off, int len) throws IOException { // this-is null stream, do nothing ! } /* (non-Javadoc) * @see java.io.OutputStream#write(byte[]) */ public void write(byte[] b) throws IOException { // this-is null stream, do nothing ! } public void write(int b) throws IOException { // this-is null stream, do nothing ! } } public class ServletStringWriter extends Writer { private boolean opened = true; public ServletStringWriter() { super(); stringWriter = new FastBufferWriter(bufferSize); } public void write(char[] cbuf, int off, int len) throws IOException { if (opened) { stringWriter.write(cbuf, off, len); } } /* (non-Javadoc) * @see java.io.Writer#write(char[]) */ public void write(char[] cbuf) throws IOException { // TODO Auto-generated method stub if (opened) { stringWriter.write(cbuf); } } /* (non-Javadoc) * @see java.io.Writer#write(int) */ public void write(int c) throws IOException { // TODO Auto-generated method stub if (opened) { stringWriter.write(c); } } public void flush() throws IOException { stringWriter.flush(); } public void close() throws IOException { stringWriter.close(); opened = false; } } // public boolean isCommitted() { // // NOTE: What makes sense here? // return false; // } /** * Return a charset from a content-type. */ public static String getContentTypeCharset(String contentType) { if (contentType == null) return null; int semicolumnIndex = contentType.indexOf(";"); if (semicolumnIndex == -1) return null; int charsetIndex = contentType.indexOf("charset=", semicolumnIndex); if (charsetIndex == -1) return null; // FIXME: There may be other attributes after charset, right? String afterCharset = contentType.substring(charsetIndex + 8); afterCharset = afterCharset.replace('"', ' '); return afterCharset.trim(); } /* (non-Javadoc) * @see javax.servlet.http.HttpServletResponse#addHeader(java.lang.String, java.lang.String) */ public void addHeader(String name, String value) { if ("Content-Type".equals(name)) { setContentType(value); } else { this.headers.put(name, value); super.addHeader(name, value); } } /* (non-Javadoc) * @see javax.servlet.http.HttpServletResponse#setHeader(java.lang.String, java.lang.String) */ public void setHeader(String name, String value) { // HACK - weblogic do not use setContentType, instead directly set header ! if ("Content-Type".equals(name)) { setContentType(value); } else { this.headers.put(name, value); super.setHeader(name, value); } } public Map<String, Object> getHeaders() { return this.headers; } /* (non-Javadoc) * @see javax.servlet.ServletResponse#getCharacterEncoding() */ public String getCharacterEncoding() { // return this.charterEncoding; if (null != this.charterEncoding) { return this.charterEncoding; } else { // For cases of implicit setting return super.getCharacterEncoding(); } } /* (non-Javadoc) * @see javax.servlet.ServletResponse#setCharacterEncoding(java.lang.String) */ public void setCharacterEncoding(String charset) { this.charterEncoding = charset; //super.setCharacterEncoding(charset); } public void setContentType(String type) { String contentTypeCharset = getContentTypeCharset(type); if (null != contentTypeCharset) { this.charterEncoding = contentTypeCharset; } this.contentType = type; // super.setContentType(type); } public void setLocale(Locale loc) { super.setLocale(loc); } public String getContentType() { return contentType; } /** * Send buffered content directly to output stream. * @param outputStream * @throws IOException */ public void sendContent(ServletOutputStream outputStream) throws IOException { if (getContentLength() > 0) { super.setContentLength(getContentLength()); } if (isUseWriter()) { printWriter.flush(); printWriter.close(); stringWriter.printTo(outputStream); /// outputStream.print(stringWriter.toString()); } else if (isUseStream()) { try { servletOutputStream.flush(); } catch (IOException ex) { log.warn(Messages.getMessage(Messages.FLUSH_BUFFERED_STREAM_ERROR), ex); } byteStream.writeTo(outputStream); } } /** * Send buffered content directly to output stream. * @param outputStream * @throws IOException */ public void sendContent(Writer output) throws IOException { if (getContentLength() > 0) { super.setContentLength(getContentLength()); } if (isUseWriter()) { printWriter.flush(); printWriter.close(); stringWriter.writeTo(output); /// outputStream.print(stringWriter.toString()); } else if (isUseStream()) { try { servletOutputStream.flush(); } catch (IOException ex) { log.warn(Messages.getMessage(Messages.FLUSH_BUFFERED_STREAM_ERROR), ex); } byteStream.writeTo(output, getCharacterEncoding()); } } /** * @return Returns the useStream. */ public boolean isUseStream() { return this.useStream; } /** * @return Returns the useWriter. */ public boolean isUseWriter() { return this.useWriter; } /** * @return * @throws RuntimeException */ public InputSource getContentAsInputSource() throws RuntimeException { // Create InputSource InputSource inputSource = null; String encoding = this.getCharacterEncoding(); if (isUseWriter()) { inputSource = new InputSource(getContentAsReader()); } else if (isUseStream()) { inputSource = new InputSource(getContentAsStream()); if (encoding != null) inputSource.setEncoding(encoding); } else { if (log.isDebugEnabled()) { log.debug(Messages.getMessage(Messages.NO_WRITER_CALLED_INFO)); } return null; } return inputSource; } /* (non-Javadoc) * @see javax.servlet.ServletResponseWrapper#flushBuffer() */ public void flushBuffer() throws IOException { if (isUseStream()) { servletOutputStream.flush(); } else if (isUseWriter()) { printWriter.flush(); } } /* (non-Javadoc) * @see javax.servlet.ServletResponseWrapper#getBufferSize() */ public int getBufferSize() { // TODO Auto-generated method stub return bufferSize; } /* (non-Javadoc) * @see javax.servlet.ServletResponseWrapper#resetBuffer() */ public void resetBuffer() { this.printWriter = null; this.stringWriter = null; this.servletOutputStream = null; this.byteStream = null; this.useStream = false; this.useWriter = false; } /* (non-Javadoc) * @see javax.servlet.ServletResponseWrapper#setBufferSize(int) */ public void setBufferSize(int arg0) { // TODO Auto-generated method stub bufferSize = arg0; } /* (non-Javadoc) * @see javax.servlet.ServletResponseWrapper#reset() */ public void reset() { // TODO Auto-generated method stub this.resetBuffer(); this.headers = new HashMap<String, Object>(); this.contentType = null; this.charterEncoding = null; super.reset(); } /** * @return Returns the contentLength. */ public int getContentLength() { return contentLength; } /** * @param contentLength The contentLength to set. */ public void setContentLength(int contentLength) { this.contentLength = contentLength; } /** * Parse saved content to output stream ( and store as Dom Document tree ) * @param out stream to send parsed content, if null - only build dom tree. * @return parsed document as dom tree. * @throws IOException */ public void parseContent(Writer out, HtmlParser parser) throws IOException { parser.setInputEncoding(getCharacterEncoding()); if (isUseWriter()) { parser.parseHtml(getContentAsReader(), out); } else if (isUseStream()) { parser.parseHtml(getContentAsStream(), out); } } public void sendRedirect(String arg0) throws IOException { // TODO Auto-generated method stub this.redirectLocation = arg0; } public String getRedirectLocation() { return redirectLocation; } /** * @return the useNullStream */ public boolean isUseNullStream() { return useNullStream; } /** * @param useNullStream the useNullStream to set */ public void setUseNullStream(boolean useNullStream) { this.useNullStream = useNullStream; } public void addCookie(Cookie cookie) { cookies.add(cookie); super.addCookie(cookie); } public Collection<Cookie> getCookies() { return cookies; } public void sendError(int sc) throws IOException { this.error = true; super.sendError(sc); } public void sendError(int sc, String msg) throws IOException { this.error = true; super.sendError(sc, msg); } public boolean isError() { return error; } }