/**
* License Agreement.
*
* Rich Faces - Natural Ajax for Java Server Faces (JSF)
*
* Copyright (C) 2007 Exadel, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation.
*
* This library 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. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package org.ajax4jsf.webapp;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.Serializable;
import java.io.Writer;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import org.ajax4jsf.io.FastBufferOutputStream;
import org.ajax4jsf.io.FastBufferWriter;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* @author shura (latest modification by $Author: alexsmirnov $)
* @version $Revision: 1.1.2.1 $ $Date: 2007/01/09 18:58:20 $
*
*/
public class CacheContent implements Serializable {
/**
*
*/
private static final long serialVersionUID = 8120940486890871177L;
private static final Log _log = LogFactory.getLog(CacheContent.class);
// private transient ByteArrayOutputStream outputStream ;
private transient FastBufferOutputStream outputStream;
private transient FastBufferWriter stringOutputWriter;
private transient PrintWriter servletWriter;
private transient ServletOutputStream servletStream;
// content to send.
private byte[] content = null;
private String writerContent = null;
boolean filledOutputStream = false;
boolean filledOutputWriter = false;
private Map<String, Object> headers = new HashMap<String, Object>();
private String contentType;
private Integer contentLength;
/**
* Send saved content to http responce
*
* @param response
* @throws IOException
*/
public void send(HttpServletResponse response) throws IOException {
if (filledOutputStream) {
OutputStream out = response.getOutputStream();
if (content != null) {
out.write(content);
} else {
this.outputStream.writeTo(out);
}
// out.flush();
// out.close();
} else if (filledOutputWriter) {
Writer out = response.getWriter();
if (null != writerContent) {
out.write(writerContent);
} else {
stringOutputWriter.writeTo(out);
}
// out.flush();
// out.close();
}
}
/**
* Send saved headers to http responce.
*
* @param response
*/
public void sendHeaders(HttpServletResponse response) {
// set real content-length.
// / if (null != content) {
int realContentLength = 0;
if (filledOutputStream) {
if (null != content && content.length > 0) {
realContentLength = content.length;
} else if (null != outputStream && outputStream.getLength() > 0) {
realContentLength = outputStream.getLength();
}
} // TODO - calculate content-lenght for writer ?
if (realContentLength <= 0 && contentLength != null) {
realContentLength = contentLength.intValue();
}
for (Iterator<Entry<String, Object>> iter = headers.entrySet()
.iterator(); iter.hasNext();) {
Entry<String, Object> element = iter.next();
String header = (String) element.getKey();
Object headerValue = element.getValue();
try {
if (headerValue instanceof Long) {
Long time = (Long) headerValue;
response.setDateHeader(header, time.longValue());
} else if (headerValue instanceof Integer) {
Integer value = (Integer) headerValue;
// Check real content length.
if ("Content-Length".equals(header)) {
if (realContentLength <= 0) {
realContentLength = value.intValue();
} else {
//do nothing
}
} else {
response.setIntHeader(header, value.intValue());
}
} else {
// Don't send "chunked" transfer-encoding type with real content-length
if (!(realContentLength > 0
&& "Transfer-Encoding".equals(header) && "chunked"
.equals(headerValue))) {
response.setHeader(header, (String) headerValue);
}
}
} catch (Exception e) {
_log.error("Error set response header " + header + "for value "
+ headerValue, e);
}
if(realContentLength > 0){
response.setContentLength(realContentLength);
}
if (null != contentType) {
response.setContentType(this.contentType);
}
}
}
public void setDateHeader(String name, long value) {
// Expires not stored in cache - must be re-calculated for every
// response.
if (!"Expires".equals(name)) {
headers.put(name, new Long(value));
}
}
/*
* (non-Javadoc)
*
* @see org.ajax4jsf.framework.resource.ResourceContext#setHeader(java.lang.String,
* java.lang.String)
*/
public void setHeader(String name, String value) {
headers.put(name, value);
}
/*
* (non-Javadoc)
*
* @see org.ajax4jsf.framework.resource.ResourceContext#setIntHeader(java.lang.String,
* int)
*/
public void setIntHeader(String name, int value) {
headers.put(name, new Integer(value));
}
/**
* Create UNIX command 'tee' like stream - send all data to servlet
*
* @param responseStream
* @return
*/
public OutputStream getOutputStream() {
if (null == servletStream) {
outputStream = new FastBufferOutputStream(1024);
servletStream = new ServletOutputStream() {
/*
* (non-Javadoc)
*
* @see java.io.OutputStream#close()
*/
public void close() throws IOException {
filledOutputStream = true;
// / content = outputStream.toByteArray();
content = null;
}
/*
* (non-Javadoc)
*
* @see java.io.OutputStream#flush()
*/
public void flush() throws IOException {
}
/*
* (non-Javadoc)
*
* @see java.io.OutputStream#write(byte[], int, int)
*/
public void write(byte[] b, int off, int len)
throws IOException {
outputStream.write(b, off, len);
}
/*
* (non-Javadoc)
*
* @see java.io.OutputStream#write(byte[])
*/
public void write(byte[] b) throws IOException {
outputStream.write(b);
}
public void write(int b) throws IOException {
outputStream.write(b);
}
};
}
return servletStream;
}
public PrintWriter getWriter() {
if (null == servletWriter) {
stringOutputWriter = new FastBufferWriter(1024);
Writer out = new Writer() {
public void write(char[] cbuf, int off, int len)
throws IOException {
stringOutputWriter.write(cbuf, off, len);
}
public void flush() throws IOException {
}
public void close() throws IOException {
// / writerContent = stringOutputWriter.toString();
filledOutputWriter = true;
writerContent = null;
}
};
servletWriter = new PrintWriter(out);
}
return servletWriter;
}
public void setContentType(String contentType) {
this.contentType = contentType;
}
/**
* @return Returns the contentType.
*/
public String getContentType() {
return contentType;
}
private void writeObject(java.io.ObjectOutputStream s) throws IOException {
if (filledOutputStream) {
if (outputStream != null) {
content = outputStream.toByteArray();
}
} else if (filledOutputWriter) {
if (stringOutputWriter != null) {
char[] cs = stringOutputWriter.toCharArray();
writerContent = new String(cs);
}
}
s.defaultWriteObject();
}
/**
* Flush used output writer/stream, to fix https://jira.jboss.org/jira/browse/RF-4017
* @param response
* @throws IOException
*/
public void flush(HttpServletResponse response) throws IOException {
if (filledOutputStream) {
OutputStream out = response.getOutputStream();
out.flush();
} else if (filledOutputWriter) {
Writer out = response.getWriter();
out.flush();
}
}
public int getContentLength() {
if (contentLength == null) {
throw new IllegalStateException("Content length hasn't been set yet!");
}
return contentLength.intValue();
}
public void setContentLength(int contentLength) {
this.contentLength = contentLength;
}
}