FileDocCategorySizeDatePackage
XPathUtil.javaAPI DocGlassfish v2 API22824Sat May 05 19:17:56 BST 2007org.apache.taglibs.standard.tag.common.xml

XPathUtil

public class XPathUtil extends Object

Support for tag handlers that evaluate XPath expressions.

author
Shawn Bayern
author
Ramesh Mandava ( ramesh.mandava@sun.com )
author
Pierre Delisle ( pierre.delisle@sun.com )

Fields Summary
private static final String
PAGE_NS_URL
private static final String
REQUEST_NS_URL
private static final String
SESSION_NS_URL
private static final String
APP_NS_URL
private static final String
PARAM_NS_URL
private static final String
INITPARAM_NS_URL
private static final String
COOKIE_NS_URL
private static final String
HEADER_NS_URL
private javax.servlet.jsp.PageContext
pageContext
private static HashMap
exprCache
private static JSTLXPathNamespaceContext
jstlXPathNamespaceContext
private static final String
XPATH_FACTORY_CLASS_NAME
private static XPathFactory
XPATH_FACTORY
static DocumentBuilderFactory
dbf
static DocumentBuilder
db
static Document
d
String
modifiedXPath
Constructors Summary
public XPathUtil(javax.servlet.jsp.PageContext pc)
Constructs a new XPathUtil object associated with the given PageContext.

        pageContext = pc;
    
Methods Summary
protected org.w3c.dom.NodeadaptParamsForXalan(org.w3c.dom.Node n, java.lang.String xpath, javax.xml.xpath.XPathVariableResolver jxvr)
To evaluate an XPath expression using Xalan, we need to create an XPath object, which wraps an expression object and provides general services for execution of that expression. An XPath object can be instantiated with the following information: - XPath expression to evaluate - SourceLocator (reports where an error occurred in the XML source or transformation instructions) - PrefixResolver (resolve prefixes to namespace URIs) - type (one of SELECT or MATCH) - ErrorListener (customized error handling) Execution of the XPath expression represented by an XPath object is done via method execute which takes the following parameters: - XPathContext The execution context - Node contextNode The node that "." expresses - PrefixResolver namespaceContext The context in which namespaces in the XPath are supposed to be expanded. Given all of this, if no context node is set for the evaluation of the XPath expression, one must be set so Xalan can successfully evaluate a JSTL XPath expression. (it will not work if the context node is given as a varialbe at the beginning of the expression)

@@
Provide more details...

        Node boundDocument = null;
        
        modifiedXPath = xpath;
        String origXPath = xpath;
        boolean whetherOrigXPath = true;
        
        // If contextNode is not null then  just pass the values to Xalan XPath
        if ( n != null ) {
            return n;
        }
        
        if (  xpath.startsWith("$")  ) {
            // JSTL uses $scopePrefix:varLocalName/xpath expression

            String varQName=  xpath.substring( xpath.indexOf("$")+1);
            if ( varQName.indexOf("/") > 0 ) {
                varQName = varQName.substring( 0, varQName.indexOf("/"));
            }
            String varPrefix =  null;
            String varLocalName =  varQName;
            if ( varQName.indexOf( ":") >= 0 ) {
                varPrefix = varQName.substring( 0, varQName.indexOf(":") );
                varLocalName = varQName.substring( varQName.indexOf(":")+1 );
            }
            
            if ( xpath.indexOf("/") > 0 ) {
                xpath = xpath.substring( xpath.indexOf("/"));
            } else  {
                xpath = "/*";
                whetherOrigXPath = false; 
            }
           
            
            try {
                Object varObject=((JSTLXPathVariableResolver) jxvr).getVariableValue("", varPrefix,
                    varLocalName);
                //p( "varObject => : its Class " +varObject +
                // ":" + varObject.getClass() );
                
                if ( Class.forName("org.w3c.dom.Document").isInstance(
                    varObject ) )  {
                    //boundDocument = ((Document)varObject).getDocumentElement();
                    boundDocument = ((Document)varObject);
                } else {
                    
                    //p("Creating a Dummy document to pass " +
                    // " onto as context node " );
                    
                    if ( Class.forName("org.apache.taglibs.standard.tag.common.xml.JSTLNodeList").isInstance( varObject ) ) {
                        Document newDocument = getDummyDocument();

                        JSTLNodeList jstlNodeList = (JSTLNodeList)varObject;
                        if   ( jstlNodeList.getLength() == 1 ) { 
                            if ( Class.forName("org.w3c.dom.Node").isInstance(
                                jstlNodeList.elementAt(0) ) ) { 
                                Node node = (Node)jstlNodeList.elementAt(0);
                                Document doc = getDummyDocumentWithoutRoot();
                                Node importedNode = doc.importNode( node, true);
                                doc.appendChild (importedNode );
                                boundDocument = doc;
                                if ( whetherOrigXPath ) {
                                    xpath="/*" + xpath;
                                }

                            } else {

                                //Nodelist with primitive type
                                Object myObject = jstlNodeList.elementAt(0);

                                //p("Single Element of primitive type");
                                //p("Type => " + myObject.getClass());

                                xpath = myObject.toString();

                                //p("String value ( xpathwould be this) => " + xpath);
                                boundDocument = newDocument;
                            } 
                            
                        } else {

                            Element dummyroot = newDocument.getDocumentElement();
                            for ( int i=0; i< jstlNodeList.getLength(); i++ ) {
                                Node currNode = (Node)jstlNodeList.item(i);
                            
                                Node importedNode = newDocument.importNode(
                                    currNode, true );

                                //printDetails ( newDocument);

                                dummyroot.appendChild( importedNode );

                                //p( "Details of the document After importing");
                                //printDetails ( newDocument);
                            }
                            boundDocument = newDocument;
                            // printDetails ( boundDocument );
                            //Verify :As we are adding Document element we need
                            // to change the xpath expression.Hopefully this
                            // won't  change the result

                            xpath = "/*" +  xpath;
                        }
                    } else if ( Class.forName("org.w3c.dom.Node").isInstance(
                        varObject ) ) {
                        boundDocument = (Node)varObject;
                    } else {
                        boundDocument = getDummyDocument();
                        xpath = origXPath;
                    }
                    
                    
                }
            } catch ( UnresolvableException ue ) {
                // FIXME: LOG
                // p("Variable Unresolvable :" + ue.getMessage());
                ue.printStackTrace();
            } catch ( ClassNotFoundException cnf ) {
                // Will never happen
            }
        } else { 
            //p("Not encountered $ Creating a Dummydocument 2 "+
            //   "pass onto as context node " );
            boundDocument = getDummyDocument();
        }
     
        modifiedXPath = xpath;
        //p("Modified XPath::boundDocument =>" + modifiedXPath +
        //    "::" + boundDocument );
         
        return boundDocument;
    
