/* * Copyright (c) 1998-2011 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.jstl.rt; import com.caucho.jsp.PageContextImpl; import com.caucho.jstl.NameValueTag; import com.caucho.server.webapp.WebApp; import com.caucho.util.L10N; import com.caucho.vfs.*; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import javax.servlet.http.HttpServletRequest; import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspWriter; import javax.servlet.jsp.tagext.BodyContent; import javax.servlet.jsp.tagext.BodyTagSupport; import javax.xml.transform.Result; import javax.xml.transform.Source; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMResult; 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.InputStream; import java.io.Reader; import java.io.Writer; import java.util.ArrayList; import java.util.logging.Logger; public class XmlTransformTag extends BodyTagSupport implements NameValueTag { private static final Logger log = Logger.getLogger(XmlTransformTag.class.getName()); private static final L10N L = new L10N(XmlTransformTag.class); private Object _xml; private Object _xslt; private String _xmlSystemId; private String _xsltSystemId; private String _var; private String _scope; private Object _result; private ArrayList<String> _paramNames = new ArrayList<String>(); private ArrayList<String> _paramValues = new ArrayList<String>(); /** * Sets the JSP-EL XML value. */ public void setDoc(Object xml) { _xml = xml; } /** * Sets the JSP-EL XML value. */ public void setXml(Object xml) { setDoc(xml); } /** * Sets the JSP-EL XML value. */ public void setXslt(Object xslt) { _xslt = xslt; } /** * Sets the JSP-EL XML system id expr. */ public void setXmlSystemId(String xmlSystemId) { _xmlSystemId = xmlSystemId; } /** * Sets the JSP-EL XML system id expr. */ public void setDocSystemId(String docSystemId) { _xmlSystemId = docSystemId; } /** * Sets the JSP-EL XSLT system id. */ public void setXsltSystemId(String xsltSystemId) { _xsltSystemId = xsltSystemId; } /** * Sets the variable */ public void setVar(String var) { _var = var; } /** * Sets the scope */ public void setScope(String scope) { _scope = scope; } /** * Sets the result */ public void setResult(Object result) { _result = result; } /** * Adds a parameter. */ public void addParam(String name, String value) { _paramNames.add(name); _paramValues.add(value); } /** * Process the tag. */ public int doStartTag() throws JspException { _paramNames.clear(); _paramValues.clear(); return super.doStartTag(); } /** * Process the tag. */ public int doEndTag() throws JspException { try { PageContextImpl pageContext = (PageContextImpl) this.pageContext; JspWriter out = pageContext.getOut(); TransformerFactory factory = TransformerFactory.newInstance(); String xsltSystemId = getCanonicalURL(pageContext, _xsltSystemId); Source source = getSource(_xslt, xsltSystemId); Transformer transformer = factory.newTransformer(source); // transformer.setOutputProperty("omit-xml-declaration", "yes"); for (int i = 0; i < _paramNames.size(); i++) { String name = _paramNames.get(i); String value = _paramValues.get(i); transformer.setParameter(name, value); } if (_xml != null) source = getSource(_xml, getCanonicalURL(pageContext, _xmlSystemId)); else { BodyContent body = getBodyContent(); TempCharReader tempReader = (TempCharReader) body.getReader(); int ch; while (Character.isWhitespace((ch = tempReader.read()))) { } if (ch >= 0) tempReader.unread(); source = new StreamSource(tempReader); if (_xmlSystemId != null) source.setSystemId(getCanonicalURL(pageContext, _xmlSystemId)); else source.setSystemId(((HttpServletRequest) pageContext.getRequest()).getRequestURI()); } Result result; Node top = null; if (_result != null) { result = (Result) _result; } else if (_var != null) { top = new com.caucho.xml.QDocument(); result = new DOMResult(top); } else { result = new StreamResult(new WriterWrapper(out)); } transformer.transform(source, result); if (_var != null) CoreSetTag.setValue(pageContext, _var, _scope, top); } catch (Exception e) { throw new JspException(e); } return SKIP_BODY; } /** * Returns the ML source. */ private Source getSource(Object xml, String systemId) throws JspException { PageContextImpl pageContext = (PageContextImpl) this.pageContext; Object xmlObj = xml; Source source = null; if (xmlObj instanceof String) { ReadStream is = Vfs.openString((String) xmlObj); source = new StreamSource(is, systemId); } else if (xmlObj instanceof InputStream) { source = new StreamSource((InputStream) xmlObj, systemId); } else if (xmlObj instanceof Reader) { source = new StreamSource((Reader) xmlObj, systemId); } else if (xmlObj instanceof Node) { source = new DOMSource((Node) xmlObj, systemId); } else if (xmlObj instanceof NodeList) { source = new DOMSource(((NodeList) xmlObj).item(0), systemId); } else if (xmlObj instanceof Source) source = (Source) xmlObj; else throw new JspException(L.l("unknown xml object type `{0}'", xmlObj)); return source; } private String getCanonicalURL(PageContextImpl pageContext, String url) { WebApp app = pageContext.getApplication(); Path appDir = pageContext.getApplication().getRootDirectory(); if (url != null) { if (url.startsWith("/")) url = app.getRealPath(url); else if (url.indexOf(':') > 0 && url.indexOf(':') < url.indexOf('/')) { } else { url = pageContext.getRequest().getRealPath(url); } url = appDir.lookup(url).getURL(); } return url; } static class WriterWrapper extends Writer { private JspWriter _out; WriterWrapper(JspWriter out) { _out = out; } public void write(char []buf, int off, int len) throws IOException { _out.write(buf, off, len); } public void write(int ch) throws IOException { _out.write(ch); } public void write(String s) throws IOException { _out.write(s); } public void write(String s, int off, int len) throws IOException { _out.write(s, off, len); } public void flush() { } public void close() { } } }