Code Snippets
ServletFilter that creates a chain of XMLFilter(s)
a class that extends ServletFilter that can make a chain of XMLFilter objects apply to the output. The basic idea is that you can infinitely add SAX Filters to the Xml before it is output. I had a need to do this for a while with something resembling a rules engine. The idea was to store all information about fields in a seperate configuration - such as required, length etc... and use that information to effect the html output
package org.klangworks;
import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.ListIterator;
import java.util.Enumeration;
import java.util.StringTokenizer;
import java.io.CharArrayWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringReader;
import org.xml.sax.XMLReader;
import org.xml.sax.XMLFilter;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.SAXNotSupportedException;
import org.xml.sax.DTDHandler;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.xml.sax.InputSource;
import org.xml.sax.Attributes;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.AttributesImpl;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import org.apache.log4j.Logger;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.TransformerException;
import org.xml.sax.helpers.XMLFilterImpl;
/**
* Servlet Filter to apply XMLFilters to the content
* before it is sent to the browser
*
*@author rob nelson
*@created August 4, 2005
*/
public class XMLServletFilter implements Filter {
private FilterConfig filterConfig = null;
private SAXParser parser;
private XMLReader reader;
private Transformer transformer;
private String contentType;
private String filterStr;
private List filters;
private XMLFilter theFilter;
/**
* Log4j Logger
*/
public static Logger logger =
Logger.getLogger("net.klangworks.XMLServletFilter");
/**
* Initialization routine. Reads parameters from web.xml
* sets up the parsers and reads in and creates all the
* XMLFilter[] filters
*
*@param filterConfig The web.xml configuration info
*@exception ServletException Exception on the servlet
*/
public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig = filterConfig;
filterStr = filterConfig.getInitParameter("filters");
contentType = filterConfig.getInitParameter("content-type");
filters = new ArrayList();
try {
StringTokenizer st = new StringTokenizer(filterStr, ",");
while (st.hasMoreTokens()) {
Class clazz = Class.forName(st.nextToken());
XMLFilter filter = (XMLFilter) clazz.newInstance();
filters.add(filter);
}
SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setNamespaceAware(true);
parser = spf.newSAXParser();
reader = parser.getXMLReader();
SAXTransformerFactory stf =
(SAXTransformerFactory) TransformerFactory.newInstance();
transformer = stf.newTransformer();
transformer.setOutputProperty(
javax.xml.transform.OutputKeys.OMIT_XML_DECLARATION,
"yes");
XMLFilter[] filterArray = (XMLFilter[]) filters.toArray(new XMLFilter[0]);
filterArray[0].setParent(reader);
int size = filterArray.length;
int flag = 1;
while (flag < size) {
filterArray[1].setParent(filterArray[flag - 1]);
flag++;
}
theFilter = filterArray[size - 1];
} catch (Exception e) {
throw new ServletException(e);
}
}
/**
* What to do when the filter is applied. The will be called
* for every page it is applied ot
*
*@param request HttpRequest
*@param response HttpResponse
*@param chain The existing chain of filters
*@exception IOException an exception with I/O
*@exception ServletException a servlet wide exception
*/
public void doFilter(
ServletRequest request,
ServletResponse response,
FilterChain chain)
throws IOException, ServletException {
response.setContentType(contentType);
CharResponseWrapper wrapper =
new CharResponseWrapper((HttpServletResponse) response);
chain.doFilter(request, wrapper);
logger.debug("trying to run XMLServletFilter");
try {
InputSource source =
new InputSource(new StringReader(wrapper.toString()));
SAXSource saxSource = new SAXSource(theFilter, source);
StreamResult result = new StreamResult(response.getWriter());
transformer.transform(saxSource, result);
} catch (TransformerException tfe) {
throw new ServletException(tfe);
}
}
/**
* What happens when the Filter is removed
*/
public void destroy() {
this.filterConfig = null;
}
}
It requires this simple class:
package org.klangworks;
import java.io.CharArrayWriter;
import java.io.PrintWriter;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
/**
* A Wrapper around a Servlet Response so we can intercept it and write
* something else
*
*@author robnelson
*@created August 2, 2005
*/
public class CharResponseWrapper extends HttpServletResponseWrapper {
private CharArrayWriter output;
/**
* Get the output as a String
*
*@return A string representation of the output
*/
public String toString() {
return output.toString();
}
/**
* Constructor
*
*@param response The response to wrap
*/
public CharResponseWrapper(HttpServletResponse response) {
super(response);
output = new CharArrayWriter();
}
/**
* Gets the writer attribute of the CharResponseWrapper object
*
*@return The writer value
*/
public PrintWriter getWriter() {
return new PrintWriter(output);
}
}
04/28/06