styletag.java

来自「jakarta-taglibs」· Java 代码 · 共 361 行

JAVA
361
字号
/*
 * Copyright 1999,2004 The Apache Software Foundation.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.taglibs.xtags.xslt;

import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.InputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.servlet.ServletContext;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.BodyTagSupport;

import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.URIResolver;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource; 

import org.dom4j.Node;
import org.dom4j.Document;
import org.dom4j.io.DocumentSource;

import org.apache.taglibs.xtags.util.JspNestedException;
import org.apache.taglibs.xtags.util.URLHelper;

import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

/** A tag which performs an XSLT transformation on a given XML document
  *
  * @author James Strachan
  */
public class StyleTag extends BodyTagSupport implements ParameterAcceptingTag {
    
    /** The XML data resource. */
    private Object xml;

    /** The XSL stylesheet resource. */
    private Object xsl;

    /** The destination result of the XSLT transformation */
    private Result result;

    /** The XSLT output method, "xml", "html", "text" or whatever */
    private String outputMethod;

    /** XSLT parameters */
    private Map parameters;
    
    /** Indirection buffer, used to avoid flush problems with BodyContent */
    private StringWriter stringWriter;
    
    
    // ParameterAcceptingTag interface
    //-------------------------------------------------------------------------                
    public void setParameter(String name, Object value) {
        if ( parameters == null ) {
            parameters = new HashMap();
        }
        parameters.put( name, value );
    }
    

    // BodyTag interface
    //-------------------------------------------------------------------------                

    /** Evaluate the body content of this tag if 
      * we need to for either the XML or XSLT data; otherwise we skip it.
     *
     * @exception JspException if a JSP error occurs
     */
    public int doStartTag() throws JspException {
        parameters = null;
        return EVAL_BODY_TAG;
    }


    /** Extract the body if required for either the XML or XSLT
      *
      * @exception JspException if a JSP error has occurred
      */
    public int doAfterBody() throws JspException {
        if ( bodyContent != null ) {
            String text = bodyContent.getString().trim();
            if ( text.length() > 0 ) {
                if ( xsl == null ) {
                    xsl = new StringReader( text );
                }
                else if ( xml == null ) { 
                    xml = new StringReader( text );
                }
            }
        }        
	return SKIP_BODY;
    }


    /** Perform the transformation and render the output.
      *
      * @exception JspException if a JSP exception occurs
      */
    public int doEndTag() throws JspException {
        if ( xml == null || xsl == null ) {
            throw new JspException( "Must specify both XML and an XSLT to style" );
        }
        
        // Prepare an input source for the data
        Source data = getSource(xml);

        // Prepare an input source for the stylesheet
        Source style = getSource(xsl);

        // Prepare an output source for the outputs
        Result result = getResult();

        // Use JAXP to perform the stylesheet
        try {
            TransformerFactory factory = TransformerFactory.newInstance();
            factory.setURIResolver( createURIResolver() );
            Transformer transformer = factory.newTransformer(style);
            configure(transformer);
            transformer.transform( data, result );
            if ( stringWriter != null ) {
                pageContext.getOut().write( stringWriter.toString() );
            }
        } 
        catch (TransformerException e) {
            handleException(e);
        }
        catch (IOException e) {
            handleException(e);
        }
        finally {
            stringWriter = null;
        }
	return EVAL_PAGE;
    }

    
    /**
     * Release any allocated resources.
     */
    public void release() {
	xml = null;
	xsl = null;
	result = null;
        parameters = null;
    }



    // Properties
    //-------------------------------------------------------------------------                
    
    public void setOutputMethod(String outputMethod) {
        this.outputMethod = outputMethod;
    }
    
    /** Sets the dom4j document to be styled */
    public void setDocument(Document document) {
        this.xml = document;
    }

    /** Sets the XSLT transformer used to transform the document */
    public void setTransformer(Transformer transformer) {
        this.xsl = transformer;
    }

    /** Sets the JAXP Result instance to 
      */
    public void setResult(Result result) {
        this.result = result;
    }

