package org.python.util;
import java.io.File;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.python.core.PyException;
import org.python.util.PythonInterpreter;
/**
* Enables you to write Jython modules that inherit from javax.servlet.Filter, and to
* insert them in your servlet container's filter chain, like any Java Filter.
*
*
* Example: * *
* /WEB-INF/filters/HeaderFilter.py: * *
* from javax.servlet import Filter
*
* # Module must contain a class with the same name as the module
* # which in turn must implement javax.servlet.Filter
* class HeaderFilter (Filter):
* def init(self, config):
* self.header = config.getInitParameter('header')
*
* def doFilter(self, request, response, chain):
* response.setHeader(self.header, "Yup")
* chain.doFilter(request, response)
*
*
* * web.xml: *
* ** <!-- Initialize the Jython runtime --> * <listener> * <listener-class>org.python.util.PyServletInitializer</listener-class> * <load-on-startup>1</load-on-startup> * </listener> * * <!-- Declare a uniquely-named PyFilter --> * <filter> * <filter-name>HeaderFilter</filter-name> * <filter-class>org.python.util.PyFilter</filter-class> * * <!-- The special param __filter__ gives the context-relative path to the Jython source file --> * <init-param> * <param-name>__filter__</param-name> * <param-value>/WEB-INF/pyfilter/HeaderFilter.py</param-value> * </init-param> * * <!-- Other params are passed on the the Jython filter --> * <init-param> * <param-name>header</param-name> * <param-value>X-LookMaNoJava</param-value> * </init-param> * </filter> * <filter-mapping> * <filter-name>HeaderFilter</filter-name> * <url-pattern>/*</url-pattern> * </filter-mapping> **/ public class PyFilter implements Filter { public static final String FILTER_PATH_PARAM = "__filter__"; public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { request.setAttribute("pyfilter", this); getFilter().doFilter(request, response, chain); } public void init(FilterConfig config) throws ServletException { if (config.getServletContext().getAttribute(PyServlet.INIT_ATTR) == null) { throw new ServletException("Jython has not been initialized. Add " + "org.python.util.PyServletInitializer as a listener to your " + "web.xml."); } this.config = config; String filterPath = config.getInitParameter(FILTER_PATH_PARAM); if (filterPath == null) { throw new ServletException("Missing required param '" + FILTER_PATH_PARAM + "'"); } source = new File(getRealPath(config.getServletContext(), filterPath)); if (!source.exists()) { throw new ServletException(source.getAbsolutePath() + " does not exist."); } interp = PyServlet.createInterpreter(config.getServletContext()); } private String getRealPath(ServletContext context, String appPath) { String realPath = context.getRealPath(appPath); // This madness seems to be necessary on Windows return realPath.replaceAll("\\\\", "/"); } private Filter getFilter() throws ServletException, IOException { if (cached == null || source.lastModified() > loadedMtime) { return loadFilter(); } return cached; } private Filter loadFilter() throws ServletException, IOException { loadedMtime = source.lastModified(); cached = PyServlet.createInstance(interp, source, Filter.class); try { cached.init(config); } catch (PyException e) { throw new ServletException(e); } return cached; } public void destroy() { if (cached != null) { cached.destroy(); } if (interp != null) { interp.cleanup(); } } private PythonInterpreter interp; private FilterConfig config; private File source; private Filter cached; private long loadedMtime; }