blob: 0649909838ee523bcbf68a8a889ecd2409511226 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.standard.tag.common.xml;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspTagException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.BodyTagSupport;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.sax.TransformerHandler;
import org.apache.taglibs.standard.resources.Resources;
import org.apache.taglibs.standard.tag.common.core.Util;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLFilter;
import org.xml.sax.XMLReader;
/**
* <p>Support for tag handlers for &lt;parse&gt;, the XML parsing tag.</p>
*
* @author Shawn Bayern
*/
public abstract class ParseSupport extends BodyTagSupport {
//*********************************************************************
// Protected state
protected Object xml; // 'xml' attribute
protected String systemId; // 'systemId' attribute
protected XMLFilter filter; // 'filter' attribute
//*********************************************************************
// Private state
private String var; // 'var' attribute
private String varDom; // 'varDom' attribute
private int scope; // processed 'scope' attr
private int scopeDom; // processed 'scopeDom' attr
private XmlUtil.JstlEntityResolver entityResolver;
//*********************************************************************
// Constructor and initialization
public ParseSupport() {
super();
init();
}
private void init() {
var = varDom = null;
xml = null;
systemId = null;
filter = null;
scope = PageContext.PAGE_SCOPE;
scopeDom = PageContext.PAGE_SCOPE;
}
//*********************************************************************
// Tag logic
// parse 'source' or body, storing result in 'var'
@Override
public int doEndTag() throws JspException {
// produce a Document by parsing whatever the attributes tell us to use
Object xmlText = this.xml;
if (xmlText == null) {
// if the attribute was specified, use the body as 'xml'
if (bodyContent != null && bodyContent.getString() != null) {
xmlText = bodyContent.getString().trim();
} else {
xmlText = "";
}
}
if (xmlText instanceof String) {
xmlText = new StringReader((String) xmlText);
}
if (!(xmlText instanceof Reader)) {
throw new JspTagException(Resources.getMessage("PARSE_INVALID_SOURCE"));
}
InputSource source = XmlUtil.newInputSource(((Reader) xmlText), systemId);
Document d;
if (filter != null) {
d = parseInputSourceWithFilter(source, filter);
} else {
d = parseInputSource(source);
}
// we've got a Document object; store it out as appropriate
// (let any exclusivity or other constraints be enforced by TEI/TLV)
if (var != null) {
pageContext.setAttribute(var, d, scope);
}
if (varDom != null) {
pageContext.setAttribute(varDom, d, scopeDom);
}
return EVAL_PAGE;
}
// Releases any resources we may have (or inherit)
@Override
public void release() {
init();
}
//*********************************************************************
// Private utility methods
/**
* Parses the given InputSource after, applying the given XMLFilter.
*/
private Document parseInputSourceWithFilter(InputSource s, XMLFilter f) throws JspException {
try {
XMLReader xr = XmlUtil.newXMLReader(entityResolver);
// (note that we overwrite the filter's parent. this seems
// to be expected usage. we could cache and reset the old
// parent, but you can't setParent(null), so this wouldn't
// be perfect.)
f.setParent(xr);
TransformerHandler th = XmlUtil.newTransformerHandler();
Document o = XmlUtil.newEmptyDocument();
th.setResult(new DOMResult(o));
f.setContentHandler(th);
f.parse(s);
return o;
} catch (IOException e) {
throw new JspException(e);
} catch (SAXException e) {
throw new JspException(e);
} catch (TransformerConfigurationException e) {
throw new JspException(e);
}
}
/**
* Parses the given InputSource into a Document.
*/
private Document parseInputSource(InputSource s) throws JspException {
try {
DocumentBuilder db = XmlUtil.newDocumentBuilder();
db.setEntityResolver(entityResolver);
return db.parse(s);
} catch (SAXException e) {
throw new JspException(e);
} catch (IOException e) {
throw new JspException(e);
}
}
@Override
public void setPageContext(PageContext pageContext) {
super.setPageContext(pageContext);
entityResolver = pageContext == null ? null: new XmlUtil.JstlEntityResolver(pageContext);
}
//*********************************************************************
// Tag attributes
public void setVar(String var) {
this.var = var;
}
public void setVarDom(String varDom) {
this.varDom = varDom;
}
public void setScope(String scope) {
this.scope = Util.getScope(scope);
}
public void setScopeDom(String scopeDom) {
this.scopeDom = Util.getScope(scopeDom);
}
}