public booleanbooleanValueOf(org.w3c.dom.Node n, java.lang.String xpathString)
Evaluate an XPath expression to a boolean value.

        
        staticInit();
        XPathVariableResolver jxvr = new JSTLXPathVariableResolver(pageContext);
        Node contextNode = adaptParamsForXalan(n, xpathString.trim(), jxvr);
        xpathString = modifiedXPath;
        
        XPath xpath = XPATH_FACTORY.newXPath();
        xpath.setNamespaceContext(jstlXPathNamespaceContext);
        xpath.setXPathVariableResolver(jxvr);
        try {
            return ((Boolean) xpath.evaluate(
              xpathString, contextNode, XPathConstants.BOOLEAN)).booleanValue();
        } catch (XPathExpressionException ex) {
            throw new JspTagException(
                Resources.getMessage("XPATH_ERROR_XOBJECT", ex.toString()), ex);            
        }
    
public static org.w3c.dom.NodegetContext(javax.servlet.jsp.tagext.Tag t)

        ForEachTag xt =
        (ForEachTag) TagSupport.findAncestorWithClass(
        t, ForEachTag.class);
        if (xt == null)
            return null;
        else
            return (xt.getContext());
    
static org.w3c.dom.DocumentgetDummyDocument()

    
        
        try {
            if ( dbf == null ) {
                dbf = DocumentBuilderFactory.newInstance();
                dbf.setNamespaceAware( true );
                dbf.setValidating( false );
            }
            db = dbf.newDocumentBuilder();

            DOMImplementation dim = db.getDOMImplementation();
            d = dim.createDocument("http://java.sun.com/jstl", "dummyroot", null); 
            //d = db.newDocument();
            return d;
        } catch ( Exception e ) {
            e.printStackTrace();
        }
        return null;
    
static org.w3c.dom.DocumentgetDummyDocumentWithoutRoot()

        try {
            if ( dbf == null ) {
                dbf = DocumentBuilderFactory.newInstance();
                dbf.setNamespaceAware( true );
                dbf.setValidating( false );
            }
            db = dbf.newDocumentBuilder();

            d = db.newDocument();
            return d;
        } catch ( Exception e ) {
            e.printStackTrace();
        }
        return null;
    
private static voidp(java.lang.String s)

        System.out.println("[XPathUtil] " + s);
    
public static voidprintDetails(org.w3c.dom.Node n)

        p("\n\nDetails of Node = > " + n ) ;
        p("Name:Type:Node Value = > " + n.getNodeName() +
        ":" + n.getNodeType() + ":" + n.getNodeValue()  ) ;
        p("Namespace URI : Prefix : localName = > " +
        n.getNamespaceURI() + ":" +n.getPrefix() + ":" + n.getLocalName());
        p("\n Node has children => " + n.hasChildNodes() );
        if ( n.hasChildNodes() ) {
            NodeList nl = n.getChildNodes();
            p("Number of Children => " + nl.getLength() );
            for ( int i=0; i<nl.getLength(); i++ ) {
                Node childNode = nl.item(i);
                printDetails( childNode );
            }
        }
    
