/** http://www43.tok2.com/home/mahkun/pg/java019.html */ import java.io.*; import java.util.*; import javax.servlet.*; import javax.servlet.http.*; import javax.xml.transform.*; import javax.xml.transform.stream.*; public class XSLTFilter implements Filter { private ServletContext ctx; private String xslt; private String forceConversion; private TransformerFactory factory = TransformerFactory.newInstance(); private Transformer defaultxslt; private String outputEncoding; private String ignoreDoctype; private static class ByteArrayServletStream extends ServletOutputStream { ByteArrayOutputStream baos; ByteArrayServletStream(ByteArrayOutputStream baos) { this.baos = baos; } public void write(int param) throws java.io.IOException { baos.write(param); } } private static class ByteArrayPrintWriter { private ByteArrayOutputStream baos = new ByteArrayOutputStream(); private PrintWriter pw = new PrintWriter(baos); private ServletOutputStream sos = new ByteArrayServletStream(baos); public PrintWriter getWriter() { return pw; } public ServletOutputStream getStream() { return sos; } byte[] toByteArray() { return baos.toByteArray(); } } /** * フィルタを初期化します。 * web.xmlで指定できる初期化パラメータは次の通りです。 * default-xsl XML文書でXSLスタイルシートが指定されていないときの * デフォルトのXSLファイル名。このファイルを編集したら、サーブレットコンテナ * の再起動が必要です。 * force-conversion 1の場合は入力がtext/xmlでなくても変換を行います。 * その他の値の場合は、text/xmlでなければ変換は行いません。 * ignore-doctype 1の場合は入力に含まれるDOCTYPE宣言を無視します。 * これはXercesのバージョンによって、DOCTYPE宣言が参照するdtdが * SAXParseExceptionを生じる場合に使ってください。 * output-encoding 出力ストリームのヘッダ(text/html;charset=) * につけるエンコーディング。デフォルトはShift_JISです。 */ public void init(FilterConfig fc) throws ServletException { ctx = fc.getServletContext(); xslt = fc.getInitParameter("default-xsl"); forceConversion = fc.getInitParameter("force-conversion"); ignoreDoctype = fc.getInitParameter("ignore-doctype"); outputEncoding = fc.getInitParameter("output-encoding"); if(outputEncoding == null){ outputEncoding = "Shift_JIS"; } /* パラメータxsltが指定されていれば、*/ /* これをデフォルトのXSLTスタイルシートとします */ if(xslt != null){ ctx.log("Filter " + fc.getFilterName() + " using xslt " + xslt); try { defaultxslt = factory.newTransformer(new StreamSource(ctx.getResourceAsStream(xslt))); } catch (Exception e) { ctx.log("Could not intialize transform", e); throw new ServletException("Could not initialize transform", e); } } else{ defaultxslt = null; } } public String httpReqLine(HttpServletRequest req) { StringBuffer ret = req.getRequestURL(); String query = req.getQueryString(); if (query != null) { ret.append("?").append(query); } return ret.toString(); } public String getHeaders(HttpServletRequest req) throws IOException { Enumeration en = req.getHeaderNames(); StringBuffer sb = new StringBuffer(); while (en.hasMoreElements()) { String name = (String) en.nextElement(); sb.append(name).append(": ").append(req.getHeader(name)).append("\n"); } return sb.toString(); } public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws java.io.IOException, ServletException { HttpServletRequest hsr = (HttpServletRequest)servletRequest; final HttpServletResponse resp = (HttpServletResponse)servletResponse; ctx.log("Accessing filter for " + httpReqLine(hsr) + " " + hsr.getMethod()); final ByteArrayPrintWriter pw = new ByteArrayPrintWriter(); final boolean[] transformNeeded = new boolean[1]; HttpServletResponse wrappedResp = new HttpServletResponseWrapper(resp) { public PrintWriter getWriter() { return pw.getWriter(); } public ServletOutputStream getOutputStream() { return pw.getStream(); } public void setContentType(String type) { if( (forceConversion != null && forceConversion.equals("1")) || type.indexOf("text/xml") >= 0) { ctx.log("Converting xml to html"); resp.setContentType("text/html;charset=" + outputEncoding); transformNeeded[0] = true; } else { ctx.log("Content-type=" + type + "... conversion is not applied."); resp.setContentType(type); } } }; filterChain.doFilter(servletRequest, wrappedResp); byte[] bytes; if(ignoreDoctype != null && ignoreDoctype.equals("1")){ byte[] origBytes = pw.toByteArray(); /* DOCTYPE宣言を削ります */ bytes = new byte[origBytes.length]; int j = 0; for(int i=0; i HTML conversion completed"); } catch (Exception e) { ctx.log("Unable to transform document " + e); throw new ServletException("Unable to transform document", e); } } else { ctx.log("Conversion is not needed."); resp.getOutputStream().write(bytes); } } public void destroy() { ctx.log("Destroying filter..."); } } /* end. */