    /** Sets where the output is written to
      */
    public void setWriter(Writer writer) {
        setResult( new StreamResult( writer ) );
    }

    /** Sets the SAX ContentHandler that the output is written to */
    public void setResultHandler(ContentHandler handler) {
        setResult( new SAXResult( handler ) );
    }

    /** Sets the XML URL that the input document is read from */
    public void setXml(String xml) {
	this.xml = xml;
    }

    /** Sets the source of the XML document */
    public void setXmlSource(Source source) {
        this.xml = source;
    }

    public void setXmlReader(Reader reader) {
        this.xml = reader;
    }

    /** Sets the XSL URL that the stylesheet is read from */
    public void setXsl(String xsl) {
	this.xsl = xsl;
    }

    public void setXslReader(Reader reader) {
	this.xsl = reader;
    }

    /** Sets the source of the XML document */
    public void setXslSource(Source source) {
        this.xsl = source;
    }




    // Implementation methods
    //-------------------------------------------------------------------------                    

    /** Configures the Transformer before use 
      */
    protected void configure(Transformer transformer) {
        if ( outputMethod != null ) {
            transformer.setOutputProperty( OutputKeys.METHOD, outputMethod );
        }
        if ( parameters != null ) {
            for ( Iterator iter = parameters.entrySet().iterator(); iter.hasNext(); ) {
                Map.Entry entry = (Map.Entry) iter.next();
                String name = entry.getKey().toString();
                Object value = entry.getValue();
                transformer.setParameter( name, value );
            }
        }
    }

    /** Construct and return a JAXP Source to read the XML data to be styled.
      *
      * @param source is the object to be converted into a JAXP Source
      * @exception JspException if a JSP error occurs
      */
    protected Source getSource(Object source) throws JspException {
        if (source instanceof Source) {
	    return (Source) source;
        }
        else if (source instanceof Reader) {
	    return new StreamSource((Reader) source);
        }
        else if (source instanceof String) {
            try {
                URL url = URLHelper.createURL( (String) source, pageContext );
                if ( url == null ) {
                    throw new JspException("Bad URL: " + source + ".");
                }
                return new StreamSource(url.openStream(), url.toExternalForm());
            }
            catch (IOException e) {
                throw new JspException( 
                    "Bad URL: " + source + ". Exception: " + e.getMessage() 
                );
            }
        }
        else if (source instanceof Node) {
	    return new DocumentSource((Node) source);
        }
        else if (source instanceof org.w3c.dom.Node) {
	    return new DOMSource((org.w3c.dom.Node) source);
        }
        else if (source instanceof InputSource) {
	    return new SAXSource((InputSource) source);
        }
        else if ( source == null ) {
	    throw new JspException( "No XSLT source specified" );
        }
        else {
	    throw new JspException(
                "Invalid input source type '" + source.getClass().getName() + "'"
            );
        }
    }
 
    /** Construct and return a JAXP Result
      *
      * @exception JspException if a JSP error occurs
      */
    protected Result getResult() throws JspException {
        if ( result == null ) {
            // use StringWriter to avoid flushing problems with BodyContent
            stringWriter = new StringWriter();
            return new StreamResult( stringWriter );
        }
        else {
            stringWriter = null;
        }
        return result;
    }
    
    /** Creates a URI resolver capable of resolving URIs when used in XSLT includes or imports */
    protected URIResolver createURIResolver() {
        return new URIResolver() {
            public Source resolve(String href, String base)
               throws TransformerException {
                try {
                    return getSource(href);
                }
                catch(javax.servlet.jsp.JspException e) {
                    return null;
                }
            }

        };
    }

    /** Handles non-JspExceptions thrown in this instance
      */
    protected void handleException( Exception e ) throws JspException {
        if ( e instanceof JspException ) {
            throw (JspException) e;
        }
        else {
            pageContext.getServletContext().log( e.getMessage(), e );
            e.printStackTrace();
            throw new JspNestedException( e );
        }
    }
}

⌨️ 快捷键说明

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