public java.util.ListselectNodes(org.w3c.dom.Node n, java.lang.String xpathString)
Evaluate an XPath expression to a List of nodes.

        
        staticInit();
        XPathVariableResolver jxvr = new JSTLXPathVariableResolver(pageContext);
        Node contextNode = adaptParamsForXalan(n, xpathString.trim(), jxvr);
        xpathString = modifiedXPath;
        
        try {
            XPath xpath = XPATH_FACTORY.newXPath();
            xpath.setNamespaceContext(jstlXPathNamespaceContext);
            xpath.setXPathVariableResolver(jxvr);
            Object nl = xpath.evaluate(
                xpathString, contextNode, JSTLXPathConstants.OBJECT);
            return new JSTLNodeList( nl );
        } catch (XPathExpressionException ex ) {
            throw new JspTagException(ex.toString(), ex);
        }
    
public org.w3c.dom.NodeselectSingleNode(org.w3c.dom.Node n, java.lang.String xpathString)
Evaluate an XPath expression to a single node.

        //p("selectSingleNode of XPathUtil = passed node:" +
        //   "xpathString => " + n + " : " + xpathString );
        
        staticInit();
        XPathVariableResolver jxvr = new JSTLXPathVariableResolver(pageContext);
        Node contextNode = adaptParamsForXalan(n, xpathString.trim(), jxvr);
        xpathString = modifiedXPath;
        
        try {
            XPath xpath = XPATH_FACTORY.newXPath();
            xpath.setNamespaceContext(jstlXPathNamespaceContext);
            xpath.setXPathVariableResolver(jxvr);
            return (Node) xpath.evaluate(
                xpathString, contextNode, XPathConstants.NODE);
        } catch (XPathExpressionException ex) {
            throw new JspTagException(ex.toString(), ex);            
        }
    
private static synchronized voidstaticInit()
Initialize globally useful data.

     
        // If the system property DEFAULT_PROPERTY_NAME + ":uri" is present, 
        // where uri is the parameter to this method, then its value is read 
        // as a class name. The method will try to create a new instance of 
        // this class by using the class loader, and returns it if it is 
        // successfully created.
        if (System.getSecurityManager() !=  null) {
             AccessController.doPrivileged(new PrivilegedAction(){
                public Object run(){
                    System.setProperty(XPathFactory.DEFAULT_PROPERTY_NAME + 
                            ":" + XPathFactory.DEFAULT_OBJECT_MODEL_URI, 
                            XPATH_FACTORY_CLASS_NAME);
                    return null;
                }
            });
        } else {
            System.setProperty(XPathFactory.DEFAULT_PROPERTY_NAME + 
                ":" + XPathFactory.DEFAULT_OBJECT_MODEL_URI, 
                XPATH_FACTORY_CLASS_NAME);
        }
        try {
            XPATH_FACTORY = XPathFactory.newInstance(XPathFactory.DEFAULT_OBJECT_MODEL_URI);
        } catch (XPathFactoryConfigurationException xpce) {
            xpce.printStackTrace();
        }
    
        if (jstlXPathNamespaceContext == null) {
            // register supported namespaces
            jstlXPathNamespaceContext = new JSTLXPathNamespaceContext();
            jstlXPathNamespaceContext.addNamespace("pageScope", PAGE_NS_URL);
            jstlXPathNamespaceContext.addNamespace("requestScope", REQUEST_NS_URL);
            jstlXPathNamespaceContext.addNamespace("sessionScope", SESSION_NS_URL);
            jstlXPathNamespaceContext.addNamespace("applicationScope", APP_NS_URL);
            jstlXPathNamespaceContext.addNamespace("param", PARAM_NS_URL);
            jstlXPathNamespaceContext.addNamespace("initParam", INITPARAM_NS_URL);
            jstlXPathNamespaceContext.addNamespace("header", HEADER_NS_URL);
            jstlXPathNamespaceContext.addNamespace("cookie", COOKIE_NS_URL);
            
            
            // create a HashMap to cache the expressions
            exprCache = new HashMap();
        }
    
public java.lang.StringvalueOf(org.w3c.dom.Node n, java.lang.String xpathString)
Evaluate an XPath expression to a String value.

    
                  
            
        // p("******** valueOf(" + n + ", " + xpathString + ")");
        staticInit();
        XPathVariableResolver jxvr = new JSTLXPathVariableResolver(pageContext);
        Node contextNode = adaptParamsForXalan(n, xpathString.trim(), jxvr);

        XPath xpath = XPATH_FACTORY.newXPath();
        xpath.setNamespaceContext(jstlXPathNamespaceContext);
        xpath.setXPathVariableResolver(jxvr);
        try {
            return xpath.evaluate(xpathString, contextNode);
        } catch (XPathExpressionException ex) {
            throw new JspTagException(ex.toString(), ex);
        }