package com.idega.servlet.filter;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.StringWriter;
import java.util.Calendar;
import java.util.Enumeration;
import java.util.Locale;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Class to use for generic caching of output from .jsps or Servlets.<br>
* Accepts the following init parameters:
*
* <filter-mapping>
* <filter-name>CacheFilter</filter-name>
* <url-pattern>*.jsp</url-pattern>
* <init-param>
* <param-name>/time.jsp</param-name>
* <param-value>nocache</param-value>
* </init-param>
* <init-param>
* <param-name>cacheTimeout</param-name>
* <param-value>1</param-value>
* </init-param>
* </filter-mapping>
*
* @author tryggvil
*/
public class CacheFilter implements Filter {
ServletContext sc;
FilterConfig fc;
long cacheTimeout = Long.MAX_VALUE;
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
// check if was a resource that shouldn't be cached.
String r = this.sc.getRealPath("");
String path = this.fc.getInitParameter(request.getRequestURI());
if (path!= null && path.equals("nocache")) {
chain.doFilter(request, response);
return;
}
path = r+path;
// customize to match parameters
String id = request.getRequestURI()+request.getQueryString();
// optionally append i18n sensitivity
String localeSensitive = this.fc.getInitParameter("locale-sensitive");
if (localeSensitive != null) {
StringWriter ldata = new StringWriter();
Enumeration locales = request.getLocales();
while (locales.hasMoreElements()) {
Locale locale = (Locale)locales.nextElement();
ldata.write(locale.getISO3Language());
}
id = id + ldata.toString();
}
File tempDir = (File)this.sc.getAttribute(
"javax.servlet.context.tempdir");
// get possible cache
String temp = tempDir.getAbsolutePath();
File file = new File(temp+id);
// get current resource
if (path == null) {
path = this.sc.getRealPath(request.getRequestURI());
}
File current = new File(path);
try {
long now = Calendar.getInstance().getTimeInMillis();
//set timestamp check
if (!file.exists() || (file.exists() &&
current.lastModified() > file.lastModified()) ||
this.cacheTimeout < now - file.lastModified()) {
String name = file.getAbsolutePath();
name = name.substring(0,name.lastIndexOf("/")==-1?0:name.lastIndexOf("/"));
new File(name).mkdirs();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
CacheResponseWrapper wrappedResponse =
new CacheResponseWrapper(response, baos);
chain.doFilter(req, wrappedResponse);
FileOutputStream fos = new FileOutputStream(file);
fos.write(baos.toByteArray());
fos.flush();
fos.close();
}
} catch (ServletException e) {
if (!file.exists()) {
throw new ServletException(e);
}
}
catch (IOException e) {
if (!file.exists()) {
throw e;
}
}
FileInputStream fis = new FileInputStream(file);
String mt = this.sc.getMimeType(request.getRequestURI());
response.setContentType(mt);
ServletOutputStream sos = res.getOutputStream();
for (int i = fis.read(); i!= -1; i = fis.read()) {
sos.write((byte)i);
}
}
public void init(FilterConfig filterConfig) {
this.fc = filterConfig;
String ct = this.fc.getInitParameter("cacheTimeout");
if (ct != null) {
this.cacheTimeout = 60*1000*Long.parseLong(ct);
}
this.sc = filterConfig.getServletContext();
}
public void destroy() {
this.sc = null;
this.fc = null;
}
}