xsltfilter.java

来自「RESIN 3.2 最新源码」· Java 代码 · 共 473 行

JAVA
473
字号
/* * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved * * This file is part of Resin(R) Open Source * * Each copy or derived work must preserve the copyright notice and this * notice unmodified. * * Resin Open Source is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Resin Open Source 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, or any warranty * of NON-INFRINGEMENT.  See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with Resin Open Source; if not, write to the *   Free SoftwareFoundation, Inc. *   59 Temple Place, Suite 330 *   Boston, MA 02111-1307  USA * * @author Scott Ferguson */package com.caucho.filters;import com.caucho.loader.DynamicClassLoader;import com.caucho.log.Log;import com.caucho.server.connection.CauchoRequest;import com.caucho.server.connection.RequestAdapter;import com.caucho.util.CompileException;import com.caucho.util.L10N;import com.caucho.vfs.MergePath;import com.caucho.vfs.Path;import com.caucho.vfs.ReadStream;import com.caucho.vfs.TempStream;import com.caucho.vfs.Vfs;import com.caucho.vfs.WriteStream;import com.caucho.xml.Xml;import com.caucho.xml.XmlUtil;import com.caucho.xpath.XPath;import com.caucho.xpath.XPathException;import com.caucho.xsl.AbstractStylesheetFactory;import com.caucho.xsl.CauchoStylesheet;import com.caucho.xsl.StyleScript;import com.caucho.xsl.TransformerImpl;import org.w3c.dom.Document;import org.w3c.dom.ProcessingInstruction;import javax.servlet.*;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.xml.transform.OutputKeys;import javax.xml.transform.Result;import javax.xml.transform.Source;import javax.xml.transform.Templates;import javax.xml.transform.Transformer;import javax.xml.transform.TransformerFactory;import javax.xml.transform.dom.DOMSource;import javax.xml.transform.stream.StreamResult;import javax.xml.transform.stream.StreamSource;import java.io.IOException;import java.io.OutputStream;import java.net.URL;import java.util.ArrayList;import java.util.logging.Level;import java.util.logging.Logger;/** * Sends the results of the servlet through XSLT. * * @since Resin 2.0.6 */public class XsltFilter implements Filter {  private static final L10N L = new L10N(XsltFilter.class);  private static final Logger log = Log.open(XsltFilter.class);    private String _mimeType = "x-application/xslt";  private MergePath _stylePath;  private ServletContext _application;  private boolean _isConditional = true;  public void setMimeType(String mimeType)  {    _mimeType = mimeType;  }  public void setUnconditional(boolean isUnconditional)  {    _isConditional = ! isUnconditional;  }    public void init(FilterConfig config)    throws ServletException  {    _stylePath = new MergePath();    _stylePath.addMergePath(Vfs.lookup());    DynamicClassLoader loader;    loader = (DynamicClassLoader) Thread.currentThread().getContextClassLoader();    String resourcePath = loader.getResourcePathSpecificFirst();    _stylePath.addClassPath(resourcePath);    _application = config.getServletContext();    if ("true".equals(config.getInitParameter("unconditional")))      _isConditional = false;  }    /**   * Creates a wrapper to compress the output.   */  public void doFilter(ServletRequest request, ServletResponse response,                       FilterChain nextFilter)    throws ServletException, IOException  {    HttpServletRequest req = (HttpServletRequest) request;    HttpServletResponse res = (HttpServletResponse) response;    XsltResponse xsltResponse = new XsltResponse(req, res);    nextFilter.doFilter(req, xsltResponse);    xsltResponse.finish(req, res);  }    /**   * Any cleanup for the filter.   */  public void destroy()  {  }  class XsltResponse extends CauchoResponseWrapper {    private HttpServletRequest _request;    private XsltTempStream _xsltStream;    private String _chainingType;        XsltResponse(HttpServletRequest request, HttpServletResponse response)    {      super(response);      _request = request;    }    /**     * This needs to be bypassed because the file's content     * length has nothing to do with the returned length.     */    public void setContentLength(int length)    {    }    /**     * Sets the content type of the filter.     */    public void setContentType(String contentType)    {      super.setContentType(contentType);      int p = contentType.indexOf(';');      if (p > 0)        contentType = contentType.substring(0, p);      if (! _isConditional ||	  contentType.equals("x-application/xslt") ||          contentType.equals("x-application/xsl") ||          contentType.equals("x-application/stylescript")) {        _chainingType = contentType;	if (log.isLoggable(Level.FINER))	  log.finer(L.l("'{0}' chaining xslt with {1}",			_request.getRequestURI(), contentType));        if (_xsltStream == null)          _xsltStream = new XsltTempStream(_response);                _xsltStream.setChaining();      }    }    /**     * Calculates and returns the proper stream.     */    protected OutputStream getStream() throws IOException    {      if (_xsltStream == null)        _xsltStream = new XsltTempStream(_response);      return _xsltStream;    }    /**     * Flushes the stream's buffer.     */    public void flushBuffer()      throws IOException    {      super.flushBuffer();            if (_stream != null)	_stream.flush();    }    /**     * Complets the request.     */    public void finish(HttpServletRequest req,                       HttpServletResponse res)      throws IOException, ServletException    {      try {	flushBuffer();        if (_chainingType == null)          return;        TempStream ts = _xsltStream.getTempStream();        Document doc = null;                ReadStream is = ts.openRead();        Path userPath = Vfs.lookup();        if (req instanceof CauchoRequest)          userPath.setUserPath(((CauchoRequest) req).getPageURI());        else          userPath.setUserPath(req.getRequestURI());        is.setPath(userPath);        try {          doc = new Xml().parseDocument(is);        } finally {          is.close();        }              String href = (String) req.getAttribute("caucho.xsl.stylesheet");        if (href == null)          href = getStylesheetHref(doc);	        if (href == null)          href = "default.xsl";        Templates stylesheet = null;                //Path path = Vfs.lookup(href);        try {          //ReadStream sis = path.openReadAndSaveBuffer();          TransformerFactory factory;                    if (_chainingType.equals("x-application/stylescript"))            factory = new StyleScript();          else {            factory = TransformerFactory.newInstance();	  }	  if (factory instanceof AbstractStylesheetFactory)	    ((AbstractStylesheetFactory) factory).setStylePath(_stylePath);	  Path path = null;	  	  if (href.startsWith("/"))	    path = Vfs.getPwd().lookup(_application.getRealPath(href));	  else {	    String servletPath = RequestAdapter.getPageServletPath(req);	  	    Path pwd = Vfs.getPwd();	    pwd = pwd.lookup(_application.getRealPath(servletPath));	    path = pwd.getParent().lookup(href);	  }	  if (! path.canRead()) {	    Thread thread = Thread.currentThread();	    ClassLoader loader = thread.getContextClassLoader();	    	    URL url = loader.getResource(href);	    if (url != null) {	      Path newPath = Vfs.getPwd().lookup(url.toString());	      if (newPath.canRead())		path = newPath;	    }	  }	  	  Source source;	  if (path.canRead())	    source = new StreamSource(path.getURL());	  else	    source = new StreamSource(href);	  if (log.isLoggable(Level.FINE))	    log.fine(L.l("'{0}' XSLT filter using stylesheet {1}",			 req.getRequestURI(), source.getSystemId()));	  stylesheet = factory.newTemplates(source);        } finally {          // is.close();        }                Transformer transformer = null;        transformer = (Transformer) stylesheet.newTransformer();	TransformerImpl cauchoTransformer = null;	if (transformer instanceof TransformerImpl)	  cauchoTransformer = (TransformerImpl) transformer;        String mediaType = (String) transformer.getOutputProperty(OutputKeys.MEDIA_TYPE);        String encoding = (String) transformer.getOutputProperty(OutputKeys.ENCODING);        String method = (String) transformer.getOutputProperty(OutputKeys.METHOD);        if (encoding != null) {        }        else if (method == null) {        }        else if (method.equals("xml"))          encoding = "UTF-8";        if (encoding != null) {          if (mediaType == null)            mediaType = "text/html";          res.setContentType(mediaType + "; charset=" + encoding);        }        else if (mediaType != null)          res.setContentType(mediaType);        else          res.setContentType("text/html");        if (encoding == null)          encoding = "ISO-8859-1";        transformer.setOutputProperty(OutputKeys.ENCODING, encoding);	ArrayList params = null;;	if (cauchoTransformer != null) {	  params = (ArrayList) cauchoTransformer.getProperty(CauchoStylesheet.GLOBAL_PARAM);	}        for (int i = 0; params != null && i < params.size(); i++) {          String param = (String) params.get(i);                  transformer.setParameter(param, req.getParameter(param));        }	DOMSource domSource = new DOMSource(doc);	domSource.setSystemId(userPath.getUserPath());	Result result = getResult(res.getOutputStream());        transformer.transform(domSource, result);      } catch (IOException e) {        throw e;      } catch (Exception e) {        if (e instanceof CompileException)	  throw new ServletException(e.getMessage(), e);	else	  throw new ServletException(e.toString(), e);      }    }    /**     * Returns the result object.     */    protected Result getResult(OutputStream out)    {      return new StreamResult(out);    }    /**     * Returns the stylesheet specified by the page.     *     * The syntax is:     * <pre>     *  &lt;?xml-stylesheet href='...'?>     * </pre>     *     * @return the href of the xml-stylesheet processing-instruction or      * "default.xsl" if none is found.     */    private String getStylesheetHref(Document doc)      throws XPathException    {      ProcessingInstruction pi = null;      pi = (ProcessingInstruction) XPath.find("//processing-instruction('xml-stylesheet')", doc);            if (pi == null)        return null;      String value = pi.getNodeValue();          return XmlUtil.getPIAttribute(value, "href");    }  }    static class XsltTempStream extends OutputStream {    private ServletResponse _response;    private OutputStream _os;        private TempStream _tempStream;    XsltTempStream(ServletResponse response)    {      _response = response;    }    void setChaining()    {      if (_os != null)        throw new IllegalStateException(L.l("setContentType for XSLT chaining must be before any data."));            _tempStream = new TempStream();      _tempStream.openWrite();      _os = new WriteStream(_tempStream);    }    TempStream getTempStream()      throws IOException    {      if (_tempStream != null) {        _os.close();        _os = null;      }            return _tempStream;    }    /**     * Writes a buffer to the underlying stream.     *     * @param ch the byte to write     */    public void write(int ch)      throws IOException    {      if (_os == null)        _os = _response.getOutputStream();      _os.write(ch);    }    /**     * Writes a buffer to the underlying stream.     *     * @param buffer the byte array to write.     * @param offset the offset into the byte array.     * @param length the number of bytes to write.     */    public void write(byte []buffer, int offset, int length)      throws IOException    {      if (_os == null)        _os = _response.getOutputStream();      _os.write(buffer, offset, length);    }    public void flush()      throws IOException    {      if (_os == null)        _os = _response.getOutputStream();      _os.flush();    }  }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?