feat(jdk8): move files to new folder to avoid resources compiled.
This commit is contained in:
266
jdkSrc/jdk8/com/sun/org/apache/xpath/internal/Arg.java
Normal file
266
jdkSrc/jdk8/com/sun/org/apache/xpath/internal/Arg.java
Normal file
@@ -0,0 +1,266 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal;
|
||||
|
||||
import com.sun.org.apache.xml.internal.utils.QName;
|
||||
import com.sun.org.apache.xpath.internal.objects.XObject;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* This class holds an instance of an argument on
|
||||
* the stack. The value of the argument can be either an
|
||||
* XObject or a String containing an expression.
|
||||
* @xsl.usage internal
|
||||
*/
|
||||
public class Arg
|
||||
{
|
||||
|
||||
/** Field m_qname: The name of this argument, expressed as a QName
|
||||
* (Qualified Name) object.
|
||||
* @see getQName
|
||||
* @see setQName
|
||||
* */
|
||||
private QName m_qname;
|
||||
|
||||
/**
|
||||
* Get the qualified name for this argument.
|
||||
*
|
||||
* @return QName object containing the qualified name
|
||||
*/
|
||||
public final QName getQName()
|
||||
{
|
||||
return m_qname;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the qualified name for this argument.
|
||||
*
|
||||
* @param name QName object representing the new Qualified Name.
|
||||
*/
|
||||
public final void setQName(QName name)
|
||||
{
|
||||
m_qname = name;
|
||||
}
|
||||
|
||||
/** Field m_val: Stored XObject value of this argument
|
||||
* @see #getVal()
|
||||
* @see #setVal()
|
||||
*/
|
||||
private XObject m_val;
|
||||
|
||||
/**
|
||||
* Get the value for this argument.
|
||||
*
|
||||
* @return the argument's stored XObject value.
|
||||
* @see #setVal(XObject)
|
||||
*/
|
||||
public final XObject getVal()
|
||||
{
|
||||
return m_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of this argument.
|
||||
*
|
||||
* @param val an XObject representing the arguments's value.
|
||||
* @see #getVal()
|
||||
*/
|
||||
public final void setVal(XObject val)
|
||||
{
|
||||
m_val = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Have the object release it's resources.
|
||||
* Call only when the variable or argument is going out of scope.
|
||||
*/
|
||||
public void detach()
|
||||
{
|
||||
if(null != m_val)
|
||||
{
|
||||
m_val.allowDetachToRelease(true);
|
||||
m_val.detach();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Field m_expression: Stored expression value of this argument.
|
||||
* @see #setExpression
|
||||
* @see #getExpression
|
||||
* */
|
||||
private String m_expression;
|
||||
|
||||
/**
|
||||
* Get the value expression for this argument.
|
||||
*
|
||||
* @return String containing the expression previously stored into this
|
||||
* argument
|
||||
* @see #setExpression
|
||||
*/
|
||||
public String getExpression()
|
||||
{
|
||||
return m_expression;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value expression for this argument.
|
||||
*
|
||||
* @param expr String containing the expression to be stored as this
|
||||
* argument's value.
|
||||
* @see #getExpression
|
||||
*/
|
||||
public void setExpression(String expr)
|
||||
{
|
||||
m_expression = expr;
|
||||
}
|
||||
|
||||
/**
|
||||
* True if this variable was added with an xsl:with-param or
|
||||
* is added via setParameter.
|
||||
*/
|
||||
private boolean m_isFromWithParam;
|
||||
|
||||
/**
|
||||
* Tell if this variable is a parameter passed with a with-param or as
|
||||
* a top-level parameter.
|
||||
*/
|
||||
public boolean isFromWithParam()
|
||||
{
|
||||
return m_isFromWithParam;
|
||||
}
|
||||
|
||||
/**
|
||||
* True if this variable is currently visible. To be visible,
|
||||
* a variable needs to come either from xsl:variable or be
|
||||
* a "received" parameter, ie one for which an xsl:param has
|
||||
* been encountered.
|
||||
* Set at the time the object is constructed and updated as needed.
|
||||
*/
|
||||
private boolean m_isVisible;
|
||||
|
||||
/**
|
||||
* Tell if this variable is currently visible.
|
||||
*/
|
||||
public boolean isVisible()
|
||||
{
|
||||
return m_isVisible;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update visibility status of this variable.
|
||||
*/
|
||||
public void setIsVisible(boolean b)
|
||||
{
|
||||
m_isVisible = b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a dummy parameter argument, with no QName and no
|
||||
* value (either expression string or value XObject). isVisible
|
||||
* defaults to true.
|
||||
*/
|
||||
public Arg()
|
||||
{
|
||||
|
||||
m_qname = new QName("");
|
||||
// so that string compares can be done.
|
||||
m_val = null;
|
||||
m_expression = null;
|
||||
m_isVisible = true;
|
||||
m_isFromWithParam = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a parameter argument that contains an expression.
|
||||
*
|
||||
* @param qname Name of the argument, expressed as a QName object.
|
||||
* @param expression String to be stored as this argument's value expression.
|
||||
* @param isFromWithParam True if this is a parameter variable.
|
||||
*/
|
||||
public Arg(QName qname, String expression, boolean isFromWithParam)
|
||||
{
|
||||
|
||||
m_qname = qname;
|
||||
m_val = null;
|
||||
m_expression = expression;
|
||||
m_isFromWithParam = isFromWithParam;
|
||||
m_isVisible = !isFromWithParam;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a parameter argument which has an XObject value.
|
||||
* isVisible defaults to true.
|
||||
*
|
||||
* @param qname Name of the argument, expressed as a QName object.
|
||||
* @param val Value of the argument, expressed as an XObject
|
||||
*/
|
||||
public Arg(QName qname, XObject val)
|
||||
{
|
||||
|
||||
m_qname = qname;
|
||||
m_val = val;
|
||||
m_isVisible = true;
|
||||
m_isFromWithParam = false;
|
||||
m_expression = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(this.m_qname);
|
||||
}
|
||||
|
||||
/**
|
||||
* Equality function specialized for the variable name. If the argument
|
||||
* is not a qname, it will deligate to the super class.
|
||||
*
|
||||
* @param obj the reference object with which to compare.
|
||||
* @return <code>true</code> if this object is the same as the obj
|
||||
* argument; <code>false</code> otherwise.
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if(obj instanceof QName)
|
||||
{
|
||||
return m_qname.equals(obj);
|
||||
}
|
||||
else
|
||||
return super.equals(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a parameter argument.
|
||||
*
|
||||
* @param qname Name of the argument, expressed as a QName object.
|
||||
* @param val Value of the argument, expressed as an XObject
|
||||
* @param isFromWithParam True if this is a parameter variable.
|
||||
*/
|
||||
public Arg(QName qname, XObject val, boolean isFromWithParam)
|
||||
{
|
||||
|
||||
m_qname = qname;
|
||||
m_val = val;
|
||||
m_isFromWithParam = isFromWithParam;
|
||||
m_isVisible = !isFromWithParam;
|
||||
m_expression = null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,336 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal;
|
||||
|
||||
import javax.xml.transform.TransformerException;
|
||||
|
||||
import com.sun.org.apache.xml.internal.utils.PrefixResolver;
|
||||
import com.sun.org.apache.xml.internal.utils.PrefixResolverDefault;
|
||||
import com.sun.org.apache.xpath.internal.objects.XObject;
|
||||
import jdk.xml.internal.JdkXmlUtils;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.w3c.dom.traversal.NodeIterator;
|
||||
|
||||
/**
|
||||
* The methods in this class are convenience methods into the
|
||||
* low-level XPath API.
|
||||
*
|
||||
* These functions tend to be a little slow, since a number of objects must be
|
||||
* created for each evaluation. A faster way is to precompile the
|
||||
* XPaths using the low-level API, and then just use the XPaths
|
||||
* over and over.
|
||||
*
|
||||
* This is an alternative for the old XPathAPI class, which provided
|
||||
* static methods for the purpose but had the drawback of
|
||||
* instantiating a new XPathContext (and thus building a new DTMManager,
|
||||
* and new DTMs) each time it was called. XPathAPIObject instead retains
|
||||
* its context as long as the object persists, reusing the DTMs. This
|
||||
* does have a downside: if you've changed your source document, you should
|
||||
* obtain a new XPathAPIObject to continue searching it, since trying to use
|
||||
* the old DTMs will probably yield bad results or malfunction outright... and
|
||||
* the cached DTMs may consume memory until this object and its context are
|
||||
* returned to the heap. Essentially, it's the caller's responsibility to
|
||||
* decide when to discard the cache.
|
||||
*
|
||||
* @see <a href="http://www.w3.org/TR/xpath">XPath Specification</a>
|
||||
* */
|
||||
public class CachedXPathAPI
|
||||
{
|
||||
/** XPathContext, and thus the document model system (DTMs), persists through multiple
|
||||
calls to this object. This is set in the constructor.
|
||||
*/
|
||||
protected XPathContext xpathSupport;
|
||||
|
||||
/**
|
||||
* <p>Default constructor. Establishes its own {@link XPathContext}, and hence
|
||||
* its own {@link com.sun.org.apache.xml.internal.dtm.DTMManager}.
|
||||
* Good choice for simple uses.</p>
|
||||
* <p>Note that any particular instance of {@link CachedXPathAPI} must not be
|
||||
* operated upon by multiple threads without synchronization; we do
|
||||
* not currently support multithreaded access to a single
|
||||
* {@link com.sun.org.apache.xml.internal.dtm.DTM}.</p>
|
||||
*/
|
||||
public CachedXPathAPI()
|
||||
{
|
||||
xpathSupport = new XPathContext(JdkXmlUtils.OVERRIDE_PARSER_DEFAULT);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>This constructor shares its {@link XPathContext} with a pre-existing
|
||||
* {@link CachedXPathAPI}. That allows sharing document models
|
||||
* ({@link com.sun.org.apache.xml.internal.dtm.DTM}) and previously established location
|
||||
* state.</p>
|
||||
* <p>Note that the original {@link CachedXPathAPI} and the new one should
|
||||
* not be operated upon concurrently; we do not support multithreaded access
|
||||
* to a single {@link com.sun.org.apache.xml.internal.dtm.DTM} at this time. Similarly,
|
||||
* any particular instance of {@link CachedXPathAPI} must not be operated
|
||||
* upon by multiple threads without synchronization.</p>
|
||||
* <p>%REVIEW% Should this instead do a clone-and-reset on the XPathSupport object?</p>
|
||||
*
|
||||
*/
|
||||
public CachedXPathAPI(CachedXPathAPI priorXPathAPI)
|
||||
{
|
||||
xpathSupport = priorXPathAPI.xpathSupport;
|
||||
}
|
||||
|
||||
|
||||
/** Returns the XPathSupport object used in this CachedXPathAPI
|
||||
*
|
||||
* %REVIEW% I'm somewhat concerned about the loss of encapsulation
|
||||
* this causes, but the xml-security folks say they need it.
|
||||
* */
|
||||
public XPathContext getXPathContext()
|
||||
{
|
||||
return this.xpathSupport;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Use an XPath string to select a single node. XPath namespace
|
||||
* prefixes are resolved from the context node, which may not
|
||||
* be what you want (see the next method).
|
||||
*
|
||||
* @param contextNode The node to start searching from.
|
||||
* @param str A valid XPath string.
|
||||
* @return The first node found that matches the XPath, or null.
|
||||
*
|
||||
* @throws TransformerException
|
||||
*/
|
||||
public Node selectSingleNode(Node contextNode, String str)
|
||||
throws TransformerException
|
||||
{
|
||||
return selectSingleNode(contextNode, str, contextNode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use an XPath string to select a single node.
|
||||
* XPath namespace prefixes are resolved from the namespaceNode.
|
||||
*
|
||||
* @param contextNode The node to start searching from.
|
||||
* @param str A valid XPath string.
|
||||
* @param namespaceNode The node from which prefixes in the XPath will be resolved to namespaces.
|
||||
* @return The first node found that matches the XPath, or null.
|
||||
*
|
||||
* @throws TransformerException
|
||||
*/
|
||||
public Node selectSingleNode(
|
||||
Node contextNode, String str, Node namespaceNode)
|
||||
throws TransformerException
|
||||
{
|
||||
|
||||
// Have the XObject return its result as a NodeSetDTM.
|
||||
NodeIterator nl = selectNodeIterator(contextNode, str, namespaceNode);
|
||||
|
||||
// Return the first node, or null
|
||||
return nl.nextNode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Use an XPath string to select a nodelist.
|
||||
* XPath namespace prefixes are resolved from the contextNode.
|
||||
*
|
||||
* @param contextNode The node to start searching from.
|
||||
* @param str A valid XPath string.
|
||||
* @return A NodeIterator, should never be null.
|
||||
*
|
||||
* @throws TransformerException
|
||||
*/
|
||||
public NodeIterator selectNodeIterator(Node contextNode, String str)
|
||||
throws TransformerException
|
||||
{
|
||||
return selectNodeIterator(contextNode, str, contextNode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use an XPath string to select a nodelist.
|
||||
* XPath namespace prefixes are resolved from the namespaceNode.
|
||||
*
|
||||
* @param contextNode The node to start searching from.
|
||||
* @param str A valid XPath string.
|
||||
* @param namespaceNode The node from which prefixes in the XPath will be resolved to namespaces.
|
||||
* @return A NodeIterator, should never be null.
|
||||
*
|
||||
* @throws TransformerException
|
||||
*/
|
||||
public NodeIterator selectNodeIterator(
|
||||
Node contextNode, String str, Node namespaceNode)
|
||||
throws TransformerException
|
||||
{
|
||||
|
||||
// Execute the XPath, and have it return the result
|
||||
XObject list = eval(contextNode, str, namespaceNode);
|
||||
|
||||
// Have the XObject return its result as a NodeSetDTM.
|
||||
return list.nodeset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Use an XPath string to select a nodelist.
|
||||
* XPath namespace prefixes are resolved from the contextNode.
|
||||
*
|
||||
* @param contextNode The node to start searching from.
|
||||
* @param str A valid XPath string.
|
||||
* @return A NodeIterator, should never be null.
|
||||
*
|
||||
* @throws TransformerException
|
||||
*/
|
||||
public NodeList selectNodeList(Node contextNode, String str)
|
||||
throws TransformerException
|
||||
{
|
||||
return selectNodeList(contextNode, str, contextNode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use an XPath string to select a nodelist.
|
||||
* XPath namespace prefixes are resolved from the namespaceNode.
|
||||
*
|
||||
* @param contextNode The node to start searching from.
|
||||
* @param str A valid XPath string.
|
||||
* @param namespaceNode The node from which prefixes in the XPath will be resolved to namespaces.
|
||||
* @return A NodeIterator, should never be null.
|
||||
*
|
||||
* @throws TransformerException
|
||||
*/
|
||||
public NodeList selectNodeList(
|
||||
Node contextNode, String str, Node namespaceNode)
|
||||
throws TransformerException
|
||||
{
|
||||
|
||||
// Execute the XPath, and have it return the result
|
||||
XObject list = eval(contextNode, str, namespaceNode);
|
||||
|
||||
// Return a NodeList.
|
||||
return list.nodelist();
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate XPath string to an XObject. Using this method,
|
||||
* XPath namespace prefixes will be resolved from the namespaceNode.
|
||||
* @param contextNode The node to start searching from.
|
||||
* @param str A valid XPath string.
|
||||
* @return An XObject, which can be used to obtain a string, number, nodelist, etc, should never be null.
|
||||
* @see com.sun.org.apache.xpath.internal.objects.XObject
|
||||
* @see com.sun.org.apache.xpath.internal.objects.XNull
|
||||
* @see com.sun.org.apache.xpath.internal.objects.XBoolean
|
||||
* @see com.sun.org.apache.xpath.internal.objects.XNumber
|
||||
* @see com.sun.org.apache.xpath.internal.objects.XString
|
||||
* @see com.sun.org.apache.xpath.internal.objects.XRTreeFrag
|
||||
*
|
||||
* @throws TransformerException
|
||||
*/
|
||||
public XObject eval(Node contextNode, String str)
|
||||
throws TransformerException
|
||||
{
|
||||
return eval(contextNode, str, contextNode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate XPath string to an XObject.
|
||||
* XPath namespace prefixes are resolved from the namespaceNode.
|
||||
* The implementation of this is a little slow, since it creates
|
||||
* a number of objects each time it is called. This could be optimized
|
||||
* to keep the same objects around, but then thread-safety issues would arise.
|
||||
*
|
||||
* @param contextNode The node to start searching from.
|
||||
* @param str A valid XPath string.
|
||||
* @param namespaceNode The node from which prefixes in the XPath will be resolved to namespaces.
|
||||
* @return An XObject, which can be used to obtain a string, number, nodelist, etc, should never be null.
|
||||
* @see com.sun.org.apache.xpath.internal.objects.XObject
|
||||
* @see com.sun.org.apache.xpath.internal.objects.XNull
|
||||
* @see com.sun.org.apache.xpath.internal.objects.XBoolean
|
||||
* @see com.sun.org.apache.xpath.internal.objects.XNumber
|
||||
* @see com.sun.org.apache.xpath.internal.objects.XString
|
||||
* @see com.sun.org.apache.xpath.internal.objects.XRTreeFrag
|
||||
*
|
||||
* @throws TransformerException
|
||||
*/
|
||||
public XObject eval(Node contextNode, String str, Node namespaceNode)
|
||||
throws TransformerException
|
||||
{
|
||||
|
||||
// Since we don't have a XML Parser involved here, install some default support
|
||||
// for things like namespaces, etc.
|
||||
// (Changed from: XPathContext xpathSupport = new XPathContext();
|
||||
// because XPathContext is weak in a number of areas... perhaps
|
||||
// XPathContext should be done away with.)
|
||||
|
||||
// Create an object to resolve namespace prefixes.
|
||||
// XPath namespaces are resolved from the input context node's document element
|
||||
// if it is a root node, or else the current context node (for lack of a better
|
||||
// resolution space, given the simplicity of this sample code).
|
||||
PrefixResolverDefault prefixResolver = new PrefixResolverDefault(
|
||||
(namespaceNode.getNodeType() == Node.DOCUMENT_NODE)
|
||||
? ((Document) namespaceNode).getDocumentElement() : namespaceNode);
|
||||
|
||||
// Create the XPath object.
|
||||
XPath xpath = new XPath(str, null, prefixResolver, XPath.SELECT, null);
|
||||
|
||||
// Execute the XPath, and have it return the result
|
||||
// return xpath.execute(xpathSupport, contextNode, prefixResolver);
|
||||
int ctxtNode = xpathSupport.getDTMHandleFromNode(contextNode);
|
||||
|
||||
return xpath.execute(xpathSupport, ctxtNode, prefixResolver);
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate XPath string to an XObject.
|
||||
* XPath namespace prefixes are resolved from the namespaceNode.
|
||||
* The implementation of this is a little slow, since it creates
|
||||
* a number of objects each time it is called. This could be optimized
|
||||
* to keep the same objects around, but then thread-safety issues would arise.
|
||||
*
|
||||
* @param contextNode The node to start searching from.
|
||||
* @param str A valid XPath string.
|
||||
* @param prefixResolver Will be called if the parser encounters namespace
|
||||
* prefixes, to resolve the prefixes to URLs.
|
||||
* @return An XObject, which can be used to obtain a string, number, nodelist, etc, should never be null.
|
||||
* @see com.sun.org.apache.xpath.internal.objects.XObject
|
||||
* @see com.sun.org.apache.xpath.internal.objects.XNull
|
||||
* @see com.sun.org.apache.xpath.internal.objects.XBoolean
|
||||
* @see com.sun.org.apache.xpath.internal.objects.XNumber
|
||||
* @see com.sun.org.apache.xpath.internal.objects.XString
|
||||
* @see com.sun.org.apache.xpath.internal.objects.XRTreeFrag
|
||||
*
|
||||
* @throws TransformerException
|
||||
*/
|
||||
public XObject eval(
|
||||
Node contextNode, String str, PrefixResolver prefixResolver)
|
||||
throws TransformerException
|
||||
{
|
||||
|
||||
// Since we don't have a XML Parser involved here, install some default support
|
||||
// for things like namespaces, etc.
|
||||
// (Changed from: XPathContext xpathSupport = new XPathContext();
|
||||
// because XPathContext is weak in a number of areas... perhaps
|
||||
// XPathContext should be done away with.)
|
||||
// Create the XPath object.
|
||||
XPath xpath = new XPath(str, null, prefixResolver, XPath.SELECT, null);
|
||||
|
||||
// Execute the XPath, and have it return the result
|
||||
XPathContext xpathSupport = new XPathContext(JdkXmlUtils.OVERRIDE_PARSER_DEFAULT);
|
||||
int ctxtNode = xpathSupport.getDTMHandleFromNode(contextNode);
|
||||
|
||||
return xpath.execute(xpathSupport, ctxtNode, prefixResolver);
|
||||
}
|
||||
}
|
||||
590
jdkSrc/jdk8/com/sun/org/apache/xpath/internal/Expression.java
Normal file
590
jdkSrc/jdk8/com/sun/org/apache/xpath/internal/Expression.java
Normal file
@@ -0,0 +1,590 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal;
|
||||
|
||||
import javax.xml.transform.ErrorListener;
|
||||
import javax.xml.transform.TransformerException;
|
||||
|
||||
import com.sun.org.apache.xalan.internal.res.XSLMessages;
|
||||
import com.sun.org.apache.xml.internal.dtm.DTM;
|
||||
import com.sun.org.apache.xml.internal.dtm.DTMIterator;
|
||||
import com.sun.org.apache.xml.internal.utils.XMLString;
|
||||
import com.sun.org.apache.xpath.internal.objects.XNodeSet;
|
||||
import com.sun.org.apache.xpath.internal.objects.XObject;
|
||||
import com.sun.org.apache.xpath.internal.res.XPATHErrorResources;
|
||||
|
||||
import org.xml.sax.ContentHandler;
|
||||
|
||||
/**
|
||||
* This abstract class serves as the base for all expression objects. An
|
||||
* Expression can be executed to return a {@link com.sun.org.apache.xpath.internal.objects.XObject},
|
||||
* normally has a location within a document or DOM, can send error and warning
|
||||
* events, and normally do not hold state and are meant to be immutable once
|
||||
* construction has completed. An exception to the immutibility rule is iterators
|
||||
* and walkers, which must be cloned in order to be used -- the original must
|
||||
* still be immutable.
|
||||
*/
|
||||
public abstract class Expression implements java.io.Serializable, ExpressionNode, XPathVisitable
|
||||
{
|
||||
static final long serialVersionUID = 565665869777906902L;
|
||||
/**
|
||||
* The location where this expression was built from. Need for diagnostic
|
||||
* messages. May be null.
|
||||
* @serial
|
||||
*/
|
||||
private ExpressionNode m_parent;
|
||||
|
||||
/**
|
||||
* Tell if this expression or it's subexpressions can traverse outside
|
||||
* the current subtree.
|
||||
*
|
||||
* @return true if traversal outside the context node's subtree can occur.
|
||||
*/
|
||||
public boolean canTraverseOutsideSubtree()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Set the location where this expression was built from.
|
||||
// *
|
||||
// *
|
||||
// * @param locator the location where this expression was built from, may be
|
||||
// * null.
|
||||
// */
|
||||
// public void setSourceLocator(SourceLocator locator)
|
||||
// {
|
||||
// m_slocator = locator;
|
||||
// }
|
||||
|
||||
/**
|
||||
* Execute an expression in the XPath runtime context, and return the
|
||||
* result of the expression.
|
||||
*
|
||||
*
|
||||
* @param xctxt The XPath runtime context.
|
||||
* @param currentNode The currentNode.
|
||||
*
|
||||
* @return The result of the expression in the form of a <code>XObject</code>.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException if a runtime exception
|
||||
* occurs.
|
||||
*/
|
||||
public XObject execute(XPathContext xctxt, int currentNode)
|
||||
throws javax.xml.transform.TransformerException
|
||||
{
|
||||
|
||||
// For now, the current node is already pushed.
|
||||
return execute(xctxt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute an expression in the XPath runtime context, and return the
|
||||
* result of the expression.
|
||||
*
|
||||
*
|
||||
* @param xctxt The XPath runtime context.
|
||||
* @param currentNode The currentNode.
|
||||
* @param dtm The DTM of the current node.
|
||||
* @param expType The expanded type ID of the current node.
|
||||
*
|
||||
* @return The result of the expression in the form of a <code>XObject</code>.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException if a runtime exception
|
||||
* occurs.
|
||||
*/
|
||||
public XObject execute(
|
||||
XPathContext xctxt, int currentNode, DTM dtm, int expType)
|
||||
throws javax.xml.transform.TransformerException
|
||||
{
|
||||
|
||||
// For now, the current node is already pushed.
|
||||
return execute(xctxt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute an expression in the XPath runtime context, and return the
|
||||
* result of the expression.
|
||||
*
|
||||
*
|
||||
* @param xctxt The XPath runtime context.
|
||||
*
|
||||
* @return The result of the expression in the form of a <code>XObject</code>.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException if a runtime exception
|
||||
* occurs.
|
||||
*/
|
||||
public abstract XObject execute(XPathContext xctxt)
|
||||
throws javax.xml.transform.TransformerException;
|
||||
|
||||
/**
|
||||
* Execute an expression in the XPath runtime context, and return the
|
||||
* result of the expression, but tell that a "safe" object doesn't have
|
||||
* to be returned. The default implementation just calls execute(xctxt).
|
||||
*
|
||||
*
|
||||
* @param xctxt The XPath runtime context.
|
||||
* @param destructiveOK true if a "safe" object doesn't need to be returned.
|
||||
*
|
||||
* @return The result of the expression in the form of a <code>XObject</code>.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException if a runtime exception
|
||||
* occurs.
|
||||
*/
|
||||
public XObject execute(XPathContext xctxt, boolean destructiveOK)
|
||||
throws javax.xml.transform.TransformerException
|
||||
{
|
||||
return execute(xctxt);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Evaluate expression to a number.
|
||||
*
|
||||
*
|
||||
* @param xctxt The XPath runtime context.
|
||||
* @return The expression evaluated as a double.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
public double num(XPathContext xctxt)
|
||||
throws javax.xml.transform.TransformerException
|
||||
{
|
||||
return execute(xctxt).num();
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate expression to a boolean.
|
||||
*
|
||||
*
|
||||
* @param xctxt The XPath runtime context.
|
||||
* @return false
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
public boolean bool(XPathContext xctxt)
|
||||
throws javax.xml.transform.TransformerException
|
||||
{
|
||||
return execute(xctxt).bool();
|
||||
}
|
||||
|
||||
/**
|
||||
* Cast result object to a string.
|
||||
*
|
||||
*
|
||||
* @param xctxt The XPath runtime context.
|
||||
* @return The string this wraps or the empty string if null
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
public XMLString xstr(XPathContext xctxt)
|
||||
throws javax.xml.transform.TransformerException
|
||||
{
|
||||
return execute(xctxt).xstr();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tell if the expression is a nodeset expression. In other words, tell
|
||||
* if you can execute {@link #asNode(XPathContext) asNode} without an exception.
|
||||
* @return true if the expression can be represented as a nodeset.
|
||||
*/
|
||||
public boolean isNodesetExpr()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the first node out of the nodeset, if this expression is
|
||||
* a nodeset expression.
|
||||
* @param xctxt The XPath runtime context.
|
||||
* @return the first node out of the nodeset, or DTM.NULL.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
public int asNode(XPathContext xctxt)
|
||||
throws javax.xml.transform.TransformerException
|
||||
{
|
||||
DTMIterator iter = execute(xctxt).iter();
|
||||
return iter.nextNode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an select expression and a context, evaluate the XPath
|
||||
* and return the resulting iterator.
|
||||
*
|
||||
* @param xctxt The execution context.
|
||||
* @param contextNode The node that "." expresses.
|
||||
*
|
||||
*
|
||||
* @return A valid DTMIterator.
|
||||
* @throws TransformerException thrown if the active ProblemListener decides
|
||||
* the error condition is severe enough to halt processing.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
* @xsl.usage experimental
|
||||
*/
|
||||
public DTMIterator asIterator(XPathContext xctxt, int contextNode)
|
||||
throws javax.xml.transform.TransformerException
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
xctxt.pushCurrentNodeAndExpression(contextNode, contextNode);
|
||||
|
||||
return execute(xctxt).iter();
|
||||
}
|
||||
finally
|
||||
{
|
||||
xctxt.popCurrentNodeAndExpression();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an select expression and a context, evaluate the XPath
|
||||
* and return the resulting iterator, but do not clone.
|
||||
*
|
||||
* @param xctxt The execution context.
|
||||
* @param contextNode The node that "." expresses.
|
||||
*
|
||||
*
|
||||
* @return A valid DTMIterator.
|
||||
* @throws TransformerException thrown if the active ProblemListener decides
|
||||
* the error condition is severe enough to halt processing.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
* @xsl.usage experimental
|
||||
*/
|
||||
public DTMIterator asIteratorRaw(XPathContext xctxt, int contextNode)
|
||||
throws javax.xml.transform.TransformerException
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
xctxt.pushCurrentNodeAndExpression(contextNode, contextNode);
|
||||
|
||||
XNodeSet nodeset = (XNodeSet)execute(xctxt);
|
||||
return nodeset.iterRaw();
|
||||
}
|
||||
finally
|
||||
{
|
||||
xctxt.popCurrentNodeAndExpression();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Execute an expression in the XPath runtime context, and return the
|
||||
* result of the expression.
|
||||
*
|
||||
*
|
||||
* @param xctxt The XPath runtime context.
|
||||
* NEEDSDOC @param handler
|
||||
*
|
||||
* @return The result of the expression in the form of a <code>XObject</code>.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException if a runtime exception
|
||||
* occurs.
|
||||
* @throws org.xml.sax.SAXException
|
||||
*/
|
||||
public void executeCharsToContentHandler(
|
||||
XPathContext xctxt, ContentHandler handler)
|
||||
throws javax.xml.transform.TransformerException,
|
||||
org.xml.sax.SAXException
|
||||
{
|
||||
|
||||
XObject obj = execute(xctxt);
|
||||
|
||||
obj.dispatchCharactersEvents(handler);
|
||||
obj.detach();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tell if this expression returns a stable number that will not change during
|
||||
* iterations within the expression. This is used to determine if a proximity
|
||||
* position predicate can indicate that no more searching has to occur.
|
||||
*
|
||||
*
|
||||
* @return true if the expression represents a stable number.
|
||||
*/
|
||||
public boolean isStableNumber()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is used to fixup variables from QNames to stack frame
|
||||
* indexes at stylesheet build time.
|
||||
* @param vars List of QNames that correspond to variables. This list
|
||||
* should be searched backwards for the first qualified name that
|
||||
* corresponds to the variable reference qname. The position of the
|
||||
* QName in the vector from the start of the vector will be its position
|
||||
* in the stack frame (but variables above the globalsTop value will need
|
||||
* to be offset to the current stack frame).
|
||||
* NEEDSDOC @param globalsSize
|
||||
*/
|
||||
public abstract void fixupVariables(java.util.Vector vars, int globalsSize);
|
||||
|
||||
/**
|
||||
* Compare this object with another object and see
|
||||
* if they are equal, include the sub heararchy.
|
||||
*
|
||||
* @param expr Another expression object.
|
||||
* @return true if this objects class and the expr
|
||||
* object's class are the same, and the data contained
|
||||
* within both objects are considered equal.
|
||||
*/
|
||||
public abstract boolean deepEquals(Expression expr);
|
||||
|
||||
/**
|
||||
* This is a utility method to tell if the passed in
|
||||
* class is the same class as this. It is to be used by
|
||||
* the deepEquals method. I'm bottlenecking it here
|
||||
* because I'm not totally confident that comparing the
|
||||
* class objects is the best way to do this.
|
||||
* @return true of the passed in class is the exact same
|
||||
* class as this class.
|
||||
*/
|
||||
protected final boolean isSameClass(Expression expr)
|
||||
{
|
||||
if(null == expr)
|
||||
return false;
|
||||
|
||||
return (getClass() == expr.getClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* Warn the user of an problem.
|
||||
*
|
||||
* @param xctxt The XPath runtime context.
|
||||
* @param msg An error msgkey that corresponds to one of the conststants found
|
||||
* in {@link com.sun.org.apache.xpath.internal.res.XPATHErrorResources}, which is
|
||||
* a key for a format string.
|
||||
* @param args An array of arguments represented in the format string, which
|
||||
* may be null.
|
||||
*
|
||||
* @throws TransformerException if the current ErrorListoner determines to
|
||||
* throw an exception.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
public void warn(XPathContext xctxt, String msg, Object[] args)
|
||||
throws javax.xml.transform.TransformerException
|
||||
{
|
||||
|
||||
java.lang.String fmsg = XSLMessages.createXPATHWarning(msg, args);
|
||||
|
||||
if (null != xctxt)
|
||||
{
|
||||
ErrorListener eh = xctxt.getErrorListener();
|
||||
|
||||
// TO DO: Need to get stylesheet Locator from here.
|
||||
eh.warning(new TransformerException(fmsg, xctxt.getSAXLocator()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tell the user of an assertion error, and probably throw an
|
||||
* exception.
|
||||
*
|
||||
* @param b If false, a runtime exception will be thrown.
|
||||
* @param msg The assertion message, which should be informative.
|
||||
*
|
||||
* @throws RuntimeException if the b argument is false.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
public void assertion(boolean b, java.lang.String msg)
|
||||
{
|
||||
|
||||
if (!b)
|
||||
{
|
||||
java.lang.String fMsg = XSLMessages.createXPATHMessage(
|
||||
XPATHErrorResources.ER_INCORRECT_PROGRAMMER_ASSERTION,
|
||||
new Object[]{ msg });
|
||||
|
||||
throw new RuntimeException(fMsg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tell the user of an error, and probably throw an
|
||||
* exception.
|
||||
*
|
||||
* @param xctxt The XPath runtime context.
|
||||
* @param msg An error msgkey that corresponds to one of the constants found
|
||||
* in {@link com.sun.org.apache.xpath.internal.res.XPATHErrorResources}, which is
|
||||
* a key for a format string.
|
||||
* @param args An array of arguments represented in the format string, which
|
||||
* may be null.
|
||||
*
|
||||
* @throws TransformerException if the current ErrorListoner determines to
|
||||
* throw an exception.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
public void error(XPathContext xctxt, String msg, Object[] args)
|
||||
throws javax.xml.transform.TransformerException
|
||||
{
|
||||
|
||||
java.lang.String fmsg = XSLMessages.createXPATHMessage(msg, args);
|
||||
|
||||
if (null != xctxt)
|
||||
{
|
||||
ErrorListener eh = xctxt.getErrorListener();
|
||||
TransformerException te = new TransformerException(fmsg, this);
|
||||
|
||||
eh.fatalError(te);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the first non-Expression parent of this node.
|
||||
* @return null or first ancestor that is not an Expression.
|
||||
*/
|
||||
public ExpressionNode getExpressionOwner()
|
||||
{
|
||||
ExpressionNode parent = exprGetParent();
|
||||
while((null != parent) && (parent instanceof Expression))
|
||||
parent = parent.exprGetParent();
|
||||
return parent;
|
||||
}
|
||||
|
||||
//=============== ExpressionNode methods ================
|
||||
|
||||
/** This pair of methods are used to inform the node of its
|
||||
parent. */
|
||||
public void exprSetParent(ExpressionNode n)
|
||||
{
|
||||
assertion(n != this, "Can not parent an expression to itself!");
|
||||
m_parent = n;
|
||||
}
|
||||
|
||||
public ExpressionNode exprGetParent()
|
||||
{
|
||||
return m_parent;
|
||||
}
|
||||
|
||||
/** This method tells the node to add its argument to the node's
|
||||
list of children. */
|
||||
public void exprAddChild(ExpressionNode n, int i)
|
||||
{
|
||||
assertion(false, "exprAddChild method not implemented!");
|
||||
}
|
||||
|
||||
/** This method returns a child node. The children are numbered
|
||||
from zero, left to right. */
|
||||
public ExpressionNode exprGetChild(int i)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Return the number of children the node has. */
|
||||
public int exprGetNumChildren()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
//=============== SourceLocator methods ================
|
||||
|
||||
/**
|
||||
* Return the public identifier for the current document event.
|
||||
*
|
||||
* <p>The return value is the public identifier of the document
|
||||
* entity or of the external parsed entity in which the markup that
|
||||
* triggered the event appears.</p>
|
||||
*
|
||||
* @return A string containing the public identifier, or
|
||||
* null if none is available.
|
||||
* @see #getSystemId
|
||||
*/
|
||||
public String getPublicId()
|
||||
{
|
||||
if(null == m_parent)
|
||||
return null;
|
||||
return m_parent.getPublicId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the system identifier for the current document event.
|
||||
*
|
||||
* <p>The return value is the system identifier of the document
|
||||
* entity or of the external parsed entity in which the markup that
|
||||
* triggered the event appears.</p>
|
||||
*
|
||||
* <p>If the system identifier is a URL, the parser must resolve it
|
||||
* fully before passing it to the application.</p>
|
||||
*
|
||||
* @return A string containing the system identifier, or null
|
||||
* if none is available.
|
||||
* @see #getPublicId
|
||||
*/
|
||||
public String getSystemId()
|
||||
{
|
||||
if(null == m_parent)
|
||||
return null;
|
||||
return m_parent.getSystemId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the line number where the current document event ends.
|
||||
*
|
||||
* <p><strong>Warning:</strong> The return value from the method
|
||||
* is intended only as an approximation for the sake of error
|
||||
* reporting; it is not intended to provide sufficient information
|
||||
* to edit the character content of the original XML document.</p>
|
||||
*
|
||||
* <p>The return value is an approximation of the line number
|
||||
* in the document entity or external parsed entity where the
|
||||
* markup that triggered the event appears.</p>
|
||||
*
|
||||
* @return The line number, or -1 if none is available.
|
||||
* @see #getColumnNumber
|
||||
*/
|
||||
public int getLineNumber()
|
||||
{
|
||||
if(null == m_parent)
|
||||
return 0;
|
||||
return m_parent.getLineNumber();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the character position where the current document event ends.
|
||||
*
|
||||
* <p><strong>Warning:</strong> The return value from the method
|
||||
* is intended only as an approximation for the sake of error
|
||||
* reporting; it is not intended to provide sufficient information
|
||||
* to edit the character content of the original XML document.</p>
|
||||
*
|
||||
* <p>The return value is an approximation of the column number
|
||||
* in the document entity or external parsed entity where the
|
||||
* markup that triggered the event appears.</p>
|
||||
*
|
||||
* @return The column number, or -1 if none is available.
|
||||
* @see #getLineNumber
|
||||
*/
|
||||
public int getColumnNumber()
|
||||
{
|
||||
if(null == m_parent)
|
||||
return 0;
|
||||
return m_parent.getColumnNumber();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal;
|
||||
|
||||
import javax.xml.transform.SourceLocator;
|
||||
|
||||
/**
|
||||
* A class that implements this interface can construct expressions,
|
||||
* give information about child and parent expressions,
|
||||
* and give the originating source information. A class that implements
|
||||
* this interface does not lay any claim to being directly executable.
|
||||
*
|
||||
* <p>Note: This interface should not be considered stable. Only exprSetParent
|
||||
* and exprGetParent can be counted on to work reliably. Work in progress.</p>
|
||||
*/
|
||||
public interface ExpressionNode extends SourceLocator
|
||||
{
|
||||
/** This pair of methods are used to inform the node of its
|
||||
parent. */
|
||||
public void exprSetParent(ExpressionNode n);
|
||||
public ExpressionNode exprGetParent();
|
||||
|
||||
/** This method tells the node to add its argument to the node's
|
||||
list of children. */
|
||||
public void exprAddChild(ExpressionNode n, int i);
|
||||
|
||||
/** This method returns a child node. The children are numbered
|
||||
from zero, left to right. */
|
||||
public ExpressionNode exprGetChild(int i);
|
||||
|
||||
/** Return the number of children the node has. */
|
||||
public int exprGetNumChildren();
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal;
|
||||
|
||||
/**
|
||||
* Classes that implement this interface own an expression, which
|
||||
* can be rewritten.
|
||||
*/
|
||||
public interface ExpressionOwner
|
||||
{
|
||||
/**
|
||||
* Get the raw Expression object that this class wraps.
|
||||
*
|
||||
* @return the raw Expression object, which should not normally be null.
|
||||
*/
|
||||
public Expression getExpression();
|
||||
|
||||
/**
|
||||
* Set the raw expression object for this object.
|
||||
*
|
||||
* @param exp the raw Expression object, which should not normally be null.
|
||||
*/
|
||||
public void setExpression(Expression exp);
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal;
|
||||
|
||||
import java.util.Vector;
|
||||
|
||||
import com.sun.org.apache.xpath.internal.functions.FuncExtFunction;
|
||||
|
||||
/**
|
||||
* Interface that XPath objects can call to obtain access to an
|
||||
* ExtensionsTable.
|
||||
*
|
||||
*/
|
||||
public interface ExtensionsProvider
|
||||
{
|
||||
/**
|
||||
* Is the extension function available?
|
||||
*/
|
||||
|
||||
public boolean functionAvailable(String ns, String funcName)
|
||||
throws javax.xml.transform.TransformerException;
|
||||
|
||||
/**
|
||||
* Is the extension element available?
|
||||
*/
|
||||
public boolean elementAvailable(String ns, String elemName)
|
||||
throws javax.xml.transform.TransformerException;
|
||||
|
||||
/**
|
||||
* Execute the extension function.
|
||||
*/
|
||||
public Object extFunction(String ns, String funcName,
|
||||
Vector argVec, Object methodKey)
|
||||
throws javax.xml.transform.TransformerException;
|
||||
|
||||
/**
|
||||
* Execute the extension function.
|
||||
*/
|
||||
public Object extFunction(FuncExtFunction extFunction,
|
||||
Vector argVec)
|
||||
throws javax.xml.transform.TransformerException;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal;
|
||||
|
||||
/**
|
||||
* Class to let us know when it's time to do
|
||||
* a search from the parent because of indexing.
|
||||
* @xsl.usage internal
|
||||
*/
|
||||
public class FoundIndex extends RuntimeException
|
||||
{
|
||||
static final long serialVersionUID = -4643975335243078270L;
|
||||
|
||||
/**
|
||||
* Constructor FoundIndex
|
||||
*
|
||||
*/
|
||||
public FoundIndex(){}
|
||||
}
|
||||
1371
jdkSrc/jdk8/com/sun/org/apache/xpath/internal/NodeSet.java
Normal file
1371
jdkSrc/jdk8/com/sun/org/apache/xpath/internal/NodeSet.java
Normal file
File diff suppressed because it is too large
Load Diff
1248
jdkSrc/jdk8/com/sun/org/apache/xpath/internal/NodeSetDTM.java
Normal file
1248
jdkSrc/jdk8/com/sun/org/apache/xpath/internal/NodeSetDTM.java
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal;
|
||||
|
||||
|
||||
/**
|
||||
* This object represents a Source Tree, and any associated
|
||||
* information.
|
||||
* @xsl.usage internal
|
||||
*/
|
||||
public class SourceTree
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructor SourceTree
|
||||
*
|
||||
*
|
||||
* @param root The root of the source tree, which may or may not be a
|
||||
* {@link org.w3c.dom.Document} node.
|
||||
* @param url The URI of the source tree.
|
||||
*/
|
||||
public SourceTree(int root, String url)
|
||||
{
|
||||
m_root = root;
|
||||
m_url = url;
|
||||
}
|
||||
|
||||
/** The URI of the source tree. */
|
||||
public String m_url;
|
||||
|
||||
/** The root of the source tree, which may or may not be a
|
||||
* {@link org.w3c.dom.Document} node. */
|
||||
public int m_root;
|
||||
}
|
||||
@@ -0,0 +1,391 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Vector;
|
||||
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.transform.SourceLocator;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.URIResolver;
|
||||
import javax.xml.transform.sax.SAXSource;
|
||||
import javax.xml.transform.stream.StreamSource;
|
||||
|
||||
import com.sun.org.apache.xml.internal.dtm.DTM;
|
||||
import com.sun.org.apache.xml.internal.utils.SystemIDResolver;
|
||||
|
||||
import org.xml.sax.XMLReader;
|
||||
import org.xml.sax.helpers.XMLReaderFactory;
|
||||
|
||||
/**
|
||||
* This class bottlenecks all management of source trees. The methods
|
||||
* in this class should allow easy garbage collection of source
|
||||
* trees (not yet!), and should centralize parsing for those source trees.
|
||||
*/
|
||||
public class SourceTreeManager
|
||||
{
|
||||
|
||||
/** Vector of SourceTree objects that this manager manages. */
|
||||
private Vector m_sourceTree = new Vector();
|
||||
|
||||
/**
|
||||
* Reset the list of SourceTree objects that this manager manages.
|
||||
*
|
||||
*/
|
||||
public void reset()
|
||||
{
|
||||
m_sourceTree = new Vector();
|
||||
}
|
||||
|
||||
/** The TrAX URI resolver used to obtain source trees. */
|
||||
URIResolver m_uriResolver;
|
||||
|
||||
/**
|
||||
* Set an object that will be used to resolve URIs used in
|
||||
* document(), etc.
|
||||
* @param resolver An object that implements the URIResolver interface,
|
||||
* or null.
|
||||
*/
|
||||
public void setURIResolver(URIResolver resolver)
|
||||
{
|
||||
m_uriResolver = resolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the object that will be used to resolve URIs used in
|
||||
* document(), etc.
|
||||
* @return An object that implements the URIResolver interface,
|
||||
* or null.
|
||||
*/
|
||||
public URIResolver getURIResolver()
|
||||
{
|
||||
return m_uriResolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a document, find the URL associated with that document.
|
||||
* @param owner Document that was previously processed by this liaison.
|
||||
*
|
||||
* @return The base URI of the owner argument.
|
||||
*/
|
||||
public String findURIFromDoc(int owner)
|
||||
{
|
||||
int n = m_sourceTree.size();
|
||||
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
SourceTree sTree = (SourceTree) m_sourceTree.elementAt(i);
|
||||
|
||||
if (owner == sTree.m_root)
|
||||
return sTree.m_url;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* This will be called by the processor when it encounters
|
||||
* an xsl:include, xsl:import, or document() function.
|
||||
*
|
||||
* @param base The base URI that should be used.
|
||||
* @param urlString Value from an xsl:import or xsl:include's href attribute,
|
||||
* or a URI specified in the document() function.
|
||||
*
|
||||
* @return a Source that can be used to process the resource.
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws TransformerException
|
||||
*/
|
||||
public Source resolveURI(
|
||||
String base, String urlString, SourceLocator locator)
|
||||
throws TransformerException, IOException
|
||||
{
|
||||
|
||||
Source source = null;
|
||||
|
||||
if (null != m_uriResolver)
|
||||
{
|
||||
source = m_uriResolver.resolve(urlString, base);
|
||||
}
|
||||
|
||||
if (null == source)
|
||||
{
|
||||
String uri = SystemIDResolver.getAbsoluteURI(urlString, base);
|
||||
|
||||
source = new StreamSource(uri);
|
||||
}
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
/** JJK: Support <?xalan:doc_cache_off?> kluge in ElemForEach.
|
||||
* TODO: This function is highly dangerous. Cache management must be improved.
|
||||
*
|
||||
* @param n The node to remove.
|
||||
*/
|
||||
public void removeDocumentFromCache(int n)
|
||||
{
|
||||
if(DTM.NULL ==n)
|
||||
return;
|
||||
for(int i=m_sourceTree.size()-1;i>=0;--i)
|
||||
{
|
||||
SourceTree st=(SourceTree)m_sourceTree.elementAt(i);
|
||||
if(st!=null && st.m_root==n)
|
||||
{
|
||||
m_sourceTree.removeElementAt(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Put the source tree root node in the document cache.
|
||||
* TODO: This function needs to be a LOT more sophisticated.
|
||||
*
|
||||
* @param n The node to cache.
|
||||
* @param source The Source object to cache.
|
||||
*/
|
||||
public void putDocumentInCache(int n, Source source)
|
||||
{
|
||||
|
||||
int cachedNode = getNode(source);
|
||||
|
||||
if (DTM.NULL != cachedNode)
|
||||
{
|
||||
if (!(cachedNode == n))
|
||||
throw new RuntimeException(
|
||||
"Programmer's Error! "
|
||||
+ "putDocumentInCache found reparse of doc: "
|
||||
+ source.getSystemId());
|
||||
return;
|
||||
}
|
||||
if (null != source.getSystemId())
|
||||
{
|
||||
m_sourceTree.addElement(new SourceTree(n, source.getSystemId()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a Source object, find the node associated with it.
|
||||
*
|
||||
* @param source The Source object to act as the key.
|
||||
*
|
||||
* @return The node that is associated with the Source, or null if not found.
|
||||
*/
|
||||
public int getNode(Source source)
|
||||
{
|
||||
|
||||
// if (source instanceof DOMSource)
|
||||
// return ((DOMSource) source).getNode();
|
||||
|
||||
// TODO: Not sure if the BaseID is really the same thing as the ID.
|
||||
String url = source.getSystemId();
|
||||
|
||||
if (null == url)
|
||||
return DTM.NULL;
|
||||
|
||||
int n = m_sourceTree.size();
|
||||
|
||||
// System.out.println("getNode: "+n);
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
SourceTree sTree = (SourceTree) m_sourceTree.elementAt(i);
|
||||
|
||||
// System.out.println("getNode - url: "+url);
|
||||
// System.out.println("getNode - sTree.m_url: "+sTree.m_url);
|
||||
if (url.equals(sTree.m_url))
|
||||
return sTree.m_root;
|
||||
}
|
||||
|
||||
// System.out.println("getNode - returning: "+node);
|
||||
return DTM.NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the source tree from the a base URL and a URL string.
|
||||
*
|
||||
* @param base The base URI to use if the urlString is relative.
|
||||
* @param urlString An absolute or relative URL string.
|
||||
* @param locator The location of the caller, for diagnostic purposes.
|
||||
*
|
||||
* @return should be a non-null reference to the node identified by the
|
||||
* base and urlString.
|
||||
*
|
||||
* @throws TransformerException If the URL can not resolve to a node.
|
||||
*/
|
||||
public int getSourceTree(
|
||||
String base, String urlString, SourceLocator locator, XPathContext xctxt)
|
||||
throws TransformerException
|
||||
{
|
||||
|
||||
// System.out.println("getSourceTree");
|
||||
try
|
||||
{
|
||||
Source source = this.resolveURI(base, urlString, locator);
|
||||
|
||||
// System.out.println("getSourceTree - base: "+base+", urlString: "+urlString+", source: "+source.getSystemId());
|
||||
return getSourceTree(source, locator, xctxt);
|
||||
}
|
||||
catch (IOException ioe)
|
||||
{
|
||||
throw new TransformerException(ioe.getMessage(), locator, ioe);
|
||||
}
|
||||
|
||||
/* catch (TransformerException te)
|
||||
{
|
||||
throw new TransformerException(te.getMessage(), locator, te);
|
||||
}*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the source tree from the input source.
|
||||
*
|
||||
* @param source The Source object that should identify the desired node.
|
||||
* @param locator The location of the caller, for diagnostic purposes.
|
||||
*
|
||||
* @return non-null reference to a node.
|
||||
*
|
||||
* @throws TransformerException if the Source argument can't be resolved to
|
||||
* a node.
|
||||
*/
|
||||
public int getSourceTree(Source source, SourceLocator locator, XPathContext xctxt)
|
||||
throws TransformerException
|
||||
{
|
||||
|
||||
int n = getNode(source);
|
||||
|
||||
if (DTM.NULL != n)
|
||||
return n;
|
||||
|
||||
n = parseToNode(source, locator, xctxt);
|
||||
|
||||
if (DTM.NULL != n)
|
||||
putDocumentInCache(n, source);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to create a DOM source tree from the input source.
|
||||
*
|
||||
* @param source The Source object that identifies the source node.
|
||||
* @param locator The location of the caller, for diagnostic purposes.
|
||||
*
|
||||
* @return non-null reference to node identified by the source argument.
|
||||
*
|
||||
* @throws TransformerException if the source argument can not be resolved
|
||||
* to a source node.
|
||||
*/
|
||||
public int parseToNode(Source source, SourceLocator locator, XPathContext xctxt)
|
||||
throws TransformerException
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
Object xowner = xctxt.getOwnerObject();
|
||||
DTM dtm;
|
||||
if(null != xowner && xowner instanceof com.sun.org.apache.xml.internal.dtm.DTMWSFilter)
|
||||
{
|
||||
dtm = xctxt.getDTM(source, false,
|
||||
(com.sun.org.apache.xml.internal.dtm.DTMWSFilter)xowner, false, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
dtm = xctxt.getDTM(source, false, null, false, true);
|
||||
}
|
||||
return dtm.getDocument();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
//e.printStackTrace();
|
||||
throw new TransformerException(e.getMessage(), locator, e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns the SAX2 parser to use with the InputSource
|
||||
* obtained from this URI.
|
||||
* It may return null if any SAX2-conformant XML parser can be used,
|
||||
* or if getInputSource() will also return null. The parser must
|
||||
* be free for use (i.e.
|
||||
* not currently in use for another parse().
|
||||
*
|
||||
* @param inputSource The value returned from the URIResolver.
|
||||
* @return a SAX2 XMLReader to use to resolve the inputSource argument.
|
||||
* @param locator The location of the original caller, for diagnostic purposes.
|
||||
*
|
||||
* @throws TransformerException if the reader can not be created.
|
||||
*/
|
||||
public static XMLReader getXMLReader(Source inputSource, SourceLocator locator)
|
||||
throws TransformerException
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
XMLReader reader = (inputSource instanceof SAXSource)
|
||||
? ((SAXSource) inputSource).getXMLReader() : null;
|
||||
|
||||
if (null == reader)
|
||||
{
|
||||
try {
|
||||
javax.xml.parsers.SAXParserFactory factory=
|
||||
javax.xml.parsers.SAXParserFactory.newInstance();
|
||||
factory.setNamespaceAware( true );
|
||||
javax.xml.parsers.SAXParser jaxpParser=
|
||||
factory.newSAXParser();
|
||||
reader=jaxpParser.getXMLReader();
|
||||
|
||||
} catch( javax.xml.parsers.ParserConfigurationException ex ) {
|
||||
throw new org.xml.sax.SAXException( ex );
|
||||
} catch( javax.xml.parsers.FactoryConfigurationError ex1 ) {
|
||||
throw new org.xml.sax.SAXException( ex1.toString() );
|
||||
} catch( NoSuchMethodError ex2 ) {
|
||||
}
|
||||
catch (AbstractMethodError ame){}
|
||||
if(null == reader)
|
||||
reader = XMLReaderFactory.createXMLReader();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
reader.setFeature("http://xml.org/sax/features/namespace-prefixes",
|
||||
true);
|
||||
}
|
||||
catch (org.xml.sax.SAXException se)
|
||||
{
|
||||
|
||||
// What can we do?
|
||||
// TODO: User diagnostics.
|
||||
}
|
||||
|
||||
return reader;
|
||||
}
|
||||
catch (org.xml.sax.SAXException se)
|
||||
{
|
||||
throw new TransformerException(se.getMessage(), locator, se);
|
||||
}
|
||||
}
|
||||
}
|
||||
519
jdkSrc/jdk8/com/sun/org/apache/xpath/internal/VariableStack.java
Normal file
519
jdkSrc/jdk8/com/sun/org/apache/xpath/internal/VariableStack.java
Normal file
@@ -0,0 +1,519 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal;
|
||||
|
||||
import javax.xml.transform.TransformerException;
|
||||
|
||||
import com.sun.org.apache.xalan.internal.res.XSLMessages;
|
||||
import com.sun.org.apache.xpath.internal.objects.XObject;
|
||||
import com.sun.org.apache.xpath.internal.res.XPATHErrorResources;
|
||||
|
||||
/**
|
||||
* Defines a class to keep track of a stack for
|
||||
* template arguments and variables.
|
||||
*
|
||||
* <p>This has been changed from the previous incarnations of this
|
||||
* class to be fairly low level.</p>
|
||||
* @xsl.usage internal
|
||||
*/
|
||||
public class VariableStack implements Cloneable
|
||||
{
|
||||
/**
|
||||
* limitation for 1K
|
||||
*/
|
||||
public static final int CLEARLIMITATION= 1024;
|
||||
|
||||
/**
|
||||
* Constructor for a variable stack.
|
||||
*/
|
||||
public VariableStack()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a clone of this variable stack.
|
||||
*
|
||||
* @return a clone of this variable stack.
|
||||
*
|
||||
* @throws CloneNotSupportedException
|
||||
*/
|
||||
public synchronized Object clone() throws CloneNotSupportedException
|
||||
{
|
||||
|
||||
VariableStack vs = (VariableStack) super.clone();
|
||||
|
||||
// I *think* I can get away with a shallow clone here?
|
||||
vs._stackFrames = (XObject[]) _stackFrames.clone();
|
||||
vs._links = (int[]) _links.clone();
|
||||
|
||||
return vs;
|
||||
}
|
||||
|
||||
/**
|
||||
* The stack frame where all variables and params will be kept.
|
||||
* @serial
|
||||
*/
|
||||
XObject[] _stackFrames = new XObject[XPathContext.RECURSIONLIMIT * 2];
|
||||
|
||||
/**
|
||||
* The top of the stack frame (<code>_stackFrames</code>).
|
||||
* @serial
|
||||
*/
|
||||
int _frameTop;
|
||||
|
||||
/**
|
||||
* The bottom index of the current frame (relative to <code>_stackFrames</code>).
|
||||
* @serial
|
||||
*/
|
||||
private int _currentFrameBottom;
|
||||
|
||||
/**
|
||||
* The stack of frame positions. I call 'em links because of distant
|
||||
* <a href="http://math.millikin.edu/mprogers/Courses/currentCourses/CS481-ComputerArchitecture/cs481.Motorola68000.html">
|
||||
* Motorola 68000 assembler</a> memories. :-)
|
||||
* @serial
|
||||
*/
|
||||
int[] _links = new int[XPathContext.RECURSIONLIMIT];
|
||||
|
||||
/**
|
||||
* The top of the links stack.
|
||||
*/
|
||||
int _linksTop;
|
||||
|
||||
/**
|
||||
* Get the element at the given index, regardless of stackframe.
|
||||
*
|
||||
* @param i index from zero.
|
||||
*
|
||||
* @return The item at the given index.
|
||||
*/
|
||||
public XObject elementAt(final int i)
|
||||
{
|
||||
return _stackFrames[i];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get size of the stack.
|
||||
*
|
||||
* @return the total size of the execution stack.
|
||||
*/
|
||||
public int size()
|
||||
{
|
||||
return _frameTop;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the stack to a start position.
|
||||
*
|
||||
* @return the total size of the execution stack.
|
||||
*/
|
||||
public void reset()
|
||||
{
|
||||
|
||||
_frameTop = 0;
|
||||
_linksTop = 0;
|
||||
|
||||
// Adding one here to the stack of frame positions will allow us always
|
||||
// to look one under without having to check if we're at zero.
|
||||
// (As long as the caller doesn't screw up link/unlink.)
|
||||
_links[_linksTop++] = 0;
|
||||
_stackFrames = new XObject[_stackFrames.length];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current stack frame.
|
||||
*
|
||||
* @param sf The new stack frame position.
|
||||
*/
|
||||
public void setStackFrame(int sf)
|
||||
{
|
||||
_currentFrameBottom = sf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the position from where the search should start,
|
||||
* which is either the searchStart property, or the top
|
||||
* of the stack if that value is -1.
|
||||
*
|
||||
* @return The current stack frame position.
|
||||
*/
|
||||
public int getStackFrame()
|
||||
{
|
||||
return _currentFrameBottom;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates memory (called a stackframe) on the stack; used to store
|
||||
* local variables and parameter arguments.
|
||||
*
|
||||
* <p>I use the link/unlink concept because of distant
|
||||
* <a href="http://math.millikin.edu/mprogers/Courses/currentCourses/CS481-ComputerArchitecture/cs481.Motorola68000.html">
|
||||
* Motorola 68000 assembler</a> memories.</p>
|
||||
*
|
||||
* @param size The size of the stack frame allocation. This ammount should
|
||||
* normally be the maximum number of variables that you can have allocated
|
||||
* at one time in the new stack frame.
|
||||
*
|
||||
* @return The bottom of the stack frame, from where local variable addressing
|
||||
* should start from.
|
||||
*/
|
||||
public int link(final int size)
|
||||
{
|
||||
|
||||
_currentFrameBottom = _frameTop;
|
||||
_frameTop += size;
|
||||
|
||||
if (_frameTop >= _stackFrames.length)
|
||||
{
|
||||
XObject newsf[] = new XObject[_stackFrames.length + XPathContext.RECURSIONLIMIT + size];
|
||||
|
||||
System.arraycopy(_stackFrames, 0, newsf, 0, _stackFrames.length);
|
||||
|
||||
_stackFrames = newsf;
|
||||
}
|
||||
|
||||
if (_linksTop + 1 >= _links.length)
|
||||
{
|
||||
int newlinks[] = new int[_links.length + (CLEARLIMITATION * 2)];
|
||||
|
||||
System.arraycopy(_links, 0, newlinks, 0, _links.length);
|
||||
|
||||
_links = newlinks;
|
||||
}
|
||||
|
||||
_links[_linksTop++] = _currentFrameBottom;
|
||||
|
||||
return _currentFrameBottom;
|
||||
}
|
||||
|
||||
/**
|
||||
* Free up the stack frame that was last allocated with
|
||||
* {@link #link(int size)}.
|
||||
*/
|
||||
public void unlink()
|
||||
{
|
||||
_frameTop = _links[--_linksTop];
|
||||
_currentFrameBottom = _links[_linksTop - 1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Free up the stack frame that was last allocated with
|
||||
* {@link #link(int size)}.
|
||||
* @param currentFrame The current frame to set to
|
||||
* after the unlink.
|
||||
*/
|
||||
public void unlink(int currentFrame)
|
||||
{
|
||||
_frameTop = _links[--_linksTop];
|
||||
_currentFrameBottom = currentFrame;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a local variable or parameter in the current stack frame.
|
||||
*
|
||||
*
|
||||
* @param index Local variable index relative to the current stack
|
||||
* frame bottom.
|
||||
*
|
||||
* @param val The value of the variable that is being set.
|
||||
*/
|
||||
public void setLocalVariable(int index, XObject val)
|
||||
{
|
||||
_stackFrames[index + _currentFrameBottom] = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a local variable or parameter in the specified stack frame.
|
||||
*
|
||||
*
|
||||
* @param index Local variable index relative to the current stack
|
||||
* frame bottom.
|
||||
* NEEDSDOC @param stackFrame
|
||||
*
|
||||
* @param val The value of the variable that is being set.
|
||||
*/
|
||||
public void setLocalVariable(int index, XObject val, int stackFrame)
|
||||
{
|
||||
_stackFrames[index + stackFrame] = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a local variable or parameter in the current stack frame.
|
||||
*
|
||||
*
|
||||
* @param xctxt The XPath context, which must be passed in order to
|
||||
* lazy evaluate variables.
|
||||
*
|
||||
* @param index Local variable index relative to the current stack
|
||||
* frame bottom.
|
||||
*
|
||||
* @return The value of the variable.
|
||||
*
|
||||
* @throws TransformerException
|
||||
*/
|
||||
public XObject getLocalVariable(XPathContext xctxt, int index)
|
||||
throws TransformerException
|
||||
{
|
||||
|
||||
index += _currentFrameBottom;
|
||||
|
||||
XObject val = _stackFrames[index];
|
||||
|
||||
if(null == val)
|
||||
throw new TransformerException(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_VARIABLE_ACCESSED_BEFORE_BIND, null),
|
||||
xctxt.getSAXLocator());
|
||||
// "Variable accessed before it is bound!", xctxt.getSAXLocator());
|
||||
|
||||
// Lazy execution of variables.
|
||||
if (val.getType() == XObject.CLASS_UNRESOLVEDVARIABLE)
|
||||
return (_stackFrames[index] = val.execute(xctxt));
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a local variable or parameter in the current stack frame.
|
||||
*
|
||||
*
|
||||
* @param index Local variable index relative to the given
|
||||
* frame bottom.
|
||||
* NEEDSDOC @param frame
|
||||
*
|
||||
* @return The value of the variable.
|
||||
*
|
||||
* @throws TransformerException
|
||||
*/
|
||||
public XObject getLocalVariable(int index, int frame)
|
||||
throws TransformerException
|
||||
{
|
||||
|
||||
index += frame;
|
||||
|
||||
XObject val = _stackFrames[index];
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a local variable or parameter in the current stack frame.
|
||||
*
|
||||
*
|
||||
* @param xctxt The XPath context, which must be passed in order to
|
||||
* lazy evaluate variables.
|
||||
*
|
||||
* @param index Local variable index relative to the current stack
|
||||
* frame bottom.
|
||||
*
|
||||
* @return The value of the variable.
|
||||
*
|
||||
* @throws TransformerException
|
||||
*/
|
||||
public XObject getLocalVariable(XPathContext xctxt, int index, boolean destructiveOK)
|
||||
throws TransformerException
|
||||
{
|
||||
|
||||
index += _currentFrameBottom;
|
||||
|
||||
XObject val = _stackFrames[index];
|
||||
|
||||
if(null == val)
|
||||
throw new TransformerException(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_VARIABLE_ACCESSED_BEFORE_BIND, null),
|
||||
xctxt.getSAXLocator());
|
||||
// "Variable accessed before it is bound!", xctxt.getSAXLocator());
|
||||
|
||||
// Lazy execution of variables.
|
||||
if (val.getType() == XObject.CLASS_UNRESOLVEDVARIABLE)
|
||||
return (_stackFrames[index] = val.execute(xctxt));
|
||||
|
||||
return destructiveOK ? val : val.getFresh();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tell if a local variable has been set or not.
|
||||
*
|
||||
* @param index Local variable index relative to the current stack
|
||||
* frame bottom.
|
||||
*
|
||||
* @return true if the value at the index is not null.
|
||||
*
|
||||
* @throws TransformerException
|
||||
*/
|
||||
public boolean isLocalSet(int index) throws TransformerException
|
||||
{
|
||||
return (_stackFrames[index + _currentFrameBottom] != null);
|
||||
}
|
||||
|
||||
/** NEEDSDOC Field m_nulls */
|
||||
private static XObject[] m_nulls = new XObject[CLEARLIMITATION];
|
||||
|
||||
/**
|
||||
* Use this to clear the variables in a section of the stack. This is
|
||||
* used to clear the parameter section of the stack, so that default param
|
||||
* values can tell if they've already been set. It is important to note that
|
||||
* this function has a 1K limitation.
|
||||
*
|
||||
* @param start The start position, relative to the current local stack frame.
|
||||
* @param len The number of slots to be cleared.
|
||||
*/
|
||||
public void clearLocalSlots(int start, int len)
|
||||
{
|
||||
|
||||
start += _currentFrameBottom;
|
||||
|
||||
System.arraycopy(m_nulls, 0, _stackFrames, start, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a global variable or parameter in the global stack frame.
|
||||
*
|
||||
*
|
||||
* @param index Local variable index relative to the global stack frame
|
||||
* bottom.
|
||||
*
|
||||
* @param val The value of the variable that is being set.
|
||||
*/
|
||||
public void setGlobalVariable(final int index, final XObject val)
|
||||
{
|
||||
_stackFrames[index] = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a global variable or parameter from the global stack frame.
|
||||
*
|
||||
*
|
||||
* @param xctxt The XPath context, which must be passed in order to
|
||||
* lazy evaluate variables.
|
||||
*
|
||||
* @param index Global variable index relative to the global stack
|
||||
* frame bottom.
|
||||
*
|
||||
* @return The value of the variable.
|
||||
*
|
||||
* @throws TransformerException
|
||||
*/
|
||||
public XObject getGlobalVariable(XPathContext xctxt, final int index)
|
||||
throws TransformerException
|
||||
{
|
||||
|
||||
XObject val = _stackFrames[index];
|
||||
|
||||
// Lazy execution of variables.
|
||||
if (val.getType() == XObject.CLASS_UNRESOLVEDVARIABLE)
|
||||
return (_stackFrames[index] = val.execute(xctxt));
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a global variable or parameter from the global stack frame.
|
||||
*
|
||||
*
|
||||
* @param xctxt The XPath context, which must be passed in order to
|
||||
* lazy evaluate variables.
|
||||
*
|
||||
* @param index Global variable index relative to the global stack
|
||||
* frame bottom.
|
||||
*
|
||||
* @return The value of the variable.
|
||||
*
|
||||
* @throws TransformerException
|
||||
*/
|
||||
public XObject getGlobalVariable(XPathContext xctxt, final int index, boolean destructiveOK)
|
||||
throws TransformerException
|
||||
{
|
||||
|
||||
XObject val = _stackFrames[index];
|
||||
|
||||
// Lazy execution of variables.
|
||||
if (val.getType() == XObject.CLASS_UNRESOLVEDVARIABLE)
|
||||
return (_stackFrames[index] = val.execute(xctxt));
|
||||
|
||||
return destructiveOK ? val : val.getFresh();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a variable based on it's qualified name.
|
||||
* This is for external use only.
|
||||
*
|
||||
* @param xctxt The XPath context, which must be passed in order to
|
||||
* lazy evaluate variables.
|
||||
*
|
||||
* @param qname The qualified name of the variable.
|
||||
*
|
||||
* @return The evaluated value of the variable.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
public XObject getVariableOrParam(
|
||||
XPathContext xctxt, com.sun.org.apache.xml.internal.utils.QName qname)
|
||||
throws javax.xml.transform.TransformerException
|
||||
{
|
||||
|
||||
// J2SE does not support Xalan interpretive
|
||||
/*
|
||||
com.sun.org.apache.xml.internal.utils.PrefixResolver prefixResolver =
|
||||
xctxt.getNamespaceContext();
|
||||
|
||||
// Get the current ElemTemplateElement, which must be pushed in as the
|
||||
// prefix resolver, and then walk backwards in document order, searching
|
||||
// for an xsl:param element or xsl:variable element that matches our
|
||||
// qname. If we reach the top level, use the StylesheetRoot's composed
|
||||
// list of top level variables and parameters.
|
||||
|
||||
if (prefixResolver instanceof com.sun.org.apache.xalan.internal.templates.ElemTemplateElement)
|
||||
{
|
||||
|
||||
com.sun.org.apache.xalan.internal.templates.ElemVariable vvar;
|
||||
|
||||
com.sun.org.apache.xalan.internal.templates.ElemTemplateElement prev =
|
||||
(com.sun.org.apache.xalan.internal.templates.ElemTemplateElement) prefixResolver;
|
||||
|
||||
if (!(prev instanceof com.sun.org.apache.xalan.internal.templates.Stylesheet))
|
||||
{
|
||||
while ( !(prev.getParentNode() instanceof com.sun.org.apache.xalan.internal.templates.Stylesheet) )
|
||||
{
|
||||
com.sun.org.apache.xalan.internal.templates.ElemTemplateElement savedprev = prev;
|
||||
|
||||
while (null != (prev = prev.getPreviousSiblingElem()))
|
||||
{
|
||||
if (prev instanceof com.sun.org.apache.xalan.internal.templates.ElemVariable)
|
||||
{
|
||||
vvar = (com.sun.org.apache.xalan.internal.templates.ElemVariable) prev;
|
||||
|
||||
if (vvar.getName().equals(qname))
|
||||
return getLocalVariable(xctxt, vvar.getIndex());
|
||||
}
|
||||
}
|
||||
prev = savedprev.getParentElem();
|
||||
}
|
||||
}
|
||||
|
||||
vvar = prev.getStylesheetRoot().getVariableOrParamComposed(qname);
|
||||
if (null != vvar)
|
||||
return getGlobalVariable(xctxt, vvar.getIndex());
|
||||
}
|
||||
*/
|
||||
|
||||
throw new javax.xml.transform.TransformerException(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_VAR_NOT_RESOLVABLE, new Object[]{qname.toString()})); //"Variable not resolvable: " + qname);
|
||||
}
|
||||
} // end VariableStack
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal;
|
||||
|
||||
import javax.xml.transform.TransformerException;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* A class that implements this interface can tell if a given element should
|
||||
* strip whitespace nodes from it's children.
|
||||
*/
|
||||
public interface WhitespaceStrippingElementMatcher
|
||||
{
|
||||
/**
|
||||
* Get information about whether or not an element should strip whitespace.
|
||||
* @see <a href="http://www.w3.org/TR/xslt#strip">strip in XSLT Specification</a>
|
||||
*
|
||||
* @param support The XPath runtime state.
|
||||
* @param targetElement Element to check
|
||||
*
|
||||
* @return true if the whitespace should be stripped.
|
||||
*
|
||||
* @throws TransformerException
|
||||
*/
|
||||
public boolean shouldStripWhiteSpace(
|
||||
XPathContext support, Element targetElement) throws TransformerException;
|
||||
|
||||
/**
|
||||
* Get information about whether or not whitespace can be stripped.
|
||||
* @see <a href="http://www.w3.org/TR/xslt#strip">strip in XSLT Specification</a>
|
||||
*
|
||||
* @return true if the whitespace can be stripped.
|
||||
*/
|
||||
public boolean canStripWhiteSpace();
|
||||
}
|
||||
642
jdkSrc/jdk8/com/sun/org/apache/xpath/internal/XPath.java
Normal file
642
jdkSrc/jdk8/com/sun/org/apache/xpath/internal/XPath.java
Normal file
@@ -0,0 +1,642 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import javax.xml.transform.ErrorListener;
|
||||
import javax.xml.transform.SourceLocator;
|
||||
import javax.xml.transform.TransformerException;
|
||||
|
||||
import com.sun.org.apache.xalan.internal.res.XSLMessages;
|
||||
import com.sun.org.apache.xml.internal.dtm.DTM;
|
||||
import com.sun.org.apache.xml.internal.utils.DefaultErrorHandler;
|
||||
import com.sun.org.apache.xml.internal.utils.PrefixResolver;
|
||||
import com.sun.org.apache.xml.internal.utils.SAXSourceLocator;
|
||||
import com.sun.org.apache.xpath.internal.compiler.Compiler;
|
||||
import com.sun.org.apache.xpath.internal.compiler.FunctionTable;
|
||||
import com.sun.org.apache.xpath.internal.compiler.XPathParser;
|
||||
import com.sun.org.apache.xpath.internal.functions.Function;
|
||||
import com.sun.org.apache.xpath.internal.objects.XObject;
|
||||
import com.sun.org.apache.xpath.internal.res.XPATHErrorResources;
|
||||
import jdk.xml.internal.XMLSecurityManager;
|
||||
|
||||
/**
|
||||
* The XPath class wraps an expression object and provides general services
|
||||
* for execution of that expression.
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public class XPath implements Serializable, ExpressionOwner
|
||||
{
|
||||
static final long serialVersionUID = 3976493477939110553L;
|
||||
|
||||
/** The top of the expression tree.
|
||||
* @serial */
|
||||
private Expression m_mainExp;
|
||||
|
||||
/**
|
||||
* The function table for xpath build-in functions
|
||||
*/
|
||||
private transient FunctionTable m_funcTable = null;
|
||||
|
||||
/**
|
||||
* initial the function table
|
||||
*/
|
||||
private void initFunctionTable(){
|
||||
m_funcTable = new FunctionTable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the raw Expression object that this class wraps.
|
||||
*
|
||||
*
|
||||
* @return the raw Expression object, which should not normally be null.
|
||||
*/
|
||||
public Expression getExpression()
|
||||
{
|
||||
return m_mainExp;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is used to fixup variables from QNames to stack frame
|
||||
* indexes at stylesheet build time.
|
||||
* @param vars List of QNames that correspond to variables. This list
|
||||
* should be searched backwards for the first qualified name that
|
||||
* corresponds to the variable reference qname. The position of the
|
||||
* QName in the vector from the start of the vector will be its position
|
||||
* in the stack frame (but variables above the globalsTop value will need
|
||||
* to be offset to the current stack frame).
|
||||
*/
|
||||
public void fixupVariables(java.util.Vector vars, int globalsSize)
|
||||
{
|
||||
m_mainExp.fixupVariables(vars, globalsSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the raw expression object for this object.
|
||||
*
|
||||
*
|
||||
* @param exp the raw Expression object, which should not normally be null.
|
||||
*/
|
||||
public void setExpression(Expression exp)
|
||||
{
|
||||
if(null != m_mainExp)
|
||||
exp.exprSetParent(m_mainExp.exprGetParent()); // a bit bogus
|
||||
m_mainExp = exp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SourceLocator on the expression object.
|
||||
*
|
||||
*
|
||||
* @return the SourceLocator on the expression object, which may be null.
|
||||
*/
|
||||
public SourceLocator getLocator()
|
||||
{
|
||||
return m_mainExp;
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Set the SourceLocator on the expression object.
|
||||
// *
|
||||
// *
|
||||
// * @param l the SourceLocator on the expression object, which may be null.
|
||||
// */
|
||||
// public void setLocator(SourceLocator l)
|
||||
// {
|
||||
// // Note potential hazards -- l may not be serializable, or may be changed
|
||||
// // after being assigned here.
|
||||
// m_mainExp.setSourceLocator(l);
|
||||
// }
|
||||
|
||||
/** The pattern string, mainly kept around for diagnostic purposes.
|
||||
* @serial */
|
||||
String m_patternString;
|
||||
|
||||
/**
|
||||
* Return the XPath string associated with this object.
|
||||
*
|
||||
*
|
||||
* @return the XPath string associated with this object.
|
||||
*/
|
||||
public String getPatternString()
|
||||
{
|
||||
return m_patternString;
|
||||
}
|
||||
|
||||
/** Represents a select type expression. */
|
||||
public static final int SELECT = 0;
|
||||
|
||||
/** Represents a match type expression. */
|
||||
public static final int MATCH = 1;
|
||||
|
||||
/**
|
||||
* Construct an XPath object.
|
||||
*
|
||||
* (Needs review -sc) This method initializes an XPathParser/
|
||||
* Compiler and compiles the expression.
|
||||
* @param exprString The XPath expression.
|
||||
* @param locator The location of the expression, may be null.
|
||||
* @param prefixResolver A prefix resolver to use to resolve prefixes to
|
||||
* namespace URIs.
|
||||
* @param type one of {@link #SELECT} or {@link #MATCH}.
|
||||
* @param errorListener The error listener, or null if default should be used.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException if syntax or other error.
|
||||
*/
|
||||
public XPath(String exprString, SourceLocator locator, PrefixResolver prefixResolver,
|
||||
int type, ErrorListener errorListener)
|
||||
throws TransformerException
|
||||
{
|
||||
this(exprString, locator, prefixResolver, type, errorListener, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an XPath object.
|
||||
*
|
||||
* (Needs review -sc) This method initializes an XPathParser/
|
||||
* Compiler and compiles the expression.
|
||||
* @param exprString The XPath expression.
|
||||
* @param locator The location of the expression, may be null.
|
||||
* @param prefixResolver A prefix resolver to use to resolve prefixes to
|
||||
* namespace URIs.
|
||||
* @param type one of {@link #SELECT} or {@link #MATCH}.
|
||||
* @param errorListener The error listener, or null if default should be used.
|
||||
* @param funcTable the function table
|
||||
* @param xmlSecMgr the XML security manager
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException if syntax or other error.
|
||||
*/
|
||||
public XPath(String exprString, SourceLocator locator, PrefixResolver prefixResolver,
|
||||
int type, ErrorListener errorListener, FunctionTable funcTable,
|
||||
XMLSecurityManager xmlSecMgr)
|
||||
throws TransformerException
|
||||
{
|
||||
if (funcTable == null) {
|
||||
initFunctionTable();
|
||||
} else {
|
||||
m_funcTable = funcTable;
|
||||
}
|
||||
if(null == errorListener)
|
||||
errorListener = new DefaultErrorHandler();
|
||||
|
||||
m_patternString = exprString;
|
||||
|
||||
XPathParser parser = new XPathParser(errorListener, locator, xmlSecMgr);
|
||||
Compiler compiler = new Compiler(errorListener, locator, m_funcTable);
|
||||
|
||||
if (SELECT == type)
|
||||
parser.initXPath(compiler, exprString, prefixResolver);
|
||||
else if (MATCH == type)
|
||||
parser.initMatchPattern(compiler, exprString, prefixResolver);
|
||||
else
|
||||
throw new RuntimeException(XSLMessages.createXPATHMessage(
|
||||
XPATHErrorResources.ER_CANNOT_DEAL_XPATH_TYPE,
|
||||
new Object[]{Integer.toString(type)}));
|
||||
//"Can not deal with XPath type: " + type);
|
||||
|
||||
// System.out.println("----------------");
|
||||
Expression expr = compiler.compileExpression(0);
|
||||
|
||||
// System.out.println("expr: "+expr);
|
||||
this.setExpression(expr);
|
||||
|
||||
if((null != locator) && locator instanceof ExpressionNode)
|
||||
{
|
||||
expr.exprSetParent((ExpressionNode)locator);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an XPath object.
|
||||
*
|
||||
* (Needs review -sc) This method initializes an XPathParser/
|
||||
* Compiler and compiles the expression.
|
||||
* @param exprString The XPath expression.
|
||||
* @param locator The location of the expression, may be null.
|
||||
* @param prefixResolver A prefix resolver to use to resolve prefixes to
|
||||
* namespace URIs.
|
||||
* @param type one of {@link #SELECT} or {@link #MATCH}.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException if syntax or other error.
|
||||
*/
|
||||
public XPath(String exprString, SourceLocator locator, PrefixResolver prefixResolver,
|
||||
int type)
|
||||
throws TransformerException
|
||||
{
|
||||
this(exprString, locator, prefixResolver, type, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an XPath object.
|
||||
*
|
||||
* @param exprString The XPath expression.
|
||||
* @param locator The location of the expression, may be null.
|
||||
* @param prefixResolver A prefix resolver to use to resolve prefixes to
|
||||
* namespace URIs.
|
||||
* @param type one of {@link #SELECT} or {@link #MATCH}.
|
||||
* @param errorListener The error listener, or null if default should be used.
|
||||
* @param funcTable the function table
|
||||
* @throws TransformerException
|
||||
*/
|
||||
public XPath(String exprString, SourceLocator locator, PrefixResolver prefixResolver,
|
||||
int type, ErrorListener errorListener, FunctionTable funcTable)
|
||||
throws TransformerException
|
||||
{
|
||||
this(exprString, locator, prefixResolver, type, errorListener, funcTable, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an XPath object.
|
||||
*
|
||||
* @param expr The Expression object.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException if syntax or other error.
|
||||
*/
|
||||
public XPath(Expression expr)
|
||||
{
|
||||
this.setExpression(expr);
|
||||
initFunctionTable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an expression and a context, evaluate the XPath
|
||||
* and return the result.
|
||||
*
|
||||
* @param xctxt The execution context.
|
||||
* @param contextNode The node that "." expresses.
|
||||
* @param namespaceContext The context in which namespaces in the
|
||||
* XPath are supposed to be expanded.
|
||||
*
|
||||
* @return The result of the XPath or null if callbacks are used.
|
||||
* @throws TransformerException thrown if
|
||||
* the error condition is severe enough to halt processing.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
* @xsl.usage experimental
|
||||
*/
|
||||
public XObject execute(
|
||||
XPathContext xctxt, org.w3c.dom.Node contextNode,
|
||||
PrefixResolver namespaceContext)
|
||||
throws javax.xml.transform.TransformerException
|
||||
{
|
||||
return execute(
|
||||
xctxt, xctxt.getDTMHandleFromNode(contextNode),
|
||||
namespaceContext);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Given an expression and a context, evaluate the XPath
|
||||
* and return the result.
|
||||
*
|
||||
* @param xctxt The execution context.
|
||||
* @param contextNode The node that "." expresses.
|
||||
* @param namespaceContext The context in which namespaces in the
|
||||
* XPath are supposed to be expanded.
|
||||
*
|
||||
* @throws TransformerException thrown if the active ProblemListener decides
|
||||
* the error condition is severe enough to halt processing.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
* @xsl.usage experimental
|
||||
*/
|
||||
public XObject execute(
|
||||
XPathContext xctxt, int contextNode, PrefixResolver namespaceContext)
|
||||
throws javax.xml.transform.TransformerException
|
||||
{
|
||||
|
||||
xctxt.pushNamespaceContext(namespaceContext);
|
||||
|
||||
xctxt.pushCurrentNodeAndExpression(contextNode, contextNode);
|
||||
|
||||
XObject xobj = null;
|
||||
|
||||
try
|
||||
{
|
||||
xobj = m_mainExp.execute(xctxt);
|
||||
}
|
||||
catch (TransformerException te)
|
||||
{
|
||||
te.setLocator(this.getLocator());
|
||||
ErrorListener el = xctxt.getErrorListener();
|
||||
if(null != el) // defensive, should never happen.
|
||||
{
|
||||
el.error(te);
|
||||
}
|
||||
else
|
||||
throw te;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
while (e instanceof com.sun.org.apache.xml.internal.utils.WrappedRuntimeException)
|
||||
{
|
||||
e = ((com.sun.org.apache.xml.internal.utils.WrappedRuntimeException) e).getException();
|
||||
}
|
||||
// e.printStackTrace();
|
||||
|
||||
String msg = e.getMessage();
|
||||
|
||||
if (msg == null || msg.length() == 0) {
|
||||
msg = XSLMessages.createXPATHMessage(
|
||||
XPATHErrorResources.ER_XPATH_ERROR, null);
|
||||
|
||||
}
|
||||
TransformerException te = new TransformerException(msg,
|
||||
getLocator(), e);
|
||||
ErrorListener el = xctxt.getErrorListener();
|
||||
// te.printStackTrace();
|
||||
if(null != el) // defensive, should never happen.
|
||||
{
|
||||
el.fatalError(te);
|
||||
}
|
||||
else
|
||||
throw te;
|
||||
}
|
||||
finally
|
||||
{
|
||||
xctxt.popNamespaceContext();
|
||||
|
||||
xctxt.popCurrentNodeAndExpression();
|
||||
}
|
||||
|
||||
return xobj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an expression and a context, evaluate the XPath
|
||||
* and return the result.
|
||||
*
|
||||
* @param xctxt The execution context.
|
||||
* @param contextNode The node that "." expresses.
|
||||
* @param namespaceContext The context in which namespaces in the
|
||||
* XPath are supposed to be expanded.
|
||||
*
|
||||
* @throws TransformerException thrown if the active ProblemListener decides
|
||||
* the error condition is severe enough to halt processing.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
* @xsl.usage experimental
|
||||
*/
|
||||
public boolean bool(
|
||||
XPathContext xctxt, int contextNode, PrefixResolver namespaceContext)
|
||||
throws javax.xml.transform.TransformerException
|
||||
{
|
||||
|
||||
xctxt.pushNamespaceContext(namespaceContext);
|
||||
|
||||
xctxt.pushCurrentNodeAndExpression(contextNode, contextNode);
|
||||
|
||||
try
|
||||
{
|
||||
return m_mainExp.bool(xctxt);
|
||||
}
|
||||
catch (TransformerException te)
|
||||
{
|
||||
te.setLocator(this.getLocator());
|
||||
ErrorListener el = xctxt.getErrorListener();
|
||||
if(null != el) // defensive, should never happen.
|
||||
{
|
||||
el.error(te);
|
||||
}
|
||||
else
|
||||
throw te;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
while (e instanceof com.sun.org.apache.xml.internal.utils.WrappedRuntimeException)
|
||||
{
|
||||
e = ((com.sun.org.apache.xml.internal.utils.WrappedRuntimeException) e).getException();
|
||||
}
|
||||
// e.printStackTrace();
|
||||
|
||||
String msg = e.getMessage();
|
||||
|
||||
if (msg == null || msg.length() == 0) {
|
||||
msg = XSLMessages.createXPATHMessage(
|
||||
XPATHErrorResources.ER_XPATH_ERROR, null);
|
||||
|
||||
}
|
||||
|
||||
TransformerException te = new TransformerException(msg,
|
||||
getLocator(), e);
|
||||
ErrorListener el = xctxt.getErrorListener();
|
||||
// te.printStackTrace();
|
||||
if(null != el) // defensive, should never happen.
|
||||
{
|
||||
el.fatalError(te);
|
||||
}
|
||||
else
|
||||
throw te;
|
||||
}
|
||||
finally
|
||||
{
|
||||
xctxt.popNamespaceContext();
|
||||
|
||||
xctxt.popCurrentNodeAndExpression();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Set to true to get diagnostic messages about the result of
|
||||
* match pattern testing. */
|
||||
private static final boolean DEBUG_MATCHES = false;
|
||||
|
||||
/**
|
||||
* Get the match score of the given node.
|
||||
*
|
||||
* @param xctxt XPath runtime context.
|
||||
* @param context The current source tree context node.
|
||||
*
|
||||
* @return score, one of {@link #MATCH_SCORE_NODETEST},
|
||||
* {@link #MATCH_SCORE_NONE}, {@link #MATCH_SCORE_OTHER},
|
||||
* or {@link #MATCH_SCORE_QNAME}.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
public double getMatchScore(XPathContext xctxt, int context)
|
||||
throws javax.xml.transform.TransformerException
|
||||
{
|
||||
|
||||
xctxt.pushCurrentNode(context);
|
||||
xctxt.pushCurrentExpressionNode(context);
|
||||
|
||||
try
|
||||
{
|
||||
XObject score = m_mainExp.execute(xctxt);
|
||||
|
||||
if (DEBUG_MATCHES)
|
||||
{
|
||||
DTM dtm = xctxt.getDTM(context);
|
||||
System.out.println("score: " + score.num() + " for "
|
||||
+ dtm.getNodeName(context) + " for xpath "
|
||||
+ this.getPatternString());
|
||||
}
|
||||
|
||||
return score.num();
|
||||
}
|
||||
finally
|
||||
{
|
||||
xctxt.popCurrentNode();
|
||||
xctxt.popCurrentExpressionNode();
|
||||
}
|
||||
|
||||
// return XPath.MATCH_SCORE_NONE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Warn the user of an problem.
|
||||
*
|
||||
* @param xctxt The XPath runtime context.
|
||||
* @param sourceNode Not used.
|
||||
* @param msg An error msgkey that corresponds to one of the constants found
|
||||
* in {@link com.sun.org.apache.xpath.internal.res.XPATHErrorResources}, which is
|
||||
* a key for a format string.
|
||||
* @param args An array of arguments represented in the format string, which
|
||||
* may be null.
|
||||
*
|
||||
* @throws TransformerException if the current ErrorListoner determines to
|
||||
* throw an exception.
|
||||
*/
|
||||
public void warn(
|
||||
XPathContext xctxt, int sourceNode, String msg, Object[] args)
|
||||
throws javax.xml.transform.TransformerException
|
||||
{
|
||||
|
||||
String fmsg = XSLMessages.createXPATHWarning(msg, args);
|
||||
ErrorListener ehandler = xctxt.getErrorListener();
|
||||
|
||||
if (null != ehandler)
|
||||
{
|
||||
|
||||
// TO DO: Need to get stylesheet Locator from here.
|
||||
ehandler.warning(new TransformerException(fmsg, (SAXSourceLocator)xctxt.getSAXLocator()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tell the user of an assertion error, and probably throw an
|
||||
* exception.
|
||||
*
|
||||
* @param b If false, a runtime exception will be thrown.
|
||||
* @param msg The assertion message, which should be informative.
|
||||
*
|
||||
* @throws RuntimeException if the b argument is false.
|
||||
*/
|
||||
public void assertion(boolean b, String msg)
|
||||
{
|
||||
|
||||
if (!b)
|
||||
{
|
||||
String fMsg = XSLMessages.createXPATHMessage(
|
||||
XPATHErrorResources.ER_INCORRECT_PROGRAMMER_ASSERTION,
|
||||
new Object[]{ msg });
|
||||
|
||||
throw new RuntimeException(fMsg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tell the user of an error, and probably throw an
|
||||
* exception.
|
||||
*
|
||||
* @param xctxt The XPath runtime context.
|
||||
* @param sourceNode Not used.
|
||||
* @param msg An error msgkey that corresponds to one of the constants found
|
||||
* in {@link com.sun.org.apache.xpath.internal.res.XPATHErrorResources}, which is
|
||||
* a key for a format string.
|
||||
* @param args An array of arguments represented in the format string, which
|
||||
* may be null.
|
||||
*
|
||||
* @throws TransformerException if the current ErrorListoner determines to
|
||||
* throw an exception.
|
||||
*/
|
||||
public void error(
|
||||
XPathContext xctxt, int sourceNode, String msg, Object[] args)
|
||||
throws javax.xml.transform.TransformerException
|
||||
{
|
||||
|
||||
String fmsg = XSLMessages.createXPATHMessage(msg, args);
|
||||
ErrorListener ehandler = xctxt.getErrorListener();
|
||||
|
||||
if (null != ehandler)
|
||||
{
|
||||
ehandler.fatalError(new TransformerException(fmsg,
|
||||
(SAXSourceLocator)xctxt.getSAXLocator()));
|
||||
}
|
||||
else
|
||||
{
|
||||
SourceLocator slocator = xctxt.getSAXLocator();
|
||||
System.out.println(fmsg + "; file " + slocator.getSystemId()
|
||||
+ "; line " + slocator.getLineNumber() + "; column "
|
||||
+ slocator.getColumnNumber());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This will traverse the heararchy, calling the visitor for
|
||||
* each member. If the called visitor method returns
|
||||
* false, the subtree should not be called.
|
||||
*
|
||||
* @param owner The owner of the visitor, where that path may be
|
||||
* rewritten if needed.
|
||||
* @param visitor The visitor whose appropriate method will be called.
|
||||
*/
|
||||
public void callVisitors(ExpressionOwner owner, XPathVisitor visitor)
|
||||
{
|
||||
m_mainExp.callVisitors(this, visitor);
|
||||
}
|
||||
|
||||
/**
|
||||
* The match score if no match is made.
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public static final double MATCH_SCORE_NONE = Double.NEGATIVE_INFINITY;
|
||||
|
||||
/**
|
||||
* The match score if the pattern has the form
|
||||
* of a QName optionally preceded by an @ character.
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public static final double MATCH_SCORE_QNAME = 0.0;
|
||||
|
||||
/**
|
||||
* The match score if the pattern pattern has the form NCName:*.
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public static final double MATCH_SCORE_NSWILD = -0.25;
|
||||
|
||||
/**
|
||||
* The match score if the pattern consists of just a NodeTest.
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public static final double MATCH_SCORE_NODETEST = -0.5;
|
||||
|
||||
/**
|
||||
* The match score if the pattern consists of something
|
||||
* other than just a NodeTest or just a qname.
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public static final double MATCH_SCORE_OTHER = 0.5;
|
||||
}
|
||||
284
jdkSrc/jdk8/com/sun/org/apache/xpath/internal/XPathAPI.java
Normal file
284
jdkSrc/jdk8/com/sun/org/apache/xpath/internal/XPathAPI.java
Normal file
@@ -0,0 +1,284 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal;
|
||||
|
||||
import javax.xml.transform.TransformerException;
|
||||
|
||||
import com.sun.org.apache.xml.internal.utils.PrefixResolver;
|
||||
import com.sun.org.apache.xml.internal.utils.PrefixResolverDefault;
|
||||
import com.sun.org.apache.xpath.internal.objects.XObject;
|
||||
import jdk.xml.internal.JdkXmlUtils;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.w3c.dom.traversal.NodeIterator;
|
||||
|
||||
/**
|
||||
* The methods in this class are convenience methods into the
|
||||
* low-level XPath API.
|
||||
* These functions tend to be a little slow, since a number of objects must be
|
||||
* created for each evaluation. A faster way is to precompile the
|
||||
* XPaths using the low-level API, and then just use the XPaths
|
||||
* over and over.
|
||||
*
|
||||
* NOTE: In particular, each call to this method will create a new
|
||||
* XPathContext, a new DTMManager... and thus a new DTM. That's very
|
||||
* safe, since it guarantees that you're always processing against a
|
||||
* fully up-to-date view of your document. But it's also portentially
|
||||
* very expensive, since you're rebuilding the DTM every time. You should
|
||||
* consider using an instance of CachedXPathAPI rather than these static
|
||||
* methods.
|
||||
*
|
||||
* @see <a href="http://www.w3.org/TR/xpath">XPath Specification</a>
|
||||
* */
|
||||
public class XPathAPI
|
||||
{
|
||||
|
||||
/**
|
||||
* Use an XPath string to select a single node. XPath namespace
|
||||
* prefixes are resolved from the context node, which may not
|
||||
* be what you want (see the next method).
|
||||
*
|
||||
* @param contextNode The node to start searching from.
|
||||
* @param str A valid XPath string.
|
||||
* @return The first node found that matches the XPath, or null.
|
||||
*
|
||||
* @throws TransformerException
|
||||
*/
|
||||
public static Node selectSingleNode(Node contextNode, String str)
|
||||
throws TransformerException
|
||||
{
|
||||
return selectSingleNode(contextNode, str, contextNode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use an XPath string to select a single node.
|
||||
* XPath namespace prefixes are resolved from the namespaceNode.
|
||||
*
|
||||
* @param contextNode The node to start searching from.
|
||||
* @param str A valid XPath string.
|
||||
* @param namespaceNode The node from which prefixes in the XPath will be resolved to namespaces.
|
||||
* @return The first node found that matches the XPath, or null.
|
||||
*
|
||||
* @throws TransformerException
|
||||
*/
|
||||
public static Node selectSingleNode(
|
||||
Node contextNode, String str, Node namespaceNode)
|
||||
throws TransformerException
|
||||
{
|
||||
|
||||
// Have the XObject return its result as a NodeSetDTM.
|
||||
NodeIterator nl = selectNodeIterator(contextNode, str, namespaceNode);
|
||||
|
||||
// Return the first node, or null
|
||||
return nl.nextNode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Use an XPath string to select a nodelist.
|
||||
* XPath namespace prefixes are resolved from the contextNode.
|
||||
*
|
||||
* @param contextNode The node to start searching from.
|
||||
* @param str A valid XPath string.
|
||||
* @return A NodeIterator, should never be null.
|
||||
*
|
||||
* @throws TransformerException
|
||||
*/
|
||||
public static NodeIterator selectNodeIterator(Node contextNode, String str)
|
||||
throws TransformerException
|
||||
{
|
||||
return selectNodeIterator(contextNode, str, contextNode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use an XPath string to select a nodelist.
|
||||
* XPath namespace prefixes are resolved from the namespaceNode.
|
||||
*
|
||||
* @param contextNode The node to start searching from.
|
||||
* @param str A valid XPath string.
|
||||
* @param namespaceNode The node from which prefixes in the XPath will be resolved to namespaces.
|
||||
* @return A NodeIterator, should never be null.
|
||||
*
|
||||
* @throws TransformerException
|
||||
*/
|
||||
public static NodeIterator selectNodeIterator(
|
||||
Node contextNode, String str, Node namespaceNode)
|
||||
throws TransformerException
|
||||
{
|
||||
|
||||
// Execute the XPath, and have it return the result
|
||||
XObject list = eval(contextNode, str, namespaceNode);
|
||||
|
||||
// Have the XObject return its result as a NodeSetDTM.
|
||||
return list.nodeset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Use an XPath string to select a nodelist.
|
||||
* XPath namespace prefixes are resolved from the contextNode.
|
||||
*
|
||||
* @param contextNode The node to start searching from.
|
||||
* @param str A valid XPath string.
|
||||
* @return A NodeIterator, should never be null.
|
||||
*
|
||||
* @throws TransformerException
|
||||
*/
|
||||
public static NodeList selectNodeList(Node contextNode, String str)
|
||||
throws TransformerException
|
||||
{
|
||||
return selectNodeList(contextNode, str, contextNode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use an XPath string to select a nodelist.
|
||||
* XPath namespace prefixes are resolved from the namespaceNode.
|
||||
*
|
||||
* @param contextNode The node to start searching from.
|
||||
* @param str A valid XPath string.
|
||||
* @param namespaceNode The node from which prefixes in the XPath will be resolved to namespaces.
|
||||
* @return A NodeIterator, should never be null.
|
||||
*
|
||||
* @throws TransformerException
|
||||
*/
|
||||
public static NodeList selectNodeList(
|
||||
Node contextNode, String str, Node namespaceNode)
|
||||
throws TransformerException
|
||||
{
|
||||
|
||||
// Execute the XPath, and have it return the result
|
||||
XObject list = eval(contextNode, str, namespaceNode);
|
||||
|
||||
// Return a NodeList.
|
||||
return list.nodelist();
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate XPath string to an XObject. Using this method,
|
||||
* XPath namespace prefixes will be resolved from the namespaceNode.
|
||||
* @param contextNode The node to start searching from.
|
||||
* @param str A valid XPath string.
|
||||
* @return An XObject, which can be used to obtain a string, number, nodelist, etc, should never be null.
|
||||
* @see com.sun.org.apache.xpath.internal.objects.XObject
|
||||
* @see com.sun.org.apache.xpath.internal.objects.XNull
|
||||
* @see com.sun.org.apache.xpath.internal.objects.XBoolean
|
||||
* @see com.sun.org.apache.xpath.internal.objects.XNumber
|
||||
* @see com.sun.org.apache.xpath.internal.objects.XString
|
||||
* @see com.sun.org.apache.xpath.internal.objects.XRTreeFrag
|
||||
*
|
||||
* @throws TransformerException
|
||||
*/
|
||||
public static XObject eval(Node contextNode, String str)
|
||||
throws TransformerException
|
||||
{
|
||||
return eval(contextNode, str, contextNode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate XPath string to an XObject.
|
||||
* XPath namespace prefixes are resolved from the namespaceNode.
|
||||
* The implementation of this is a little slow, since it creates
|
||||
* a number of objects each time it is called. This could be optimized
|
||||
* to keep the same objects around, but then thread-safety issues would arise.
|
||||
*
|
||||
* @param contextNode The node to start searching from.
|
||||
* @param str A valid XPath string.
|
||||
* @param namespaceNode The node from which prefixes in the XPath will be resolved to namespaces.
|
||||
* @return An XObject, which can be used to obtain a string, number, nodelist, etc, should never be null.
|
||||
* @see com.sun.org.apache.xpath.internal.objects.XObject
|
||||
* @see com.sun.org.apache.xpath.internal.objects.XNull
|
||||
* @see com.sun.org.apache.xpath.internal.objects.XBoolean
|
||||
* @see com.sun.org.apache.xpath.internal.objects.XNumber
|
||||
* @see com.sun.org.apache.xpath.internal.objects.XString
|
||||
* @see com.sun.org.apache.xpath.internal.objects.XRTreeFrag
|
||||
*
|
||||
* @throws TransformerException
|
||||
*/
|
||||
public static XObject eval(Node contextNode, String str, Node namespaceNode)
|
||||
throws TransformerException
|
||||
{
|
||||
|
||||
// Since we don't have a XML Parser involved here, install some default support
|
||||
// for things like namespaces, etc.
|
||||
// (Changed from: XPathContext xpathSupport = new XPathContext();
|
||||
// because XPathContext is weak in a number of areas... perhaps
|
||||
// XPathContext should be done away with.)
|
||||
XPathContext xpathSupport = new XPathContext(JdkXmlUtils.OVERRIDE_PARSER_DEFAULT);
|
||||
|
||||
// Create an object to resolve namespace prefixes.
|
||||
// XPath namespaces are resolved from the input context node's document element
|
||||
// if it is a root node, or else the current context node (for lack of a better
|
||||
// resolution space, given the simplicity of this sample code).
|
||||
PrefixResolverDefault prefixResolver = new PrefixResolverDefault(
|
||||
(namespaceNode.getNodeType() == Node.DOCUMENT_NODE)
|
||||
? ((Document) namespaceNode).getDocumentElement() : namespaceNode);
|
||||
|
||||
// Create the XPath object.
|
||||
XPath xpath = new XPath(str, null, prefixResolver, XPath.SELECT, null);
|
||||
|
||||
// Execute the XPath, and have it return the result
|
||||
// return xpath.execute(xpathSupport, contextNode, prefixResolver);
|
||||
int ctxtNode = xpathSupport.getDTMHandleFromNode(contextNode);
|
||||
|
||||
return xpath.execute(xpathSupport, ctxtNode, prefixResolver);
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate XPath string to an XObject.
|
||||
* XPath namespace prefixes are resolved from the namespaceNode.
|
||||
* The implementation of this is a little slow, since it creates
|
||||
* a number of objects each time it is called. This could be optimized
|
||||
* to keep the same objects around, but then thread-safety issues would arise.
|
||||
*
|
||||
* @param contextNode The node to start searching from.
|
||||
* @param str A valid XPath string.
|
||||
* @param prefixResolver Will be called if the parser encounters namespace
|
||||
* prefixes, to resolve the prefixes to URLs.
|
||||
* @return An XObject, which can be used to obtain a string, number, nodelist, etc, should never be null.
|
||||
* @see com.sun.org.apache.xpath.internal.objects.XObject
|
||||
* @see com.sun.org.apache.xpath.internal.objects.XNull
|
||||
* @see com.sun.org.apache.xpath.internal.objects.XBoolean
|
||||
* @see com.sun.org.apache.xpath.internal.objects.XNumber
|
||||
* @see com.sun.org.apache.xpath.internal.objects.XString
|
||||
* @see com.sun.org.apache.xpath.internal.objects.XRTreeFrag
|
||||
*
|
||||
* @throws TransformerException
|
||||
*/
|
||||
public static XObject eval(
|
||||
Node contextNode, String str, PrefixResolver prefixResolver)
|
||||
throws TransformerException
|
||||
{
|
||||
|
||||
// Since we don't have a XML Parser involved here, install some default support
|
||||
// for things like namespaces, etc.
|
||||
// (Changed from: XPathContext xpathSupport = new XPathContext();
|
||||
// because XPathContext is weak in a number of areas... perhaps
|
||||
// XPathContext should be done away with.)
|
||||
// Create the XPath object.
|
||||
XPath xpath = new XPath(str, null, prefixResolver, XPath.SELECT, null);
|
||||
|
||||
// Execute the XPath, and have it return the result
|
||||
XPathContext xpathSupport = new XPathContext(JdkXmlUtils.OVERRIDE_PARSER_DEFAULT);
|
||||
int ctxtNode = xpathSupport.getDTMHandleFromNode(contextNode);
|
||||
|
||||
return xpath.execute(xpathSupport, ctxtNode, prefixResolver);
|
||||
}
|
||||
}
|
||||
1323
jdkSrc/jdk8/com/sun/org/apache/xpath/internal/XPathContext.java
Normal file
1323
jdkSrc/jdk8/com/sun/org/apache/xpath/internal/XPathContext.java
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,329 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal;
|
||||
|
||||
import javax.xml.transform.TransformerException;
|
||||
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
/**
|
||||
* This class implements an exception object that all
|
||||
* XPath classes will throw in case of an error. This class
|
||||
* extends TransformerException, and may hold other exceptions. In the
|
||||
* case of nested exceptions, printStackTrace will dump
|
||||
* all the traces of the nested exceptions, not just the trace
|
||||
* of this object.
|
||||
* @xsl.usage general
|
||||
*/
|
||||
public class XPathException extends TransformerException
|
||||
{
|
||||
static final long serialVersionUID = 4263549717619045963L;
|
||||
|
||||
/** The home of the expression that caused the error.
|
||||
* @serial */
|
||||
Object m_styleNode = null;
|
||||
|
||||
/**
|
||||
* Get the stylesheet node from where this error originated.
|
||||
* @return The stylesheet node from where this error originated, or null.
|
||||
*/
|
||||
public Object getStylesheetNode()
|
||||
{
|
||||
return m_styleNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the stylesheet node from where this error originated.
|
||||
* @param styleNode The stylesheet node from where this error originated, or null.
|
||||
*/
|
||||
public void setStylesheetNode(Object styleNode)
|
||||
{
|
||||
m_styleNode = styleNode;
|
||||
}
|
||||
|
||||
|
||||
/** A nested exception.
|
||||
* @serial */
|
||||
protected Exception m_exception;
|
||||
|
||||
/**
|
||||
* Create an XPathException object that holds
|
||||
* an error message.
|
||||
* @param message The error message.
|
||||
*/
|
||||
public XPathException(String message, ExpressionNode ex)
|
||||
{
|
||||
super(message);
|
||||
this.setLocator(ex);
|
||||
setStylesheetNode(getStylesheetNode(ex));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an XPathException object that holds
|
||||
* an error message.
|
||||
* @param message The error message.
|
||||
*/
|
||||
public XPathException(String message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the XSLT ElemVariable that this sub-expression references. In order for
|
||||
* this to work, the SourceLocator must be the owning ElemTemplateElement.
|
||||
* @return The dereference to the ElemVariable, or null if not found.
|
||||
*/
|
||||
public org.w3c.dom.Node getStylesheetNode(ExpressionNode ex)
|
||||
{
|
||||
|
||||
ExpressionNode owner = getExpressionOwner(ex);
|
||||
|
||||
if (null != owner && owner instanceof org.w3c.dom.Node)
|
||||
{
|
||||
return ((org.w3c.dom.Node)owner);
|
||||
}
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the first non-Expression parent of this node.
|
||||
* @return null or first ancestor that is not an Expression.
|
||||
*/
|
||||
protected ExpressionNode getExpressionOwner(ExpressionNode ex)
|
||||
{
|
||||
ExpressionNode parent = ex.exprGetParent();
|
||||
while((null != parent) && (parent instanceof Expression))
|
||||
parent = parent.exprGetParent();
|
||||
return parent;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create an XPathException object that holds
|
||||
* an error message and the stylesheet node that
|
||||
* the error originated from.
|
||||
* @param message The error message.
|
||||
* @param styleNode The stylesheet node that the error originated from.
|
||||
*/
|
||||
public XPathException(String message, Object styleNode)
|
||||
{
|
||||
|
||||
super(message);
|
||||
|
||||
m_styleNode = styleNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an XPathException object that holds
|
||||
* an error message, the stylesheet node that
|
||||
* the error originated from, and another exception
|
||||
* that caused this exception.
|
||||
* @param message The error message.
|
||||
* @param styleNode The stylesheet node that the error originated from.
|
||||
* @param e The exception that caused this exception.
|
||||
*/
|
||||
public XPathException(String message, Node styleNode, Exception e)
|
||||
{
|
||||
|
||||
super(message);
|
||||
|
||||
m_styleNode = styleNode;
|
||||
this.m_exception = e;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an XPathException object that holds
|
||||
* an error message, and another exception
|
||||
* that caused this exception.
|
||||
* @param message The error message.
|
||||
* @param e The exception that caused this exception.
|
||||
*/
|
||||
public XPathException(String message, Exception e)
|
||||
{
|
||||
|
||||
super(message);
|
||||
|
||||
this.m_exception = e;
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the the trace of methods from where the error
|
||||
* originated. This will trace all nested exception
|
||||
* objects, as well as this object.
|
||||
* @param s The stream where the dump will be sent to.
|
||||
*/
|
||||
public void printStackTrace(java.io.PrintStream s)
|
||||
{
|
||||
|
||||
if (s == null)
|
||||
s = System.err;
|
||||
|
||||
try
|
||||
{
|
||||
super.printStackTrace(s);
|
||||
}
|
||||
catch (Exception e){}
|
||||
|
||||
Throwable exception = m_exception;
|
||||
|
||||
for (int i = 0; (i < 10) && (null != exception); i++)
|
||||
{
|
||||
s.println("---------");
|
||||
exception.printStackTrace(s);
|
||||
|
||||
if (exception instanceof TransformerException)
|
||||
{
|
||||
TransformerException se = (TransformerException) exception;
|
||||
Throwable prev = exception;
|
||||
|
||||
exception = se.getException();
|
||||
|
||||
if (prev == exception)
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
exception = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the most contained message.
|
||||
*
|
||||
* @return The error message of the originating exception.
|
||||
*/
|
||||
public String getMessage()
|
||||
{
|
||||
|
||||
String lastMessage = super.getMessage();
|
||||
Throwable exception = m_exception;
|
||||
|
||||
while (null != exception)
|
||||
{
|
||||
String nextMessage = exception.getMessage();
|
||||
|
||||
if (null != nextMessage)
|
||||
lastMessage = nextMessage;
|
||||
|
||||
if (exception instanceof TransformerException)
|
||||
{
|
||||
TransformerException se = (TransformerException) exception;
|
||||
Throwable prev = exception;
|
||||
|
||||
exception = se.getException();
|
||||
|
||||
if (prev == exception)
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
exception = null;
|
||||
}
|
||||
}
|
||||
|
||||
return (null != lastMessage) ? lastMessage : "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the the trace of methods from where the error
|
||||
* originated. This will trace all nested exception
|
||||
* objects, as well as this object.
|
||||
* @param s The writer where the dump will be sent to.
|
||||
*/
|
||||
public void printStackTrace(java.io.PrintWriter s)
|
||||
{
|
||||
|
||||
if (s == null)
|
||||
s = new java.io.PrintWriter(System.err);
|
||||
|
||||
try
|
||||
{
|
||||
super.printStackTrace(s);
|
||||
}
|
||||
catch (Exception e){}
|
||||
|
||||
|
||||
boolean isJdk14OrHigher = false;
|
||||
try {
|
||||
Throwable.class.getMethod("getCause", (Class[]) null);
|
||||
isJdk14OrHigher = true;
|
||||
} catch (NoSuchMethodException nsme) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
// The printStackTrace method of the Throwable class in jdk 1.4
|
||||
// and higher will include the cause when printing the backtrace.
|
||||
// The following code is only required when using jdk 1.3 or lower
|
||||
if (!isJdk14OrHigher) {
|
||||
|
||||
Throwable exception = m_exception;
|
||||
|
||||
for (int i = 0; (i < 10) && (null != exception); i++)
|
||||
{
|
||||
s.println("---------");
|
||||
|
||||
try
|
||||
{
|
||||
exception.printStackTrace(s);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
s.println("Could not print stack trace...");
|
||||
}
|
||||
|
||||
if (exception instanceof TransformerException)
|
||||
{
|
||||
TransformerException se = (TransformerException) exception;
|
||||
Throwable prev = exception;
|
||||
|
||||
exception = se.getException();
|
||||
|
||||
if (prev == exception)
|
||||
{
|
||||
exception = null;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
exception = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the embedded exception, if any.
|
||||
* Overrides javax.xml.transform.TransformerException.getException().
|
||||
*
|
||||
* @return The embedded exception, or null if there is none.
|
||||
*/
|
||||
public Throwable getException()
|
||||
{
|
||||
return m_exception;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal;
|
||||
|
||||
import javax.xml.transform.SourceLocator;
|
||||
|
||||
import com.sun.org.apache.xml.internal.utils.PrefixResolver;
|
||||
|
||||
/**
|
||||
* Factory class for creating an XPath. Implementors of XPath derivatives
|
||||
* will need to make a derived class of this.
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public interface XPathFactory
|
||||
{
|
||||
|
||||
/**
|
||||
* Create an XPath.
|
||||
*
|
||||
* @param exprString The XPath expression string.
|
||||
* @param locator The location of the expression string, mainly for diagnostic
|
||||
* purposes.
|
||||
* @param prefixResolver This will be called in order to resolve prefixes
|
||||
* to namespace URIs.
|
||||
* @param type One of {@link com.sun.org.apache.xpath.internal.XPath#SELECT} or
|
||||
* {@link com.sun.org.apache.xpath.internal.XPath#MATCH}.
|
||||
*
|
||||
* @return an XPath ready for execution.
|
||||
*/
|
||||
XPath create(String exprString, SourceLocator locator,
|
||||
PrefixResolver prefixResolver, int type);
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal;
|
||||
|
||||
/**
|
||||
* Derived from XPathException in order that XPath processor
|
||||
* exceptions may be specifically caught.
|
||||
* @xsl.usage general
|
||||
*/
|
||||
public class XPathProcessorException extends XPathException
|
||||
{
|
||||
static final long serialVersionUID = 1215509418326642603L;
|
||||
|
||||
/**
|
||||
* Create an XPathProcessorException object that holds
|
||||
* an error message.
|
||||
* @param message The error message.
|
||||
*/
|
||||
public XPathProcessorException(String message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create an XPathProcessorException object that holds
|
||||
* an error message, and another exception
|
||||
* that caused this exception.
|
||||
* @param message The error message.
|
||||
* @param e The exception that caused this exception.
|
||||
*/
|
||||
public XPathProcessorException(String message, Exception e)
|
||||
{
|
||||
super(message, e);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal;
|
||||
|
||||
/**
|
||||
* A class that implements this interface will call a XPathVisitor
|
||||
* for itself and members within it's heararchy. If the XPathVisitor's
|
||||
* method returns false, the sub-member heararchy will not be
|
||||
* traversed.
|
||||
*/
|
||||
public interface XPathVisitable
|
||||
{
|
||||
/**
|
||||
* This will traverse the heararchy, calling the visitor for
|
||||
* each member. If the called visitor method returns
|
||||
* false, the subtree should not be called.
|
||||
*
|
||||
* @param owner The owner of the visitor, where that path may be
|
||||
* rewritten if needed.
|
||||
* @param visitor The visitor whose appropriate method will be called.
|
||||
*/
|
||||
public void callVisitors(ExpressionOwner owner, XPathVisitor visitor);
|
||||
}
|
||||
203
jdkSrc/jdk8/com/sun/org/apache/xpath/internal/XPathVisitor.java
Normal file
203
jdkSrc/jdk8/com/sun/org/apache/xpath/internal/XPathVisitor.java
Normal file
@@ -0,0 +1,203 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal;
|
||||
|
||||
import com.sun.org.apache.xpath.internal.axes.LocPathIterator;
|
||||
import com.sun.org.apache.xpath.internal.axes.UnionPathIterator;
|
||||
import com.sun.org.apache.xpath.internal.functions.Function;
|
||||
import com.sun.org.apache.xpath.internal.objects.XNumber;
|
||||
import com.sun.org.apache.xpath.internal.objects.XString;
|
||||
import com.sun.org.apache.xpath.internal.operations.Operation;
|
||||
import com.sun.org.apache.xpath.internal.operations.UnaryOperation;
|
||||
import com.sun.org.apache.xpath.internal.operations.Variable;
|
||||
import com.sun.org.apache.xpath.internal.patterns.NodeTest;
|
||||
import com.sun.org.apache.xpath.internal.patterns.StepPattern;
|
||||
import com.sun.org.apache.xpath.internal.patterns.UnionPattern;
|
||||
|
||||
/**
|
||||
* A derivation from this class can be passed to a class that implements
|
||||
* the XPathVisitable interface, to have the appropriate method called
|
||||
* for each component of the XPath. Aside from possible other uses, the
|
||||
* main intention is to provide a reasonable means to perform expression
|
||||
* rewriting.
|
||||
*
|
||||
* <p>Each method has the form
|
||||
* <code>boolean visitComponentType(ExpressionOwner owner, ComponentType compType)</code>.
|
||||
* The ExpressionOwner argument is the owner of the component, and can
|
||||
* be used to reset the expression for rewriting. If a method returns
|
||||
* false, the sub hierarchy will not be traversed.</p>
|
||||
*
|
||||
* <p>This class is meant to be a base class that will be derived by concrete classes,
|
||||
* and doesn't much except return true for each method.</p>
|
||||
*/
|
||||
public class XPathVisitor
|
||||
{
|
||||
/**
|
||||
* Visit a LocationPath.
|
||||
* @param owner The owner of the expression, to which the expression can
|
||||
* be reset if rewriting takes place.
|
||||
* @param path The LocationPath object.
|
||||
* @return true if the sub expressions should be traversed.
|
||||
*/
|
||||
public boolean visitLocationPath(ExpressionOwner owner, LocPathIterator path)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visit a UnionPath.
|
||||
* @param owner The owner of the expression, to which the expression can
|
||||
* be reset if rewriting takes place.
|
||||
* @param path The UnionPath object.
|
||||
* @return true if the sub expressions should be traversed.
|
||||
*/
|
||||
public boolean visitUnionPath(ExpressionOwner owner, UnionPathIterator path)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visit a step within a location path.
|
||||
* @param owner The owner of the expression, to which the expression can
|
||||
* be reset if rewriting takes place.
|
||||
* @param step The Step object.
|
||||
* @return true if the sub expressions should be traversed.
|
||||
*/
|
||||
public boolean visitStep(ExpressionOwner owner, NodeTest step)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visit a predicate within a location path. Note that there isn't a
|
||||
* proper unique component for predicates, and that the expression will
|
||||
* be called also for whatever type Expression is.
|
||||
*
|
||||
* @param owner The owner of the expression, to which the expression can
|
||||
* be reset if rewriting takes place.
|
||||
* @param pred The predicate object.
|
||||
* @return true if the sub expressions should be traversed.
|
||||
*/
|
||||
public boolean visitPredicate(ExpressionOwner owner, Expression pred)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visit a binary operation.
|
||||
* @param owner The owner of the expression, to which the expression can
|
||||
* be reset if rewriting takes place.
|
||||
* @param op The operation object.
|
||||
* @return true if the sub expressions should be traversed.
|
||||
*/
|
||||
public boolean visitBinaryOperation(ExpressionOwner owner, Operation op)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visit a unary operation.
|
||||
* @param owner The owner of the expression, to which the expression can
|
||||
* be reset if rewriting takes place.
|
||||
* @param op The operation object.
|
||||
* @return true if the sub expressions should be traversed.
|
||||
*/
|
||||
public boolean visitUnaryOperation(ExpressionOwner owner, UnaryOperation op)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visit a variable reference.
|
||||
* @param owner The owner of the expression, to which the expression can
|
||||
* be reset if rewriting takes place.
|
||||
* @param var The variable reference object.
|
||||
* @return true if the sub expressions should be traversed.
|
||||
*/
|
||||
public boolean visitVariableRef(ExpressionOwner owner, Variable var)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visit a function.
|
||||
* @param owner The owner of the expression, to which the expression can
|
||||
* be reset if rewriting takes place.
|
||||
* @param func The function reference object.
|
||||
* @return true if the sub expressions should be traversed.
|
||||
*/
|
||||
public boolean visitFunction(ExpressionOwner owner, Function func)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visit a match pattern.
|
||||
* @param owner The owner of the expression, to which the expression can
|
||||
* be reset if rewriting takes place.
|
||||
* @param pattern The match pattern object.
|
||||
* @return true if the sub expressions should be traversed.
|
||||
*/
|
||||
public boolean visitMatchPattern(ExpressionOwner owner, StepPattern pattern)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visit a union pattern.
|
||||
* @param owner The owner of the expression, to which the expression can
|
||||
* be reset if rewriting takes place.
|
||||
* @param pattern The union pattern object.
|
||||
* @return true if the sub expressions should be traversed.
|
||||
*/
|
||||
public boolean visitUnionPattern(ExpressionOwner owner, UnionPattern pattern)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visit a string literal.
|
||||
* @param owner The owner of the expression, to which the expression can
|
||||
* be reset if rewriting takes place.
|
||||
* @param str The string literal object.
|
||||
* @return true if the sub expressions should be traversed.
|
||||
*/
|
||||
public boolean visitStringLiteral(ExpressionOwner owner, XString str)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Visit a number literal.
|
||||
* @param owner The owner of the expression, to which the expression can
|
||||
* be reset if rewriting takes place.
|
||||
* @param num The number literal object.
|
||||
* @return true if the sub expressions should be traversed.
|
||||
*/
|
||||
public boolean visitNumberLiteral(ExpressionOwner owner, XNumber num)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.axes;
|
||||
|
||||
import com.sun.org.apache.xml.internal.dtm.DTM;
|
||||
import com.sun.org.apache.xpath.internal.compiler.Compiler;
|
||||
|
||||
/**
|
||||
* This class implements an optimized iterator for
|
||||
* attribute axes patterns.
|
||||
* @see com.sun.org.apache.xpath.internal.axes#ChildTestIterator
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public class AttributeIterator extends ChildTestIterator
|
||||
{
|
||||
static final long serialVersionUID = -8417986700712229686L;
|
||||
|
||||
/**
|
||||
* Create a AttributeIterator object.
|
||||
*
|
||||
* @param compiler A reference to the Compiler that contains the op map.
|
||||
* @param opPos The position within the op map, which contains the
|
||||
* location path expression for this itterator.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
AttributeIterator(Compiler compiler, int opPos, int analysis)
|
||||
throws javax.xml.transform.TransformerException
|
||||
{
|
||||
super(compiler, opPos, analysis);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next node via getFirstAttribute && getNextAttribute.
|
||||
*/
|
||||
protected int getNextNode()
|
||||
{
|
||||
m_lastFetched = (DTM.NULL == m_lastFetched)
|
||||
? m_cdtm.getFirstAttribute(m_context)
|
||||
: m_cdtm.getNextAttribute(m_lastFetched);
|
||||
return m_lastFetched;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the axis being iterated, if it is known.
|
||||
*
|
||||
* @return Axis.CHILD, etc., or -1 if the axis is not known or is of multiple
|
||||
* types.
|
||||
*/
|
||||
public int getAxis()
|
||||
{
|
||||
return com.sun.org.apache.xml.internal.dtm.Axis.ATTRIBUTE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,591 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.axes;
|
||||
|
||||
import java.util.Vector;
|
||||
|
||||
import com.sun.org.apache.xalan.internal.res.XSLMessages;
|
||||
import com.sun.org.apache.xml.internal.dtm.DTM;
|
||||
import com.sun.org.apache.xml.internal.dtm.DTMAxisTraverser;
|
||||
import com.sun.org.apache.xml.internal.dtm.DTMIterator;
|
||||
import com.sun.org.apache.xpath.internal.Expression;
|
||||
import com.sun.org.apache.xpath.internal.ExpressionOwner;
|
||||
import com.sun.org.apache.xpath.internal.XPathContext;
|
||||
import com.sun.org.apache.xpath.internal.XPathVisitor;
|
||||
import com.sun.org.apache.xpath.internal.compiler.Compiler;
|
||||
import com.sun.org.apache.xpath.internal.res.XPATHErrorResources;
|
||||
|
||||
/**
|
||||
* Serves as common interface for axes Walkers, and stores common
|
||||
* state variables.
|
||||
*/
|
||||
public class AxesWalker extends PredicatedNodeTest
|
||||
implements Cloneable, PathComponent, ExpressionOwner
|
||||
{
|
||||
static final long serialVersionUID = -2966031951306601247L;
|
||||
|
||||
/**
|
||||
* Construct an AxesWalker using a LocPathIterator.
|
||||
*
|
||||
* @param locPathIterator non-null reference to the parent iterator.
|
||||
*/
|
||||
public AxesWalker(LocPathIterator locPathIterator, int axis)
|
||||
{
|
||||
super( locPathIterator );
|
||||
m_axis = axis;
|
||||
}
|
||||
|
||||
public final WalkingIterator wi()
|
||||
{
|
||||
return (WalkingIterator)m_lpi;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize an AxesWalker during the parse of the XPath expression.
|
||||
*
|
||||
* @param compiler The Compiler object that has information about this
|
||||
* walker in the op map.
|
||||
* @param opPos The op code position of this location step.
|
||||
* @param stepType The type of location step.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
public void init(Compiler compiler, int opPos, int stepType)
|
||||
throws javax.xml.transform.TransformerException
|
||||
{
|
||||
|
||||
initPredicateInfo(compiler, opPos);
|
||||
|
||||
// int testType = compiler.getOp(nodeTestOpPos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a cloned AxesWalker.
|
||||
*
|
||||
* @return A new AxesWalker that can be used without mutating this one.
|
||||
*
|
||||
* @throws CloneNotSupportedException
|
||||
*/
|
||||
public Object clone() throws CloneNotSupportedException
|
||||
{
|
||||
// Do not access the location path itterator during this operation!
|
||||
|
||||
AxesWalker clone = (AxesWalker) super.clone();
|
||||
|
||||
//clone.setCurrentNode(clone.m_root);
|
||||
|
||||
// clone.m_isFresh = true;
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do a deep clone of this walker, including next and previous walkers.
|
||||
* If the this AxesWalker is on the clone list, don't clone but
|
||||
* return the already cloned version.
|
||||
*
|
||||
* @param cloneOwner non-null reference to the cloned location path
|
||||
* iterator to which this clone will be added.
|
||||
* @param cloneList non-null vector of sources in odd elements, and the
|
||||
* corresponding clones in even vectors.
|
||||
*
|
||||
* @return non-null clone, which may be a new clone, or may be a clone
|
||||
* contained on the cloneList.
|
||||
*/
|
||||
AxesWalker cloneDeep(WalkingIterator cloneOwner, Vector cloneList)
|
||||
throws CloneNotSupportedException
|
||||
{
|
||||
AxesWalker clone = findClone(this, cloneList);
|
||||
if(null != clone)
|
||||
return clone;
|
||||
clone = (AxesWalker)this.clone();
|
||||
clone.setLocPathIterator(cloneOwner);
|
||||
if(null != cloneList)
|
||||
{
|
||||
cloneList.addElement(this);
|
||||
cloneList.addElement(clone);
|
||||
}
|
||||
|
||||
if(wi().m_lastUsedWalker == this)
|
||||
cloneOwner.m_lastUsedWalker = clone;
|
||||
|
||||
if(null != m_nextWalker)
|
||||
clone.m_nextWalker = m_nextWalker.cloneDeep(cloneOwner, cloneList);
|
||||
|
||||
// If you don't check for the cloneList here, you'll go into an
|
||||
// recursive infinate loop.
|
||||
if(null != cloneList)
|
||||
{
|
||||
if(null != m_prevWalker)
|
||||
clone.m_prevWalker = m_prevWalker.cloneDeep(cloneOwner, cloneList);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(null != m_nextWalker)
|
||||
clone.m_nextWalker.m_prevWalker = clone;
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a clone that corresponds to the key argument.
|
||||
*
|
||||
* @param key The original AxesWalker for which there may be a clone.
|
||||
* @param cloneList vector of sources in odd elements, and the
|
||||
* corresponding clones in even vectors, may be null.
|
||||
*
|
||||
* @return A clone that corresponds to the key, or null if key not found.
|
||||
*/
|
||||
static AxesWalker findClone(AxesWalker key, Vector cloneList)
|
||||
{
|
||||
if(null != cloneList)
|
||||
{
|
||||
// First, look for clone on list.
|
||||
int n = cloneList.size();
|
||||
for (int i = 0; i < n; i+=2)
|
||||
{
|
||||
if(key == cloneList.elementAt(i))
|
||||
return (AxesWalker)cloneList.elementAt(i+1);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Detaches the walker from the set which it iterated over, releasing
|
||||
* any computational resources and placing the iterator in the INVALID
|
||||
* state.
|
||||
*/
|
||||
public void detach()
|
||||
{
|
||||
m_currentNode = DTM.NULL;
|
||||
m_dtm = null;
|
||||
m_traverser = null;
|
||||
m_isFresh = true;
|
||||
m_root = DTM.NULL;
|
||||
}
|
||||
|
||||
//=============== TreeWalker Implementation ===============
|
||||
|
||||
/**
|
||||
* The root node of the TreeWalker, as specified in setRoot(int root).
|
||||
* Note that this may actually be below the current node.
|
||||
*
|
||||
* @return The context node of the step.
|
||||
*/
|
||||
public int getRoot()
|
||||
{
|
||||
return m_root;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the analysis bits for this walker, as defined in the WalkerFactory.
|
||||
* @return One of WalkerFactory#BIT_DESCENDANT, etc.
|
||||
*/
|
||||
public int getAnalysisBits()
|
||||
{
|
||||
int axis = getAxis();
|
||||
int bit = WalkerFactory.getAnalysisBitFromAxes(axis);
|
||||
return bit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the root node of the TreeWalker.
|
||||
* (Not part of the DOM2 TreeWalker interface).
|
||||
*
|
||||
* @param root The context node of this step.
|
||||
*/
|
||||
public void setRoot(int root)
|
||||
{
|
||||
// %OPT% Get this directly from the lpi.
|
||||
XPathContext xctxt = wi().getXPathContext();
|
||||
m_dtm = xctxt.getDTM(root);
|
||||
m_traverser = m_dtm.getAxisTraverser(m_axis);
|
||||
m_isFresh = true;
|
||||
m_foundLast = false;
|
||||
m_root = root;
|
||||
m_currentNode = root;
|
||||
|
||||
if (DTM.NULL == root)
|
||||
{
|
||||
throw new RuntimeException(
|
||||
XSLMessages.createXPATHMessage(XPATHErrorResources.ER_SETTING_WALKER_ROOT_TO_NULL, null)); //"\n !!!! Error! Setting the root of a walker to null!!!");
|
||||
}
|
||||
|
||||
resetProximityPositions();
|
||||
}
|
||||
|
||||
/**
|
||||
* The node at which the TreeWalker is currently positioned.
|
||||
* <br> The value must not be null. Alterations to the DOM tree may cause
|
||||
* the current node to no longer be accepted by the TreeWalker's
|
||||
* associated filter. currentNode may also be explicitly set to any node,
|
||||
* whether or not it is within the subtree specified by the root node or
|
||||
* would be accepted by the filter and whatToShow flags. Further
|
||||
* traversal occurs relative to currentNode even if it is not part of the
|
||||
* current view by applying the filters in the requested direction (not
|
||||
* changing currentNode where no traversal is possible).
|
||||
*
|
||||
* @return The node at which the TreeWalker is currently positioned, only null
|
||||
* if setRoot has not yet been called.
|
||||
*/
|
||||
public final int getCurrentNode()
|
||||
{
|
||||
return m_currentNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the next walker in the location step chain.
|
||||
*
|
||||
*
|
||||
* @param walker Reference to AxesWalker derivative, or may be null.
|
||||
*/
|
||||
public void setNextWalker(AxesWalker walker)
|
||||
{
|
||||
m_nextWalker = walker;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next walker in the location step chain.
|
||||
*
|
||||
*
|
||||
* @return Reference to AxesWalker derivative, or null.
|
||||
*/
|
||||
public AxesWalker getNextWalker()
|
||||
{
|
||||
return m_nextWalker;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set or clear the previous walker reference in the location step chain.
|
||||
*
|
||||
*
|
||||
* @param walker Reference to previous walker reference in the location
|
||||
* step chain, or null.
|
||||
*/
|
||||
public void setPrevWalker(AxesWalker walker)
|
||||
{
|
||||
m_prevWalker = walker;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the previous walker reference in the location step chain.
|
||||
*
|
||||
*
|
||||
* @return Reference to previous walker reference in the location
|
||||
* step chain, or null.
|
||||
*/
|
||||
public AxesWalker getPrevWalker()
|
||||
{
|
||||
return m_prevWalker;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is simply a way to bottle-neck the return of the next node, for
|
||||
* diagnostic purposes.
|
||||
*
|
||||
* @param n Node to return, or null.
|
||||
*
|
||||
* @return The argument.
|
||||
*/
|
||||
private int returnNextNode(int n)
|
||||
{
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next node in document order on the axes.
|
||||
*
|
||||
* @return the next node in document order on the axes, or null.
|
||||
*/
|
||||
protected int getNextNode()
|
||||
{
|
||||
if (m_foundLast)
|
||||
return DTM.NULL;
|
||||
|
||||
if (m_isFresh)
|
||||
{
|
||||
m_currentNode = m_traverser.first(m_root);
|
||||
m_isFresh = false;
|
||||
}
|
||||
// I shouldn't have to do this the check for current node, I think.
|
||||
// numbering\numbering24.xsl fails if I don't do this. I think
|
||||
// it occurs as the walkers are backing up. -sb
|
||||
else if(DTM.NULL != m_currentNode)
|
||||
{
|
||||
m_currentNode = m_traverser.next(m_root, m_currentNode);
|
||||
}
|
||||
|
||||
if (DTM.NULL == m_currentNode)
|
||||
this.m_foundLast = true;
|
||||
|
||||
return m_currentNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the <code>TreeWalker</code> to the next visible node in document
|
||||
* order relative to the current node, and returns the new node. If the
|
||||
* current node has no next node, or if the search for nextNode attempts
|
||||
* to step upward from the TreeWalker's root node, returns
|
||||
* <code>null</code> , and retains the current node.
|
||||
* @return The new node, or <code>null</code> if the current node has no
|
||||
* next node in the TreeWalker's logical view.
|
||||
*/
|
||||
public int nextNode()
|
||||
{
|
||||
int nextNode = DTM.NULL;
|
||||
AxesWalker walker = wi().getLastUsedWalker();
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (null == walker)
|
||||
break;
|
||||
|
||||
nextNode = walker.getNextNode();
|
||||
|
||||
if (DTM.NULL == nextNode)
|
||||
{
|
||||
|
||||
walker = walker.m_prevWalker;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (walker.acceptNode(nextNode) != DTMIterator.FILTER_ACCEPT)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (null == walker.m_nextWalker)
|
||||
{
|
||||
wi().setLastUsedWalker(walker);
|
||||
|
||||
// return walker.returnNextNode(nextNode);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
AxesWalker prev = walker;
|
||||
|
||||
walker = walker.m_nextWalker;
|
||||
|
||||
walker.setRoot(nextNode);
|
||||
|
||||
walker.m_prevWalker = prev;
|
||||
|
||||
continue;
|
||||
}
|
||||
} // if(null != nextNode)
|
||||
} // while(null != walker)
|
||||
|
||||
return nextNode;
|
||||
}
|
||||
|
||||
//============= End TreeWalker Implementation =============
|
||||
|
||||
/**
|
||||
* Get the index of the last node that can be itterated to.
|
||||
*
|
||||
*
|
||||
* @param xctxt XPath runtime context.
|
||||
*
|
||||
* @return the index of the last node that can be itterated to.
|
||||
*/
|
||||
public int getLastPos(XPathContext xctxt)
|
||||
{
|
||||
|
||||
int pos = getProximityPosition();
|
||||
|
||||
AxesWalker walker;
|
||||
|
||||
try
|
||||
{
|
||||
walker = (AxesWalker) clone();
|
||||
}
|
||||
catch (CloneNotSupportedException cnse)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
walker.setPredicateCount(m_predicateIndex);
|
||||
walker.setNextWalker(null);
|
||||
walker.setPrevWalker(null);
|
||||
|
||||
WalkingIterator lpi = wi();
|
||||
AxesWalker savedWalker = lpi.getLastUsedWalker();
|
||||
|
||||
try
|
||||
{
|
||||
lpi.setLastUsedWalker(walker);
|
||||
|
||||
int next;
|
||||
|
||||
while (DTM.NULL != (next = walker.nextNode()))
|
||||
{
|
||||
pos++;
|
||||
}
|
||||
|
||||
// TODO: Should probably save this in the iterator.
|
||||
}
|
||||
finally
|
||||
{
|
||||
lpi.setLastUsedWalker(savedWalker);
|
||||
}
|
||||
|
||||
// System.out.println("pos: "+pos);
|
||||
return pos;
|
||||
}
|
||||
|
||||
//============= State Data =============
|
||||
|
||||
/**
|
||||
* The DTM for the root. This can not be used, or must be changed,
|
||||
* for the filter walker, or any walker that can have nodes
|
||||
* from multiple documents.
|
||||
* Never, ever, access this value without going through getDTM(int node).
|
||||
*/
|
||||
private DTM m_dtm;
|
||||
|
||||
/**
|
||||
* Set the DTM for this walker.
|
||||
*
|
||||
* @param dtm Non-null reference to a DTM.
|
||||
*/
|
||||
public void setDefaultDTM(DTM dtm)
|
||||
{
|
||||
m_dtm = dtm;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the DTM for this walker.
|
||||
*
|
||||
* @return Non-null reference to a DTM.
|
||||
*/
|
||||
public DTM getDTM(int node)
|
||||
{
|
||||
//
|
||||
return wi().getXPathContext().getDTM(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if all the nodes in the iteration well be returned in document
|
||||
* order.
|
||||
* Warning: This can only be called after setRoot has been called!
|
||||
*
|
||||
* @return true as a default.
|
||||
*/
|
||||
public boolean isDocOrdered()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the axis being iterated, if it is known.
|
||||
*
|
||||
* @return Axis.CHILD, etc., or -1 if the axis is not known or is of multiple
|
||||
* types.
|
||||
*/
|
||||
public int getAxis()
|
||||
{
|
||||
return m_axis;
|
||||
}
|
||||
|
||||
/**
|
||||
* This will traverse the heararchy, calling the visitor for
|
||||
* each member. If the called visitor method returns
|
||||
* false, the subtree should not be called.
|
||||
*
|
||||
* @param owner The owner of the visitor, where that path may be
|
||||
* rewritten if needed.
|
||||
* @param visitor The visitor whose appropriate method will be called.
|
||||
*/
|
||||
public void callVisitors(ExpressionOwner owner, XPathVisitor visitor)
|
||||
{
|
||||
if(visitor.visitStep(owner, this))
|
||||
{
|
||||
callPredicateVisitors(visitor);
|
||||
if(null != m_nextWalker)
|
||||
{
|
||||
m_nextWalker.callVisitors(this, visitor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ExpressionOwner#getExpression()
|
||||
*/
|
||||
public Expression getExpression()
|
||||
{
|
||||
return m_nextWalker;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ExpressionOwner#setExpression(Expression)
|
||||
*/
|
||||
public void setExpression(Expression exp)
|
||||
{
|
||||
exp.exprSetParent(this);
|
||||
m_nextWalker = (AxesWalker)exp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Expression#deepEquals(Expression)
|
||||
*/
|
||||
public boolean deepEquals(Expression expr)
|
||||
{
|
||||
if (!super.deepEquals(expr))
|
||||
return false;
|
||||
|
||||
AxesWalker walker = (AxesWalker)expr;
|
||||
if(this.m_axis != walker.m_axis)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* The root node of the TreeWalker, as specified when it was created.
|
||||
*/
|
||||
transient int m_root = DTM.NULL;
|
||||
|
||||
/**
|
||||
* The node at which the TreeWalker is currently positioned.
|
||||
*/
|
||||
private transient int m_currentNode = DTM.NULL;
|
||||
|
||||
/** True if an itteration has not begun. */
|
||||
transient boolean m_isFresh;
|
||||
|
||||
/** The next walker in the location step chain.
|
||||
* @serial */
|
||||
protected AxesWalker m_nextWalker;
|
||||
|
||||
/** The previous walker in the location step chain, or null.
|
||||
* @serial */
|
||||
AxesWalker m_prevWalker;
|
||||
|
||||
/** The traversal axis from where the nodes will be filtered. */
|
||||
protected int m_axis = -1;
|
||||
|
||||
/** The DTM inner traversal class, that corresponds to the super axis. */
|
||||
protected DTMAxisTraverser m_traverser;
|
||||
}
|
||||
@@ -0,0 +1,226 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.axes;
|
||||
|
||||
import com.sun.org.apache.xml.internal.dtm.DTM;
|
||||
import com.sun.org.apache.xml.internal.dtm.DTMFilter;
|
||||
import com.sun.org.apache.xml.internal.dtm.DTMIterator;
|
||||
import com.sun.org.apache.xml.internal.utils.PrefixResolver;
|
||||
import com.sun.org.apache.xpath.internal.compiler.Compiler;
|
||||
import com.sun.org.apache.xpath.internal.compiler.OpMap;
|
||||
|
||||
/**
|
||||
* Base for iterators that handle predicates. Does the basic next
|
||||
* node logic, so all the derived iterator has to do is get the
|
||||
* next node.
|
||||
*/
|
||||
public abstract class BasicTestIterator extends LocPathIterator
|
||||
{
|
||||
static final long serialVersionUID = 3505378079378096623L;
|
||||
/**
|
||||
* Create a LocPathIterator object.
|
||||
*
|
||||
* @param nscontext The namespace context for this iterator,
|
||||
* should be OK if null.
|
||||
*/
|
||||
protected BasicTestIterator()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a LocPathIterator object.
|
||||
*
|
||||
* @param nscontext The namespace context for this iterator,
|
||||
* should be OK if null.
|
||||
*/
|
||||
protected BasicTestIterator(PrefixResolver nscontext)
|
||||
{
|
||||
|
||||
super(nscontext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a LocPathIterator object, including creation
|
||||
* of step walkers from the opcode list, and call back
|
||||
* into the Compiler to create predicate expressions.
|
||||
*
|
||||
* @param compiler The Compiler which is creating
|
||||
* this expression.
|
||||
* @param opPos The position of this iterator in the
|
||||
* opcode list from the compiler.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
protected BasicTestIterator(Compiler compiler, int opPos, int analysis)
|
||||
throws javax.xml.transform.TransformerException
|
||||
{
|
||||
super(compiler, opPos, analysis, false);
|
||||
|
||||
int firstStepPos = OpMap.getFirstChildPos(opPos);
|
||||
int whatToShow = compiler.getWhatToShow(firstStepPos);
|
||||
|
||||
if ((0 == (whatToShow
|
||||
& (DTMFilter.SHOW_ATTRIBUTE
|
||||
| DTMFilter.SHOW_NAMESPACE
|
||||
| DTMFilter.SHOW_ELEMENT
|
||||
| DTMFilter.SHOW_PROCESSING_INSTRUCTION)))
|
||||
|| (whatToShow == DTMFilter.SHOW_ALL))
|
||||
initNodeTest(whatToShow);
|
||||
else
|
||||
{
|
||||
initNodeTest(whatToShow, compiler.getStepNS(firstStepPos),
|
||||
compiler.getStepLocalName(firstStepPos));
|
||||
}
|
||||
initPredicateInfo(compiler, firstStepPos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a LocPathIterator object, including creation
|
||||
* of step walkers from the opcode list, and call back
|
||||
* into the Compiler to create predicate expressions.
|
||||
*
|
||||
* @param compiler The Compiler which is creating
|
||||
* this expression.
|
||||
* @param opPos The position of this iterator in the
|
||||
* opcode list from the compiler.
|
||||
* @param shouldLoadWalkers True if walkers should be
|
||||
* loaded, or false if this is a derived iterator and
|
||||
* it doesn't wish to load child walkers.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
protected BasicTestIterator(
|
||||
Compiler compiler, int opPos, int analysis, boolean shouldLoadWalkers)
|
||||
throws javax.xml.transform.TransformerException
|
||||
{
|
||||
super(compiler, opPos, analysis, shouldLoadWalkers);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the next node via getNextXXX. Bottlenecked for derived class override.
|
||||
* @return The next node on the axis, or DTM.NULL.
|
||||
*/
|
||||
protected abstract int getNextNode();
|
||||
|
||||
/**
|
||||
* Returns the next node in the set and advances the position of the
|
||||
* iterator in the set. After a NodeIterator is created, the first call
|
||||
* to nextNode() returns the first node in the set.
|
||||
*
|
||||
* @return The next <code>Node</code> in the set being iterated over, or
|
||||
* <code>null</code> if there are no more members in that set.
|
||||
*/
|
||||
public int nextNode()
|
||||
{
|
||||
if(m_foundLast)
|
||||
{
|
||||
m_lastFetched = DTM.NULL;
|
||||
return DTM.NULL;
|
||||
}
|
||||
|
||||
if(DTM.NULL == m_lastFetched)
|
||||
{
|
||||
resetProximityPositions();
|
||||
}
|
||||
|
||||
int next;
|
||||
|
||||
com.sun.org.apache.xpath.internal.VariableStack vars;
|
||||
int savedStart;
|
||||
if (-1 != m_stackFrame)
|
||||
{
|
||||
vars = m_execContext.getVarStack();
|
||||
|
||||
// These three statements need to be combined into one operation.
|
||||
savedStart = vars.getStackFrame();
|
||||
|
||||
vars.setStackFrame(m_stackFrame);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Yuck. Just to shut up the compiler!
|
||||
vars = null;
|
||||
savedStart = 0;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
do
|
||||
{
|
||||
next = getNextNode();
|
||||
|
||||
if (DTM.NULL != next)
|
||||
{
|
||||
if(DTMIterator.FILTER_ACCEPT == acceptNode(next))
|
||||
break;
|
||||
else
|
||||
continue;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
while (next != DTM.NULL);
|
||||
|
||||
if (DTM.NULL != next)
|
||||
{
|
||||
m_pos++;
|
||||
return next;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_foundLast = true;
|
||||
|
||||
return DTM.NULL;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (-1 != m_stackFrame)
|
||||
{
|
||||
// These two statements need to be combined into one operation.
|
||||
vars.setStackFrame(savedStart);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a cloned Iterator that is reset to the beginning
|
||||
* of the query.
|
||||
*
|
||||
* @return A cloned NodeIterator set of the start of the query.
|
||||
*
|
||||
* @throws CloneNotSupportedException
|
||||
*/
|
||||
public DTMIterator cloneWithReset() throws CloneNotSupportedException
|
||||
{
|
||||
|
||||
ChildTestIterator clone = (ChildTestIterator) super.cloneWithReset();
|
||||
|
||||
clone.resetProximityPositions();
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.axes;
|
||||
|
||||
import com.sun.org.apache.xml.internal.dtm.DTM;
|
||||
import com.sun.org.apache.xml.internal.dtm.DTMFilter;
|
||||
import com.sun.org.apache.xpath.internal.XPathContext;
|
||||
import com.sun.org.apache.xpath.internal.compiler.Compiler;
|
||||
|
||||
/**
|
||||
* This class implements an optimized iterator for
|
||||
* "node()" patterns, that is, any children of the
|
||||
* context node.
|
||||
* @see com.sun.org.apache.xpath.internal.axes.LocPathIterator
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public class ChildIterator extends LocPathIterator
|
||||
{
|
||||
static final long serialVersionUID = -6935428015142993583L;
|
||||
|
||||
/**
|
||||
* Create a ChildIterator object.
|
||||
*
|
||||
* @param compiler A reference to the Compiler that contains the op map.
|
||||
* @param opPos The position within the op map, which contains the
|
||||
* location path expression for this itterator.
|
||||
* @param analysis Analysis bits of the entire pattern.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
ChildIterator(Compiler compiler, int opPos, int analysis)
|
||||
throws javax.xml.transform.TransformerException
|
||||
{
|
||||
super(compiler, opPos, analysis, false);
|
||||
|
||||
// This iterator matches all kinds of nodes
|
||||
initNodeTest(DTMFilter.SHOW_ALL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the first node out of the nodeset, if this expression is
|
||||
* a nodeset expression. This is the default implementation for
|
||||
* nodesets.
|
||||
* <p>WARNING: Do not mutate this class from this function!</p>
|
||||
* @param xctxt The XPath runtime context.
|
||||
* @return the first node out of the nodeset, or DTM.NULL.
|
||||
*/
|
||||
public int asNode(XPathContext xctxt)
|
||||
throws javax.xml.transform.TransformerException
|
||||
{
|
||||
int current = xctxt.getCurrentNode();
|
||||
|
||||
DTM dtm = xctxt.getDTM(current);
|
||||
|
||||
return dtm.getFirstChild(current);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the next node in the set and advances the position of the
|
||||
* iterator in the set. After a NodeIterator is created, the first call
|
||||
* to nextNode() returns the first node in the set.
|
||||
*
|
||||
* @return The next <code>Node</code> in the set being iterated over, or
|
||||
* <code>null</code> if there are no more members in that set.
|
||||
*/
|
||||
public int nextNode()
|
||||
{
|
||||
if(m_foundLast)
|
||||
return DTM.NULL;
|
||||
|
||||
int next;
|
||||
|
||||
m_lastFetched = next = (DTM.NULL == m_lastFetched)
|
||||
? m_cdtm.getFirstChild(m_context)
|
||||
: m_cdtm.getNextSibling(m_lastFetched);
|
||||
|
||||
// m_lastFetched = next;
|
||||
if (DTM.NULL != next)
|
||||
{
|
||||
m_pos++;
|
||||
return next;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_foundLast = true;
|
||||
|
||||
return DTM.NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the axis being iterated, if it is known.
|
||||
*
|
||||
* @return Axis.CHILD, etc., or -1 if the axis is not known or is of multiple
|
||||
* types.
|
||||
*/
|
||||
public int getAxis()
|
||||
{
|
||||
return com.sun.org.apache.xml.internal.dtm.Axis.CHILD;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.axes;
|
||||
|
||||
import com.sun.org.apache.xml.internal.dtm.Axis;
|
||||
import com.sun.org.apache.xml.internal.dtm.DTM;
|
||||
import com.sun.org.apache.xml.internal.dtm.DTMAxisTraverser;
|
||||
import com.sun.org.apache.xml.internal.dtm.DTMIterator;
|
||||
import com.sun.org.apache.xpath.internal.compiler.Compiler;
|
||||
|
||||
/**
|
||||
* This class implements an optimized iterator for
|
||||
* children patterns that have a node test, and possibly a predicate.
|
||||
* @see com.sun.org.apache.xpath.internal.axes.BasicTestIterator
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public class ChildTestIterator extends BasicTestIterator
|
||||
{
|
||||
static final long serialVersionUID = -7936835957960705722L;
|
||||
/** The traverser to use to navigate over the descendants. */
|
||||
transient protected DTMAxisTraverser m_traverser;
|
||||
|
||||
/** The extended type ID, not set until setRoot. */
|
||||
// protected int m_extendedTypeID;
|
||||
|
||||
|
||||
/**
|
||||
* Create a ChildTestIterator object.
|
||||
*
|
||||
* @param compiler A reference to the Compiler that contains the op map.
|
||||
* @param opPos The position within the op map, which contains the
|
||||
* location path expression for this itterator.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
ChildTestIterator(Compiler compiler, int opPos, int analysis)
|
||||
throws javax.xml.transform.TransformerException
|
||||
{
|
||||
super(compiler, opPos, analysis);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a ChildTestIterator object.
|
||||
*
|
||||
* @param traverser Traverser that tells how the KeyIterator is to be handled.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
public ChildTestIterator(DTMAxisTraverser traverser)
|
||||
{
|
||||
|
||||
super(null);
|
||||
|
||||
m_traverser = traverser;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next node via getNextXXX. Bottlenecked for derived class override.
|
||||
* @return The next node on the axis, or DTM.NULL.
|
||||
*/
|
||||
protected int getNextNode()
|
||||
{
|
||||
if(true /* 0 == m_extendedTypeID */)
|
||||
{
|
||||
m_lastFetched = (DTM.NULL == m_lastFetched)
|
||||
? m_traverser.first(m_context)
|
||||
: m_traverser.next(m_context, m_lastFetched);
|
||||
}
|
||||
// else
|
||||
// {
|
||||
// m_lastFetched = (DTM.NULL == m_lastFetched)
|
||||
// ? m_traverser.first(m_context, m_extendedTypeID)
|
||||
// : m_traverser.next(m_context, m_lastFetched,
|
||||
// m_extendedTypeID);
|
||||
// }
|
||||
|
||||
return m_lastFetched;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get a cloned Iterator that is reset to the beginning
|
||||
* of the query.
|
||||
*
|
||||
* @return A cloned NodeIterator set of the start of the query.
|
||||
*
|
||||
* @throws CloneNotSupportedException
|
||||
*/
|
||||
public DTMIterator cloneWithReset() throws CloneNotSupportedException
|
||||
{
|
||||
|
||||
ChildTestIterator clone = (ChildTestIterator) super.cloneWithReset();
|
||||
clone.m_traverser = m_traverser;
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize the context values for this expression
|
||||
* after it is cloned.
|
||||
*
|
||||
* @param context The XPath runtime context for this
|
||||
* transformation.
|
||||
*/
|
||||
public void setRoot(int context, Object environment)
|
||||
{
|
||||
super.setRoot(context, environment);
|
||||
m_traverser = m_cdtm.getAxisTraverser(Axis.CHILD);
|
||||
|
||||
// String localName = getLocalName();
|
||||
// String namespace = getNamespace();
|
||||
// int what = m_whatToShow;
|
||||
// // System.out.println("what: ");
|
||||
// // NodeTest.debugWhatToShow(what);
|
||||
// if(DTMFilter.SHOW_ALL == what ||
|
||||
// ((DTMFilter.SHOW_ELEMENT & what) == 0)
|
||||
// || localName == NodeTest.WILD
|
||||
// || namespace == NodeTest.WILD)
|
||||
// {
|
||||
// m_extendedTypeID = 0;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// int type = getNodeTypeTest(what);
|
||||
// m_extendedTypeID = m_cdtm.getExpandedTypeID(namespace, localName, type);
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the axis being iterated, if it is known.
|
||||
*
|
||||
* @return Axis.CHILD, etc., or -1 if the axis is not known or is of multiple
|
||||
* types.
|
||||
*/
|
||||
public int getAxis()
|
||||
{
|
||||
return com.sun.org.apache.xml.internal.dtm.Axis.CHILD;
|
||||
}
|
||||
|
||||
/**
|
||||
* Detaches the iterator from the set which it iterated over, releasing
|
||||
* any computational resources and placing the iterator in the INVALID
|
||||
* state. After<code>detach</code> has been invoked, calls to
|
||||
* <code>nextNode</code> or<code>previousNode</code> will raise the
|
||||
* exception INVALID_STATE_ERR.
|
||||
*/
|
||||
public void detach()
|
||||
{
|
||||
if(m_allowDetach)
|
||||
{
|
||||
m_traverser = null;
|
||||
|
||||
// Always call the superclass detach last!
|
||||
super.detach();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.axes;
|
||||
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.traversal.NodeIterator;
|
||||
|
||||
/**
|
||||
* Classes who implement this interface can be a
|
||||
* <a href="http://www.w3.org/TR/xslt#dt-current-node-list">current node list</a>,
|
||||
* also refered to here as a <term>context node list</term>.
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public interface ContextNodeList
|
||||
{
|
||||
|
||||
/**
|
||||
* Get the <a href="http://www.w3.org/TR/xslt#dt-current-node">current node</a>.
|
||||
*
|
||||
*
|
||||
* @return The current node, or null.
|
||||
*/
|
||||
public Node getCurrentNode();
|
||||
|
||||
/**
|
||||
* Get the current position, which is one less than
|
||||
* the next nextNode() call will retrieve. i.e. if
|
||||
* you call getCurrentPos() and the return is 0, the next
|
||||
* fetch will take place at index 1.
|
||||
*
|
||||
* @return The position of the
|
||||
* <a href="http://www.w3.org/TR/xslt#dt-current-node">current node</a>
|
||||
* in the <a href="http://www.w3.org/TR/xslt#dt-current-node-list">current node list</a>.
|
||||
*/
|
||||
public int getCurrentPos();
|
||||
|
||||
/**
|
||||
* Reset the iterator.
|
||||
*/
|
||||
public void reset();
|
||||
|
||||
/**
|
||||
* If setShouldCacheNodes(true) is called, then nodes will
|
||||
* be cached. They are not cached by default.
|
||||
*
|
||||
* @param b true if the nodes should be cached.
|
||||
*/
|
||||
public void setShouldCacheNodes(boolean b);
|
||||
|
||||
/**
|
||||
* If an index is requested, NodeSetDTM will call this method
|
||||
* to run the iterator to the index. By default this sets
|
||||
* m_next to the index. If the index argument is -1, this
|
||||
* signals that the iterator should be run to the end.
|
||||
*
|
||||
* @param index The index to run to, or -1 if the iterator should be run
|
||||
* to the end.
|
||||
*/
|
||||
public void runTo(int index);
|
||||
|
||||
/**
|
||||
* Set the current position in the node set.
|
||||
* @param i Must be a valid index.
|
||||
*/
|
||||
public void setCurrentPos(int i);
|
||||
|
||||
/**
|
||||
* Get the length of the list.
|
||||
*
|
||||
* @return The number of nodes in this node list.
|
||||
*/
|
||||
public int size();
|
||||
|
||||
/**
|
||||
* Tells if this NodeSetDTM is "fresh", in other words, if
|
||||
* the first nextNode() that is called will return the
|
||||
* first node in the set.
|
||||
*
|
||||
* @return true if the iteration of this list has not yet begun.
|
||||
*/
|
||||
public boolean isFresh();
|
||||
|
||||
/**
|
||||
* Get a cloned Iterator that is reset to the start of the iteration.
|
||||
*
|
||||
* @return A clone of this iteration that has been reset.
|
||||
*
|
||||
* @throws CloneNotSupportedException
|
||||
*/
|
||||
public NodeIterator cloneWithReset() throws CloneNotSupportedException;
|
||||
|
||||
/**
|
||||
* Get a clone of this iterator. Be aware that this operation may be
|
||||
* somewhat expensive.
|
||||
*
|
||||
*
|
||||
* @return A clone of this object.
|
||||
*
|
||||
* @throws CloneNotSupportedException
|
||||
*/
|
||||
public Object clone() throws CloneNotSupportedException;
|
||||
|
||||
/**
|
||||
* Get the index of the last node in this list.
|
||||
*
|
||||
*
|
||||
* @return the index of the last node in this list.
|
||||
*/
|
||||
public int getLast();
|
||||
|
||||
/**
|
||||
* Set the index of the last node in this list.
|
||||
*
|
||||
*
|
||||
* @param last the index of the last node in this list.
|
||||
*/
|
||||
public void setLast(int last);
|
||||
}
|
||||
@@ -0,0 +1,382 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.axes;
|
||||
|
||||
import com.sun.org.apache.xml.internal.dtm.Axis;
|
||||
import com.sun.org.apache.xml.internal.dtm.DTM;
|
||||
import com.sun.org.apache.xml.internal.dtm.DTMAxisTraverser;
|
||||
import com.sun.org.apache.xml.internal.dtm.DTMFilter;
|
||||
import com.sun.org.apache.xml.internal.dtm.DTMIterator;
|
||||
import com.sun.org.apache.xpath.internal.Expression;
|
||||
import com.sun.org.apache.xpath.internal.XPathContext;
|
||||
import com.sun.org.apache.xpath.internal.compiler.Compiler;
|
||||
import com.sun.org.apache.xpath.internal.compiler.OpCodes;
|
||||
import com.sun.org.apache.xpath.internal.compiler.OpMap;
|
||||
import com.sun.org.apache.xpath.internal.patterns.NodeTest;
|
||||
import org.w3c.dom.DOMException;
|
||||
|
||||
/**
|
||||
* This class implements an optimized iterator for
|
||||
* descendant, descendant-or-self, or "//foo" patterns.
|
||||
* @see com.sun.org.apache.xpath.internal.axes.LocPathIterator
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public class DescendantIterator extends LocPathIterator
|
||||
{
|
||||
static final long serialVersionUID = -1190338607743976938L;
|
||||
/**
|
||||
* Create a DescendantIterator object.
|
||||
*
|
||||
* @param compiler A reference to the Compiler that contains the op map.
|
||||
* @param opPos The position within the op map, which contains the
|
||||
* location path expression for this itterator.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
DescendantIterator(Compiler compiler, int opPos, int analysis)
|
||||
throws javax.xml.transform.TransformerException
|
||||
{
|
||||
|
||||
super(compiler, opPos, analysis, false);
|
||||
|
||||
int firstStepPos = OpMap.getFirstChildPos(opPos);
|
||||
int stepType = compiler.getOp(firstStepPos);
|
||||
|
||||
boolean orSelf = (OpCodes.FROM_DESCENDANTS_OR_SELF == stepType);
|
||||
boolean fromRoot = false;
|
||||
if (OpCodes.FROM_SELF == stepType)
|
||||
{
|
||||
orSelf = true;
|
||||
// firstStepPos += 8;
|
||||
}
|
||||
else if(OpCodes.FROM_ROOT == stepType)
|
||||
{
|
||||
fromRoot = true;
|
||||
// Ugly code... will go away when AST work is done.
|
||||
int nextStepPos = compiler.getNextStepPos(firstStepPos);
|
||||
if(compiler.getOp(nextStepPos) == OpCodes.FROM_DESCENDANTS_OR_SELF)
|
||||
orSelf = true;
|
||||
// firstStepPos += 8;
|
||||
}
|
||||
|
||||
// Find the position of the last step.
|
||||
int nextStepPos = firstStepPos;
|
||||
while(true)
|
||||
{
|
||||
nextStepPos = compiler.getNextStepPos(nextStepPos);
|
||||
if(nextStepPos > 0)
|
||||
{
|
||||
int stepOp = compiler.getOp(nextStepPos);
|
||||
if(OpCodes.ENDOP != stepOp)
|
||||
firstStepPos = nextStepPos;
|
||||
else
|
||||
break;
|
||||
}
|
||||
else
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
// Fix for http://nagoya.apache.org/bugzilla/show_bug.cgi?id=1336
|
||||
if((analysis & WalkerFactory.BIT_CHILD) != 0)
|
||||
orSelf = false;
|
||||
|
||||
if(fromRoot)
|
||||
{
|
||||
if(orSelf)
|
||||
m_axis = Axis.DESCENDANTSORSELFFROMROOT;
|
||||
else
|
||||
m_axis = Axis.DESCENDANTSFROMROOT;
|
||||
}
|
||||
else if(orSelf)
|
||||
m_axis = Axis.DESCENDANTORSELF;
|
||||
else
|
||||
m_axis = Axis.DESCENDANT;
|
||||
|
||||
int whatToShow = compiler.getWhatToShow(firstStepPos);
|
||||
|
||||
if ((0 == (whatToShow
|
||||
& (DTMFilter.SHOW_ATTRIBUTE | DTMFilter.SHOW_ELEMENT
|
||||
| DTMFilter.SHOW_PROCESSING_INSTRUCTION))) ||
|
||||
(whatToShow == DTMFilter.SHOW_ALL))
|
||||
initNodeTest(whatToShow);
|
||||
else
|
||||
{
|
||||
initNodeTest(whatToShow, compiler.getStepNS(firstStepPos),
|
||||
compiler.getStepLocalName(firstStepPos));
|
||||
}
|
||||
initPredicateInfo(compiler, firstStepPos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a DescendantIterator object.
|
||||
*
|
||||
*/
|
||||
public DescendantIterator()
|
||||
{
|
||||
super(null);
|
||||
m_axis = Axis.DESCENDANTSORSELFFROMROOT;
|
||||
int whatToShow = DTMFilter.SHOW_ALL;
|
||||
initNodeTest(whatToShow);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get a cloned Iterator that is reset to the beginning
|
||||
* of the query.
|
||||
*
|
||||
* @return A cloned NodeIterator set of the start of the query.
|
||||
*
|
||||
* @throws CloneNotSupportedException
|
||||
*/
|
||||
public DTMIterator cloneWithReset() throws CloneNotSupportedException
|
||||
{
|
||||
|
||||
DescendantIterator clone = (DescendantIterator) super.cloneWithReset();
|
||||
clone.m_traverser = m_traverser;
|
||||
|
||||
clone.resetProximityPositions();
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the next node in the set and advances the position of the
|
||||
* iterator in the set. After a NodeIterator is created, the first call
|
||||
* to nextNode() returns the first node in the set.
|
||||
*
|
||||
* @return The next <code>Node</code> in the set being iterated over, or
|
||||
* <code>null</code> if there are no more members in that set.
|
||||
*
|
||||
* @throws DOMException
|
||||
* INVALID_STATE_ERR: Raised if this method is called after the
|
||||
* <code>detach</code> method was invoked.
|
||||
*/
|
||||
public int nextNode()
|
||||
{
|
||||
if(m_foundLast)
|
||||
return DTM.NULL;
|
||||
|
||||
if(DTM.NULL == m_lastFetched)
|
||||
{
|
||||
resetProximityPositions();
|
||||
}
|
||||
|
||||
int next;
|
||||
|
||||
com.sun.org.apache.xpath.internal.VariableStack vars;
|
||||
int savedStart;
|
||||
if (-1 != m_stackFrame)
|
||||
{
|
||||
vars = m_execContext.getVarStack();
|
||||
|
||||
// These three statements need to be combined into one operation.
|
||||
savedStart = vars.getStackFrame();
|
||||
|
||||
vars.setStackFrame(m_stackFrame);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Yuck. Just to shut up the compiler!
|
||||
vars = null;
|
||||
savedStart = 0;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
do
|
||||
{
|
||||
if(0 == m_extendedTypeID)
|
||||
{
|
||||
next = m_lastFetched = (DTM.NULL == m_lastFetched)
|
||||
? m_traverser.first(m_context)
|
||||
: m_traverser.next(m_context, m_lastFetched);
|
||||
}
|
||||
else
|
||||
{
|
||||
next = m_lastFetched = (DTM.NULL == m_lastFetched)
|
||||
? m_traverser.first(m_context, m_extendedTypeID)
|
||||
: m_traverser.next(m_context, m_lastFetched,
|
||||
m_extendedTypeID);
|
||||
}
|
||||
|
||||
if (DTM.NULL != next)
|
||||
{
|
||||
if(DTMIterator.FILTER_ACCEPT == acceptNode(next))
|
||||
break;
|
||||
else
|
||||
continue;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
while (next != DTM.NULL);
|
||||
|
||||
if (DTM.NULL != next)
|
||||
{
|
||||
m_pos++;
|
||||
return next;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_foundLast = true;
|
||||
|
||||
return DTM.NULL;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (-1 != m_stackFrame)
|
||||
{
|
||||
// These two statements need to be combined into one operation.
|
||||
vars.setStackFrame(savedStart);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the context values for this expression
|
||||
* after it is cloned.
|
||||
*
|
||||
* @param context The XPath runtime context for this
|
||||
* transformation.
|
||||
*/
|
||||
public void setRoot(int context, Object environment)
|
||||
{
|
||||
super.setRoot(context, environment);
|
||||
m_traverser = m_cdtm.getAxisTraverser(m_axis);
|
||||
|
||||
String localName = getLocalName();
|
||||
String namespace = getNamespace();
|
||||
int what = m_whatToShow;
|
||||
// System.out.println("what: ");
|
||||
// NodeTest.debugWhatToShow(what);
|
||||
if(DTMFilter.SHOW_ALL == what
|
||||
|| NodeTest.WILD.equals(localName)
|
||||
|| NodeTest.WILD.equals(namespace))
|
||||
{
|
||||
m_extendedTypeID = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
int type = getNodeTypeTest(what);
|
||||
m_extendedTypeID = m_cdtm.getExpandedTypeID(namespace, localName, type);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the first node out of the nodeset, if this expression is
|
||||
* a nodeset expression. This is the default implementation for
|
||||
* nodesets.
|
||||
* <p>WARNING: Do not mutate this class from this function!</p>
|
||||
* @param xctxt The XPath runtime context.
|
||||
* @return the first node out of the nodeset, or DTM.NULL.
|
||||
*/
|
||||
public int asNode(XPathContext xctxt)
|
||||
throws javax.xml.transform.TransformerException
|
||||
{
|
||||
if(getPredicateCount() > 0)
|
||||
return super.asNode(xctxt);
|
||||
|
||||
int current = xctxt.getCurrentNode();
|
||||
|
||||
DTM dtm = xctxt.getDTM(current);
|
||||
DTMAxisTraverser traverser = dtm.getAxisTraverser(m_axis);
|
||||
|
||||
String localName = getLocalName();
|
||||
String namespace = getNamespace();
|
||||
int what = m_whatToShow;
|
||||
|
||||
// System.out.print(" (DescendantIterator) ");
|
||||
|
||||
// System.out.println("what: ");
|
||||
// NodeTest.debugWhatToShow(what);
|
||||
if(DTMFilter.SHOW_ALL == what
|
||||
|| localName == NodeTest.WILD
|
||||
|| namespace == NodeTest.WILD)
|
||||
{
|
||||
return traverser.first(current);
|
||||
}
|
||||
else
|
||||
{
|
||||
int type = getNodeTypeTest(what);
|
||||
int extendedType = dtm.getExpandedTypeID(namespace, localName, type);
|
||||
return traverser.first(current, extendedType);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Detaches the iterator from the set which it iterated over, releasing
|
||||
* any computational resources and placing the iterator in the INVALID
|
||||
* state. After<code>detach</code> has been invoked, calls to
|
||||
* <code>nextNode</code> or<code>previousNode</code> will raise the
|
||||
* exception INVALID_STATE_ERR.
|
||||
*/
|
||||
public void detach()
|
||||
{
|
||||
if (m_allowDetach) {
|
||||
m_traverser = null;
|
||||
m_extendedTypeID = 0;
|
||||
|
||||
// Always call the superclass detach last!
|
||||
super.detach();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the axis being iterated, if it is known.
|
||||
*
|
||||
* @return Axis.CHILD, etc., or -1 if the axis is not known or is of multiple
|
||||
* types.
|
||||
*/
|
||||
public int getAxis()
|
||||
{
|
||||
return m_axis;
|
||||
}
|
||||
|
||||
|
||||
/** The traverser to use to navigate over the descendants. */
|
||||
transient protected DTMAxisTraverser m_traverser;
|
||||
|
||||
/** The axis that we are traversing. */
|
||||
protected int m_axis;
|
||||
|
||||
/** The extended type ID, not set until setRoot. */
|
||||
protected int m_extendedTypeID;
|
||||
|
||||
/**
|
||||
* @see Expression#deepEquals(Expression)
|
||||
*/
|
||||
public boolean deepEquals(Expression expr)
|
||||
{
|
||||
if(!super.deepEquals(expr))
|
||||
return false;
|
||||
|
||||
if(m_axis != ((DescendantIterator)expr).m_axis)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,215 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.axes;
|
||||
|
||||
import com.sun.org.apache.xml.internal.dtm.DTM;
|
||||
import com.sun.org.apache.xpath.internal.Expression;
|
||||
import com.sun.org.apache.xpath.internal.ExpressionOwner;
|
||||
import com.sun.org.apache.xpath.internal.XPathVisitor;
|
||||
import com.sun.org.apache.xpath.internal.objects.XNodeSet;
|
||||
|
||||
public class FilterExprIterator extends BasicTestIterator
|
||||
{
|
||||
static final long serialVersionUID = 2552176105165737614L;
|
||||
/** The contained expression. Should be non-null.
|
||||
* @serial */
|
||||
private Expression m_expr;
|
||||
|
||||
/** The result of executing m_expr. Needs to be deep cloned on clone op. */
|
||||
transient private XNodeSet m_exprObj;
|
||||
|
||||
private boolean m_mustHardReset = false;
|
||||
private boolean m_canDetachNodeset = true;
|
||||
|
||||
/**
|
||||
* Create a FilterExprIterator object.
|
||||
*
|
||||
*/
|
||||
public FilterExprIterator()
|
||||
{
|
||||
super(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a FilterExprIterator object.
|
||||
*
|
||||
*/
|
||||
public FilterExprIterator(Expression expr)
|
||||
{
|
||||
super(null);
|
||||
m_expr = expr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the context values for this expression
|
||||
* after it is cloned.
|
||||
*
|
||||
* @param context The XPath runtime context for this
|
||||
* transformation.
|
||||
*/
|
||||
public void setRoot(int context, Object environment)
|
||||
{
|
||||
super.setRoot(context, environment);
|
||||
|
||||
m_exprObj = FilterExprIteratorSimple.executeFilterExpr(context,
|
||||
m_execContext, getPrefixResolver(),
|
||||
getIsTopLevel(), m_stackFrame, m_expr);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the next node via getNextXXX. Bottlenecked for derived class override.
|
||||
* @return The next node on the axis, or DTM.NULL.
|
||||
*/
|
||||
protected int getNextNode()
|
||||
{
|
||||
if (null != m_exprObj)
|
||||
{
|
||||
m_lastFetched = m_exprObj.nextNode();
|
||||
}
|
||||
else
|
||||
m_lastFetched = DTM.NULL;
|
||||
|
||||
return m_lastFetched;
|
||||
}
|
||||
|
||||
/**
|
||||
* Detaches the walker from the set which it iterated over, releasing
|
||||
* any computational resources and placing the iterator in the INVALID
|
||||
* state.
|
||||
*/
|
||||
public void detach()
|
||||
{
|
||||
super.detach();
|
||||
m_exprObj.detach();
|
||||
m_exprObj = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is used to fixup variables from QNames to stack frame
|
||||
* indexes at stylesheet build time.
|
||||
* @param vars List of QNames that correspond to variables. This list
|
||||
* should be searched backwards for the first qualified name that
|
||||
* corresponds to the variable reference qname. The position of the
|
||||
* QName in the vector from the start of the vector will be its position
|
||||
* in the stack frame (but variables above the globalsTop value will need
|
||||
* to be offset to the current stack frame).
|
||||
*/
|
||||
public void fixupVariables(java.util.Vector vars, int globalsSize)
|
||||
{
|
||||
super.fixupVariables(vars, globalsSize);
|
||||
m_expr.fixupVariables(vars, globalsSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the inner contained expression of this filter.
|
||||
*/
|
||||
public Expression getInnerExpression()
|
||||
{
|
||||
return m_expr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the inner contained expression of this filter.
|
||||
*/
|
||||
public void setInnerExpression(Expression expr)
|
||||
{
|
||||
expr.exprSetParent(this);
|
||||
m_expr = expr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the analysis bits for this walker, as defined in the WalkerFactory.
|
||||
* @return One of WalkerFactory#BIT_DESCENDANT, etc.
|
||||
*/
|
||||
public int getAnalysisBits()
|
||||
{
|
||||
if (null != m_expr && m_expr instanceof PathComponent)
|
||||
{
|
||||
return ((PathComponent) m_expr).getAnalysisBits();
|
||||
}
|
||||
return WalkerFactory.BIT_FILTER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if all the nodes in the iteration well be returned in document
|
||||
* order.
|
||||
* Warning: This can only be called after setRoot has been called!
|
||||
*
|
||||
* @return true as a default.
|
||||
*/
|
||||
public boolean isDocOrdered()
|
||||
{
|
||||
return m_exprObj.isDocOrdered();
|
||||
}
|
||||
|
||||
class filterExprOwner implements ExpressionOwner
|
||||
{
|
||||
/**
|
||||
* @see ExpressionOwner#getExpression()
|
||||
*/
|
||||
public Expression getExpression()
|
||||
{
|
||||
return m_expr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ExpressionOwner#setExpression(Expression)
|
||||
*/
|
||||
public void setExpression(Expression exp)
|
||||
{
|
||||
exp.exprSetParent(FilterExprIterator.this);
|
||||
m_expr = exp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This will traverse the heararchy, calling the visitor for
|
||||
* each member. If the called visitor method returns
|
||||
* false, the subtree should not be called.
|
||||
*
|
||||
* @param visitor The visitor whose appropriate method will be called.
|
||||
*/
|
||||
public void callPredicateVisitors(XPathVisitor visitor)
|
||||
{
|
||||
m_expr.callVisitors(new filterExprOwner(), visitor);
|
||||
|
||||
super.callPredicateVisitors(visitor);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Expression#deepEquals(Expression)
|
||||
*/
|
||||
public boolean deepEquals(Expression expr)
|
||||
{
|
||||
if (!super.deepEquals(expr))
|
||||
return false;
|
||||
|
||||
FilterExprIterator fet = (FilterExprIterator) expr;
|
||||
if (!m_expr.deepEquals(fet.m_expr))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,315 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.axes;
|
||||
|
||||
import com.sun.org.apache.xml.internal.dtm.Axis;
|
||||
import com.sun.org.apache.xml.internal.dtm.DTM;
|
||||
import com.sun.org.apache.xml.internal.utils.PrefixResolver;
|
||||
import com.sun.org.apache.xpath.internal.Expression;
|
||||
import com.sun.org.apache.xpath.internal.ExpressionOwner;
|
||||
import com.sun.org.apache.xpath.internal.VariableStack;
|
||||
import com.sun.org.apache.xpath.internal.XPathContext;
|
||||
import com.sun.org.apache.xpath.internal.XPathVisitor;
|
||||
import com.sun.org.apache.xpath.internal.objects.XNodeSet;
|
||||
|
||||
/**
|
||||
* Class to use for one-step iteration that doesn't have a predicate, and
|
||||
* doesn't need to set the context.
|
||||
*/
|
||||
public class FilterExprIteratorSimple extends LocPathIterator
|
||||
{
|
||||
static final long serialVersionUID = -6978977187025375579L;
|
||||
/** The contained expression. Should be non-null.
|
||||
* @serial */
|
||||
private Expression m_expr;
|
||||
|
||||
/** The result of executing m_expr. Needs to be deep cloned on clone op. */
|
||||
transient private XNodeSet m_exprObj;
|
||||
|
||||
private boolean m_mustHardReset = false;
|
||||
private boolean m_canDetachNodeset = true;
|
||||
|
||||
/**
|
||||
* Create a FilterExprIteratorSimple object.
|
||||
*
|
||||
*/
|
||||
public FilterExprIteratorSimple()
|
||||
{
|
||||
super(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a FilterExprIteratorSimple object.
|
||||
*
|
||||
*/
|
||||
public FilterExprIteratorSimple(Expression expr)
|
||||
{
|
||||
super(null);
|
||||
m_expr = expr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the context values for this expression
|
||||
* after it is cloned.
|
||||
*
|
||||
* @param context The XPath runtime context for this
|
||||
* transformation.
|
||||
*/
|
||||
public void setRoot(int context, Object environment)
|
||||
{
|
||||
super.setRoot(context, environment);
|
||||
m_exprObj = executeFilterExpr(context, m_execContext, getPrefixResolver(),
|
||||
getIsTopLevel(), m_stackFrame, m_expr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the expression. Meant for reuse by other FilterExpr iterators
|
||||
* that are not derived from this object.
|
||||
*/
|
||||
public static XNodeSet executeFilterExpr(int context, XPathContext xctxt,
|
||||
PrefixResolver prefixResolver,
|
||||
boolean isTopLevel,
|
||||
int stackFrame,
|
||||
Expression expr )
|
||||
throws com.sun.org.apache.xml.internal.utils.WrappedRuntimeException
|
||||
{
|
||||
PrefixResolver savedResolver = xctxt.getNamespaceContext();
|
||||
XNodeSet result = null;
|
||||
|
||||
try
|
||||
{
|
||||
xctxt.pushCurrentNode(context);
|
||||
xctxt.setNamespaceContext(prefixResolver);
|
||||
|
||||
// The setRoot operation can take place with a reset operation,
|
||||
// and so we may not be in the context of LocPathIterator#nextNode,
|
||||
// so we have to set up the variable context, execute the expression,
|
||||
// and then restore the variable context.
|
||||
|
||||
if (isTopLevel)
|
||||
{
|
||||
// System.out.println("calling m_expr.execute(getXPathContext())");
|
||||
VariableStack vars = xctxt.getVarStack();
|
||||
|
||||
// These three statements need to be combined into one operation.
|
||||
int savedStart = vars.getStackFrame();
|
||||
vars.setStackFrame(stackFrame);
|
||||
|
||||
result = (com.sun.org.apache.xpath.internal.objects.XNodeSet) expr.execute(xctxt);
|
||||
result.setShouldCacheNodes(true);
|
||||
|
||||
// These two statements need to be combined into one operation.
|
||||
vars.setStackFrame(savedStart);
|
||||
}
|
||||
else
|
||||
result = (com.sun.org.apache.xpath.internal.objects.XNodeSet) expr.execute(xctxt);
|
||||
|
||||
}
|
||||
catch (javax.xml.transform.TransformerException se)
|
||||
{
|
||||
|
||||
// TODO: Fix...
|
||||
throw new com.sun.org.apache.xml.internal.utils.WrappedRuntimeException(se);
|
||||
}
|
||||
finally
|
||||
{
|
||||
xctxt.popCurrentNode();
|
||||
xctxt.setNamespaceContext(savedResolver);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the next node in the set and advances the position of the
|
||||
* iterator in the set. After a NodeIterator is created, the first call
|
||||
* to nextNode() returns the first node in the set.
|
||||
*
|
||||
* @return The next <code>Node</code> in the set being iterated over, or
|
||||
* <code>null</code> if there are no more members in that set.
|
||||
*/
|
||||
public int nextNode()
|
||||
{
|
||||
if(m_foundLast)
|
||||
return DTM.NULL;
|
||||
|
||||
int next;
|
||||
|
||||
if (null != m_exprObj)
|
||||
{
|
||||
m_lastFetched = next = m_exprObj.nextNode();
|
||||
}
|
||||
else
|
||||
m_lastFetched = next = DTM.NULL;
|
||||
|
||||
// m_lastFetched = next;
|
||||
if (DTM.NULL != next)
|
||||
{
|
||||
m_pos++;
|
||||
return next;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_foundLast = true;
|
||||
|
||||
return DTM.NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Detaches the walker from the set which it iterated over, releasing
|
||||
* any computational resources and placing the iterator in the INVALID
|
||||
* state.
|
||||
*/
|
||||
public void detach()
|
||||
{
|
||||
if(m_allowDetach)
|
||||
{
|
||||
super.detach();
|
||||
m_exprObj.detach();
|
||||
m_exprObj = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is used to fixup variables from QNames to stack frame
|
||||
* indexes at stylesheet build time.
|
||||
* @param vars List of QNames that correspond to variables. This list
|
||||
* should be searched backwards for the first qualified name that
|
||||
* corresponds to the variable reference qname. The position of the
|
||||
* QName in the vector from the start of the vector will be its position
|
||||
* in the stack frame (but variables above the globalsTop value will need
|
||||
* to be offset to the current stack frame).
|
||||
*/
|
||||
public void fixupVariables(java.util.Vector vars, int globalsSize)
|
||||
{
|
||||
super.fixupVariables(vars, globalsSize);
|
||||
m_expr.fixupVariables(vars, globalsSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the inner contained expression of this filter.
|
||||
*/
|
||||
public Expression getInnerExpression()
|
||||
{
|
||||
return m_expr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the inner contained expression of this filter.
|
||||
*/
|
||||
public void setInnerExpression(Expression expr)
|
||||
{
|
||||
expr.exprSetParent(this);
|
||||
m_expr = expr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the analysis bits for this walker, as defined in the WalkerFactory.
|
||||
* @return One of WalkerFactory#BIT_DESCENDANT, etc.
|
||||
*/
|
||||
public int getAnalysisBits()
|
||||
{
|
||||
if (null != m_expr && m_expr instanceof PathComponent)
|
||||
{
|
||||
return ((PathComponent) m_expr).getAnalysisBits();
|
||||
}
|
||||
return WalkerFactory.BIT_FILTER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if all the nodes in the iteration well be returned in document
|
||||
* order.
|
||||
* Warning: This can only be called after setRoot has been called!
|
||||
*
|
||||
* @return true as a default.
|
||||
*/
|
||||
public boolean isDocOrdered()
|
||||
{
|
||||
return m_exprObj.isDocOrdered();
|
||||
}
|
||||
|
||||
class filterExprOwner implements ExpressionOwner
|
||||
{
|
||||
/**
|
||||
* @see ExpressionOwner#getExpression()
|
||||
*/
|
||||
public Expression getExpression()
|
||||
{
|
||||
return m_expr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ExpressionOwner#setExpression(Expression)
|
||||
*/
|
||||
public void setExpression(Expression exp)
|
||||
{
|
||||
exp.exprSetParent(FilterExprIteratorSimple.this);
|
||||
m_expr = exp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This will traverse the heararchy, calling the visitor for
|
||||
* each member. If the called visitor method returns
|
||||
* false, the subtree should not be called.
|
||||
*
|
||||
* @param visitor The visitor whose appropriate method will be called.
|
||||
*/
|
||||
public void callPredicateVisitors(XPathVisitor visitor)
|
||||
{
|
||||
m_expr.callVisitors(new filterExprOwner(), visitor);
|
||||
|
||||
super.callPredicateVisitors(visitor);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Expression#deepEquals(Expression)
|
||||
*/
|
||||
public boolean deepEquals(Expression expr)
|
||||
{
|
||||
if (!super.deepEquals(expr))
|
||||
return false;
|
||||
|
||||
FilterExprIteratorSimple fet = (FilterExprIteratorSimple) expr;
|
||||
if (!m_expr.deepEquals(fet.m_expr))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the axis being iterated, if it is known.
|
||||
*
|
||||
* @return Axis.CHILD, etc., or -1 if the axis is not known or is of multiple
|
||||
* types.
|
||||
*/
|
||||
public int getAxis()
|
||||
{
|
||||
if(null != m_exprObj)
|
||||
return m_exprObj.getAxis();
|
||||
else
|
||||
return Axis.FILTEREDLIST;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,350 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.axes;
|
||||
|
||||
import com.sun.org.apache.xml.internal.dtm.Axis;
|
||||
import com.sun.org.apache.xml.internal.dtm.DTM;
|
||||
import com.sun.org.apache.xml.internal.dtm.DTMIterator;
|
||||
import com.sun.org.apache.xpath.internal.Expression;
|
||||
import com.sun.org.apache.xpath.internal.ExpressionOwner;
|
||||
import com.sun.org.apache.xpath.internal.XPathContext;
|
||||
import com.sun.org.apache.xpath.internal.XPathVisitor;
|
||||
import com.sun.org.apache.xpath.internal.compiler.Compiler;
|
||||
import com.sun.org.apache.xpath.internal.compiler.OpCodes;
|
||||
import com.sun.org.apache.xpath.internal.objects.XNodeSet;
|
||||
|
||||
/**
|
||||
* Walker for the OP_VARIABLE, or OP_EXTFUNCTION, or OP_FUNCTION, or OP_GROUP,
|
||||
* op codes.
|
||||
* @see <a href="http://www.w3.org/TR/xpath#NT-FilterExpr">XPath FilterExpr descriptions</a>
|
||||
*/
|
||||
public class FilterExprWalker extends AxesWalker
|
||||
{
|
||||
static final long serialVersionUID = 5457182471424488375L;
|
||||
|
||||
/**
|
||||
* Construct a FilterExprWalker using a LocPathIterator.
|
||||
*
|
||||
* @param locPathIterator non-null reference to the parent iterator.
|
||||
*/
|
||||
public FilterExprWalker(WalkingIterator locPathIterator)
|
||||
{
|
||||
super(locPathIterator, Axis.FILTEREDLIST);
|
||||
}
|
||||
|
||||
/**
|
||||
* Init a FilterExprWalker.
|
||||
*
|
||||
* @param compiler non-null reference to the Compiler that is constructing.
|
||||
* @param opPos positive opcode position for this step.
|
||||
* @param stepType The type of step.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
public void init(Compiler compiler, int opPos, int stepType)
|
||||
throws javax.xml.transform.TransformerException
|
||||
{
|
||||
|
||||
super.init(compiler, opPos, stepType);
|
||||
|
||||
// Smooth over an anomily in the opcode map...
|
||||
switch (stepType)
|
||||
{
|
||||
case OpCodes.OP_FUNCTION :
|
||||
case OpCodes.OP_EXTFUNCTION :
|
||||
m_mustHardReset = true;
|
||||
case OpCodes.OP_GROUP :
|
||||
case OpCodes.OP_VARIABLE :
|
||||
m_expr = compiler.compileExpression(opPos);
|
||||
m_expr.exprSetParent(this);
|
||||
//if((OpCodes.OP_FUNCTION == stepType) && (m_expr instanceof com.sun.org.apache.xalan.internal.templates.FuncKey))
|
||||
if(m_expr instanceof com.sun.org.apache.xpath.internal.operations.Variable)
|
||||
{
|
||||
// hack/temp workaround
|
||||
m_canDetachNodeset = false;
|
||||
}
|
||||
break;
|
||||
default :
|
||||
m_expr = compiler.compileExpression(opPos + 2);
|
||||
m_expr.exprSetParent(this);
|
||||
}
|
||||
// if(m_expr instanceof WalkingIterator)
|
||||
// {
|
||||
// WalkingIterator wi = (WalkingIterator)m_expr;
|
||||
// if(wi.getFirstWalker() instanceof FilterExprWalker)
|
||||
// {
|
||||
// FilterExprWalker fw = (FilterExprWalker)wi.getFirstWalker();
|
||||
// if(null == fw.getNextWalker())
|
||||
// {
|
||||
// m_expr = fw.m_expr;
|
||||
// m_expr.exprSetParent(this);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* Detaches the walker from the set which it iterated over, releasing
|
||||
* any computational resources and placing the iterator in the INVALID
|
||||
* state.
|
||||
*/
|
||||
public void detach()
|
||||
{
|
||||
super.detach();
|
||||
if (m_canDetachNodeset)
|
||||
{
|
||||
m_exprObj.detach();
|
||||
}
|
||||
m_exprObj = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the root node of the TreeWalker.
|
||||
*
|
||||
* @param root non-null reference to the root, or starting point of
|
||||
* the query.
|
||||
*/
|
||||
public void setRoot(int root)
|
||||
{
|
||||
|
||||
super.setRoot(root);
|
||||
|
||||
m_exprObj = FilterExprIteratorSimple.executeFilterExpr(root,
|
||||
m_lpi.getXPathContext(), m_lpi.getPrefixResolver(),
|
||||
m_lpi.getIsTopLevel(), m_lpi.m_stackFrame, m_expr);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a cloned FilterExprWalker.
|
||||
*
|
||||
* @return A new FilterExprWalker that can be used without mutating this one.
|
||||
*
|
||||
* @throws CloneNotSupportedException
|
||||
*/
|
||||
public Object clone() throws CloneNotSupportedException
|
||||
{
|
||||
|
||||
FilterExprWalker clone = (FilterExprWalker) super.clone();
|
||||
|
||||
// clone.m_expr = (Expression)((Expression)m_expr).clone();
|
||||
if (null != m_exprObj)
|
||||
clone.m_exprObj = (XNodeSet) m_exprObj.clone();
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method needs to override AxesWalker.acceptNode because FilterExprWalkers
|
||||
* don't need to, and shouldn't, do a node test.
|
||||
* @param n The node to check to see if it passes the filter or not.
|
||||
* @return a constant to determine whether the node is accepted,
|
||||
* rejected, or skipped, as defined above .
|
||||
*/
|
||||
public short acceptNode(int n)
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
if (getPredicateCount() > 0)
|
||||
{
|
||||
countProximityPosition(0);
|
||||
|
||||
if (!executePredicates(n, m_lpi.getXPathContext()))
|
||||
return DTMIterator.FILTER_SKIP;
|
||||
}
|
||||
|
||||
return DTMIterator.FILTER_ACCEPT;
|
||||
}
|
||||
catch (javax.xml.transform.TransformerException se)
|
||||
{
|
||||
throw new RuntimeException(se.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the <code>TreeWalker</code> to the next visible node in document
|
||||
* order relative to the current node, and returns the new node. If the
|
||||
* current node has no next node, or if the search for nextNode attempts
|
||||
* to step upward from the TreeWalker's root node, returns
|
||||
* <code>null</code> , and retains the current node.
|
||||
* @return The new node, or <code>null</code> if the current node has no
|
||||
* next node in the TreeWalker's logical view.
|
||||
*/
|
||||
public int getNextNode()
|
||||
{
|
||||
|
||||
if (null != m_exprObj)
|
||||
{
|
||||
int next = m_exprObj.nextNode();
|
||||
return next;
|
||||
}
|
||||
else
|
||||
return DTM.NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the index of the last node that can be itterated to.
|
||||
*
|
||||
*
|
||||
* @param xctxt XPath runtime context.
|
||||
*
|
||||
* @return the index of the last node that can be itterated to.
|
||||
*/
|
||||
public int getLastPos(XPathContext xctxt)
|
||||
{
|
||||
return m_exprObj.getLength();
|
||||
}
|
||||
|
||||
/** The contained expression. Should be non-null.
|
||||
* @serial */
|
||||
private Expression m_expr;
|
||||
|
||||
/** The result of executing m_expr. Needs to be deep cloned on clone op. */
|
||||
transient private XNodeSet m_exprObj;
|
||||
|
||||
private boolean m_mustHardReset = false;
|
||||
private boolean m_canDetachNodeset = true;
|
||||
|
||||
/**
|
||||
* This function is used to fixup variables from QNames to stack frame
|
||||
* indexes at stylesheet build time.
|
||||
* @param vars List of QNames that correspond to variables. This list
|
||||
* should be searched backwards for the first qualified name that
|
||||
* corresponds to the variable reference qname. The position of the
|
||||
* QName in the vector from the start of the vector will be its position
|
||||
* in the stack frame (but variables above the globalsTop value will need
|
||||
* to be offset to the current stack frame).
|
||||
*/
|
||||
public void fixupVariables(java.util.Vector vars, int globalsSize)
|
||||
{
|
||||
super.fixupVariables(vars, globalsSize);
|
||||
m_expr.fixupVariables(vars, globalsSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the inner contained expression of this filter.
|
||||
*/
|
||||
public Expression getInnerExpression()
|
||||
{
|
||||
return m_expr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the inner contained expression of this filter.
|
||||
*/
|
||||
public void setInnerExpression(Expression expr)
|
||||
{
|
||||
expr.exprSetParent(this);
|
||||
m_expr = expr;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the analysis bits for this walker, as defined in the WalkerFactory.
|
||||
* @return One of WalkerFactory#BIT_DESCENDANT, etc.
|
||||
*/
|
||||
public int getAnalysisBits()
|
||||
{
|
||||
if (null != m_expr && m_expr instanceof PathComponent)
|
||||
{
|
||||
return ((PathComponent) m_expr).getAnalysisBits();
|
||||
}
|
||||
return WalkerFactory.BIT_FILTER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if all the nodes in the iteration well be returned in document
|
||||
* order.
|
||||
* Warning: This can only be called after setRoot has been called!
|
||||
*
|
||||
* @return true as a default.
|
||||
*/
|
||||
public boolean isDocOrdered()
|
||||
{
|
||||
return m_exprObj.isDocOrdered();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the axis being iterated, if it is known.
|
||||
*
|
||||
* @return Axis.CHILD, etc., or -1 if the axis is not known or is of multiple
|
||||
* types.
|
||||
*/
|
||||
public int getAxis()
|
||||
{
|
||||
return m_exprObj.getAxis();
|
||||
}
|
||||
|
||||
class filterExprOwner implements ExpressionOwner
|
||||
{
|
||||
/**
|
||||
* @see ExpressionOwner#getExpression()
|
||||
*/
|
||||
public Expression getExpression()
|
||||
{
|
||||
return m_expr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ExpressionOwner#setExpression(Expression)
|
||||
*/
|
||||
public void setExpression(Expression exp)
|
||||
{
|
||||
exp.exprSetParent(FilterExprWalker.this);
|
||||
m_expr = exp;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This will traverse the heararchy, calling the visitor for
|
||||
* each member. If the called visitor method returns
|
||||
* false, the subtree should not be called.
|
||||
*
|
||||
* @param visitor The visitor whose appropriate method will be called.
|
||||
*/
|
||||
public void callPredicateVisitors(XPathVisitor visitor)
|
||||
{
|
||||
m_expr.callVisitors(new filterExprOwner(), visitor);
|
||||
|
||||
super.callPredicateVisitors(visitor);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see Expression#deepEquals(Expression)
|
||||
*/
|
||||
public boolean deepEquals(Expression expr)
|
||||
{
|
||||
if (!super.deepEquals(expr))
|
||||
return false;
|
||||
|
||||
FilterExprWalker walker = (FilterExprWalker)expr;
|
||||
if(!m_expr.deepEquals(walker.m_expr))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.axes;
|
||||
|
||||
import com.sun.org.apache.xpath.internal.Expression;
|
||||
import com.sun.org.apache.xpath.internal.ExpressionOwner;
|
||||
import com.sun.org.apache.xpath.internal.XPathVisitor;
|
||||
import com.sun.org.apache.xpath.internal.functions.FuncLast;
|
||||
import com.sun.org.apache.xpath.internal.functions.FuncPosition;
|
||||
import com.sun.org.apache.xpath.internal.functions.Function;
|
||||
import com.sun.org.apache.xpath.internal.objects.XNumber;
|
||||
import com.sun.org.apache.xpath.internal.operations.Div;
|
||||
import com.sun.org.apache.xpath.internal.operations.Minus;
|
||||
import com.sun.org.apache.xpath.internal.operations.Mod;
|
||||
import com.sun.org.apache.xpath.internal.operations.Mult;
|
||||
import com.sun.org.apache.xpath.internal.operations.Plus;
|
||||
import com.sun.org.apache.xpath.internal.operations.Quo;
|
||||
import com.sun.org.apache.xpath.internal.operations.Variable;
|
||||
|
||||
public class HasPositionalPredChecker extends XPathVisitor
|
||||
{
|
||||
private boolean m_hasPositionalPred = false;
|
||||
private int m_predDepth = 0;
|
||||
|
||||
/**
|
||||
* Process the LocPathIterator to see if it contains variables
|
||||
* or functions that may make it context dependent.
|
||||
* @param path LocPathIterator that is assumed to be absolute, but needs checking.
|
||||
* @return true if the path is confirmed to be absolute, false if it
|
||||
* may contain context dependencies.
|
||||
*/
|
||||
public static boolean check(LocPathIterator path)
|
||||
{
|
||||
HasPositionalPredChecker hppc = new HasPositionalPredChecker();
|
||||
path.callVisitors(null, hppc);
|
||||
return hppc.m_hasPositionalPred;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visit a function.
|
||||
* @param owner The owner of the expression, to which the expression can
|
||||
* be reset if rewriting takes place.
|
||||
* @param func The function reference object.
|
||||
* @return true if the sub expressions should be traversed.
|
||||
*/
|
||||
public boolean visitFunction(ExpressionOwner owner, Function func)
|
||||
{
|
||||
if((func instanceof FuncPosition) ||
|
||||
(func instanceof FuncLast))
|
||||
m_hasPositionalPred = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Visit a variable reference.
|
||||
// * @param owner The owner of the expression, to which the expression can
|
||||
// * be reset if rewriting takes place.
|
||||
// * @param var The variable reference object.
|
||||
// * @return true if the sub expressions should be traversed.
|
||||
// */
|
||||
// public boolean visitVariableRef(ExpressionOwner owner, Variable var)
|
||||
// {
|
||||
// m_hasPositionalPred = true;
|
||||
// return true;
|
||||
// }
|
||||
|
||||
/**
|
||||
* Visit a predicate within a location path. Note that there isn't a
|
||||
* proper unique component for predicates, and that the expression will
|
||||
* be called also for whatever type Expression is.
|
||||
*
|
||||
* @param owner The owner of the expression, to which the expression can
|
||||
* be reset if rewriting takes place.
|
||||
* @param pred The predicate object.
|
||||
* @return true if the sub expressions should be traversed.
|
||||
*/
|
||||
public boolean visitPredicate(ExpressionOwner owner, Expression pred)
|
||||
{
|
||||
m_predDepth++;
|
||||
|
||||
if(m_predDepth == 1)
|
||||
{
|
||||
if((pred instanceof Variable) ||
|
||||
(pred instanceof XNumber) ||
|
||||
(pred instanceof Div) ||
|
||||
(pred instanceof Plus) ||
|
||||
(pred instanceof Minus) ||
|
||||
(pred instanceof Mod) ||
|
||||
(pred instanceof Quo) ||
|
||||
(pred instanceof Mult) ||
|
||||
(pred instanceof com.sun.org.apache.xpath.internal.operations.Number) ||
|
||||
(pred instanceof Function))
|
||||
m_hasPositionalPred = true;
|
||||
else
|
||||
pred.callVisitors(owner, this);
|
||||
}
|
||||
|
||||
m_predDepth--;
|
||||
|
||||
// Don't go have the caller go any further down the subtree.
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.axes;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import com.sun.org.apache.xml.internal.dtm.DTMIterator;
|
||||
import com.sun.org.apache.xml.internal.utils.WrappedRuntimeException;
|
||||
|
||||
/**
|
||||
* Pool of object of a given type to pick from to help memory usage
|
||||
* @xsl.usage internal
|
||||
*/
|
||||
public final class IteratorPool implements java.io.Serializable
|
||||
{
|
||||
static final long serialVersionUID = -460927331149566998L;
|
||||
|
||||
/**
|
||||
* Type of objects in this pool.
|
||||
*/
|
||||
private final DTMIterator m_orig;
|
||||
|
||||
/**
|
||||
* Stack of given objects this points to.
|
||||
*/
|
||||
private final ArrayList m_freeStack;
|
||||
|
||||
/**
|
||||
* Constructor IteratorPool
|
||||
*
|
||||
* @param original The original iterator from which all others will be cloned.
|
||||
*/
|
||||
public IteratorPool(DTMIterator original)
|
||||
{
|
||||
m_orig = original;
|
||||
m_freeStack = new ArrayList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an instance of the given object in this pool
|
||||
*
|
||||
* @return An instance of the given object
|
||||
*/
|
||||
public synchronized DTMIterator getInstanceOrThrow()
|
||||
throws CloneNotSupportedException
|
||||
{
|
||||
// Check if the pool is empty.
|
||||
if (m_freeStack.isEmpty())
|
||||
{
|
||||
|
||||
// Create a new object if so.
|
||||
return (DTMIterator)m_orig.clone();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Remove object from end of free pool.
|
||||
DTMIterator result = (DTMIterator)m_freeStack.remove(m_freeStack.size() - 1);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an instance of the given object in this pool
|
||||
*
|
||||
* @return An instance of the given object
|
||||
*/
|
||||
public synchronized DTMIterator getInstance()
|
||||
{
|
||||
// Check if the pool is empty.
|
||||
if (m_freeStack.isEmpty())
|
||||
{
|
||||
|
||||
// Create a new object if so.
|
||||
try
|
||||
{
|
||||
return (DTMIterator)m_orig.clone();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new WrappedRuntimeException(ex);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Remove object from end of free pool.
|
||||
DTMIterator result = (DTMIterator)m_freeStack.remove(m_freeStack.size() - 1);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an instance of the given object to the pool
|
||||
*
|
||||
*
|
||||
* @param obj Object to add.
|
||||
*/
|
||||
public synchronized void freeInstance(DTMIterator obj)
|
||||
{
|
||||
m_freeStack.add(obj);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,332 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.axes;
|
||||
|
||||
import com.sun.org.apache.xml.internal.dtm.Axis;
|
||||
import com.sun.org.apache.xml.internal.dtm.DTM;
|
||||
import com.sun.org.apache.xml.internal.dtm.DTMAxisTraverser;
|
||||
import com.sun.org.apache.xml.internal.dtm.DTMIterator;
|
||||
import com.sun.org.apache.xpath.internal.XPathContext;
|
||||
import com.sun.org.apache.xpath.internal.compiler.Compiler;
|
||||
import com.sun.org.apache.xpath.internal.compiler.OpMap;
|
||||
import com.sun.org.apache.xpath.internal.objects.XObject;
|
||||
import com.sun.org.apache.xpath.internal.patterns.NodeTest;
|
||||
import com.sun.org.apache.xpath.internal.patterns.StepPattern;
|
||||
|
||||
/**
|
||||
* This class treats a
|
||||
* <a href="http://www.w3.org/TR/xpath#location-paths">LocationPath</a> as a
|
||||
* filtered iteration over the tree, evaluating each node in a super axis
|
||||
* traversal against the LocationPath interpreted as a match pattern. This
|
||||
* class is useful to find nodes in document order that are complex paths
|
||||
* whose steps probably criss-cross each other.
|
||||
*/
|
||||
public class MatchPatternIterator extends LocPathIterator
|
||||
{
|
||||
static final long serialVersionUID = -5201153767396296474L;
|
||||
|
||||
/** This is the select pattern, translated into a match pattern. */
|
||||
protected StepPattern m_pattern;
|
||||
|
||||
/** The traversal axis from where the nodes will be filtered. */
|
||||
protected int m_superAxis = -1;
|
||||
|
||||
/** The DTM inner traversal class, that corresponds to the super axis. */
|
||||
protected DTMAxisTraverser m_traverser;
|
||||
|
||||
/** DEBUG flag for diagnostic dumps. */
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
// protected int m_nsElemBase = DTM.NULL;
|
||||
|
||||
/**
|
||||
* Create a LocPathIterator object, including creation
|
||||
* of step walkers from the opcode list, and call back
|
||||
* into the Compiler to create predicate expressions.
|
||||
*
|
||||
* @param compiler The Compiler which is creating
|
||||
* this expression.
|
||||
* @param opPos The position of this iterator in the
|
||||
* opcode list from the compiler.
|
||||
* @param analysis Analysis bits that give general information about the
|
||||
* LocationPath.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
MatchPatternIterator(Compiler compiler, int opPos, int analysis)
|
||||
throws javax.xml.transform.TransformerException
|
||||
{
|
||||
|
||||
super(compiler, opPos, analysis, false);
|
||||
|
||||
int firstStepPos = OpMap.getFirstChildPos(opPos);
|
||||
|
||||
m_pattern = WalkerFactory.loadSteps(this, compiler, firstStepPos, 0);
|
||||
|
||||
boolean fromRoot = false;
|
||||
boolean walkBack = false;
|
||||
boolean walkDescendants = false;
|
||||
boolean walkAttributes = false;
|
||||
|
||||
if (0 != (analysis & (WalkerFactory.BIT_ROOT |
|
||||
WalkerFactory.BIT_ANY_DESCENDANT_FROM_ROOT)))
|
||||
fromRoot = true;
|
||||
|
||||
if (0 != (analysis
|
||||
& (WalkerFactory.BIT_ANCESTOR
|
||||
| WalkerFactory.BIT_ANCESTOR_OR_SELF
|
||||
| WalkerFactory.BIT_PRECEDING
|
||||
| WalkerFactory.BIT_PRECEDING_SIBLING
|
||||
| WalkerFactory.BIT_FOLLOWING
|
||||
| WalkerFactory.BIT_FOLLOWING_SIBLING
|
||||
| WalkerFactory.BIT_PARENT | WalkerFactory.BIT_FILTER)))
|
||||
walkBack = true;
|
||||
|
||||
if (0 != (analysis
|
||||
& (WalkerFactory.BIT_DESCENDANT_OR_SELF
|
||||
| WalkerFactory.BIT_DESCENDANT
|
||||
| WalkerFactory.BIT_CHILD)))
|
||||
walkDescendants = true;
|
||||
|
||||
if (0 != (analysis
|
||||
& (WalkerFactory.BIT_ATTRIBUTE | WalkerFactory.BIT_NAMESPACE)))
|
||||
walkAttributes = true;
|
||||
|
||||
if(false || DEBUG)
|
||||
{
|
||||
System.out.print("analysis: "+Integer.toBinaryString(analysis));
|
||||
System.out.println(", "+WalkerFactory.getAnalysisString(analysis));
|
||||
}
|
||||
|
||||
if(fromRoot || walkBack)
|
||||
{
|
||||
if(walkAttributes)
|
||||
{
|
||||
m_superAxis = Axis.ALL;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_superAxis = Axis.DESCENDANTSFROMROOT;
|
||||
}
|
||||
}
|
||||
else if(walkDescendants)
|
||||
{
|
||||
if(walkAttributes)
|
||||
{
|
||||
m_superAxis = Axis.ALLFROMNODE;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_superAxis = Axis.DESCENDANTORSELF;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_superAxis = Axis.ALL;
|
||||
}
|
||||
if(false || DEBUG)
|
||||
{
|
||||
System.out.println("axis: "+Axis.getNames(m_superAxis));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize the context values for this expression
|
||||
* after it is cloned.
|
||||
*
|
||||
* @param context The XPath runtime context for this
|
||||
* transformation.
|
||||
*/
|
||||
public void setRoot(int context, Object environment)
|
||||
{
|
||||
super.setRoot(context, environment);
|
||||
m_traverser = m_cdtm.getAxisTraverser(m_superAxis);
|
||||
}
|
||||
|
||||
/**
|
||||
* Detaches the iterator from the set which it iterated over, releasing
|
||||
* any computational resources and placing the iterator in the INVALID
|
||||
* state. After<code>detach</code> has been invoked, calls to
|
||||
* <code>nextNode</code> or<code>previousNode</code> will raise the
|
||||
* exception INVALID_STATE_ERR.
|
||||
*/
|
||||
public void detach()
|
||||
{
|
||||
if(m_allowDetach)
|
||||
{
|
||||
m_traverser = null;
|
||||
|
||||
// Always call the superclass detach last!
|
||||
super.detach();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next node via getNextXXX. Bottlenecked for derived class override.
|
||||
* @return The next node on the axis, or DTM.NULL.
|
||||
*/
|
||||
protected int getNextNode()
|
||||
{
|
||||
m_lastFetched = (DTM.NULL == m_lastFetched)
|
||||
? m_traverser.first(m_context)
|
||||
: m_traverser.next(m_context, m_lastFetched);
|
||||
return m_lastFetched;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the next node in the set and advances the position of the
|
||||
* iterator in the set. After a NodeIterator is created, the first call
|
||||
* to nextNode() returns the first node in the set.
|
||||
* @return The next <code>Node</code> in the set being iterated over, or
|
||||
* <code>null</code> if there are no more members in that set.
|
||||
*/
|
||||
public int nextNode()
|
||||
{
|
||||
if(m_foundLast)
|
||||
return DTM.NULL;
|
||||
|
||||
int next;
|
||||
|
||||
com.sun.org.apache.xpath.internal.VariableStack vars;
|
||||
int savedStart;
|
||||
if (-1 != m_stackFrame)
|
||||
{
|
||||
vars = m_execContext.getVarStack();
|
||||
|
||||
// These three statements need to be combined into one operation.
|
||||
savedStart = vars.getStackFrame();
|
||||
|
||||
vars.setStackFrame(m_stackFrame);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Yuck. Just to shut up the compiler!
|
||||
vars = null;
|
||||
savedStart = 0;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if(DEBUG)
|
||||
System.out.println("m_pattern"+m_pattern.toString());
|
||||
|
||||
do
|
||||
{
|
||||
next = getNextNode();
|
||||
|
||||
if (DTM.NULL != next)
|
||||
{
|
||||
if(DTMIterator.FILTER_ACCEPT == acceptNode(next, m_execContext))
|
||||
break;
|
||||
else
|
||||
continue;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
while (next != DTM.NULL);
|
||||
|
||||
if (DTM.NULL != next)
|
||||
{
|
||||
if(DEBUG)
|
||||
{
|
||||
System.out.println("next: "+next);
|
||||
System.out.println("name: "+m_cdtm.getNodeName(next));
|
||||
}
|
||||
incrementCurrentPos();
|
||||
|
||||
return next;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_foundLast = true;
|
||||
|
||||
return DTM.NULL;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (-1 != m_stackFrame)
|
||||
{
|
||||
// These two statements need to be combined into one operation.
|
||||
vars.setStackFrame(savedStart);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether a specified node is visible in the logical view of a
|
||||
* TreeWalker or NodeIterator. This function will be called by the
|
||||
* implementation of TreeWalker and NodeIterator; it is not intended to
|
||||
* be called directly from user code.
|
||||
* @param n The node to check to see if it passes the filter or not.
|
||||
* @return a constant to determine whether the node is accepted,
|
||||
* rejected, or skipped, as defined above .
|
||||
*/
|
||||
public short acceptNode(int n, XPathContext xctxt)
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
xctxt.pushCurrentNode(n);
|
||||
xctxt.pushIteratorRoot(m_context);
|
||||
if(DEBUG)
|
||||
{
|
||||
System.out.println("traverser: "+m_traverser);
|
||||
System.out.print("node: "+n);
|
||||
System.out.println(", "+m_cdtm.getNodeName(n));
|
||||
// if(m_cdtm.getNodeName(n).equals("near-east"))
|
||||
System.out.println("pattern: "+m_pattern.toString());
|
||||
m_pattern.debugWhatToShow(m_pattern.getWhatToShow());
|
||||
}
|
||||
|
||||
XObject score = m_pattern.execute(xctxt);
|
||||
|
||||
if(DEBUG)
|
||||
{
|
||||
// System.out.println("analysis: "+Integer.toBinaryString(m_analysis));
|
||||
System.out.println("score: "+score);
|
||||
System.out.println("skip: "+(score == NodeTest.SCORE_NONE));
|
||||
}
|
||||
|
||||
// System.out.println("\n::acceptNode - score: "+score.num()+"::");
|
||||
return (score == NodeTest.SCORE_NONE) ? DTMIterator.FILTER_SKIP
|
||||
: DTMIterator.FILTER_ACCEPT;
|
||||
}
|
||||
catch (javax.xml.transform.TransformerException se)
|
||||
{
|
||||
|
||||
// TODO: Fix this.
|
||||
throw new RuntimeException(se.getMessage());
|
||||
}
|
||||
finally
|
||||
{
|
||||
xctxt.popCurrentNode();
|
||||
xctxt.popIteratorRoot();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,960 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.axes;
|
||||
|
||||
import java.util.Vector;
|
||||
|
||||
import com.sun.org.apache.xml.internal.dtm.DTM;
|
||||
import com.sun.org.apache.xml.internal.dtm.DTMFilter;
|
||||
import com.sun.org.apache.xml.internal.dtm.DTMIterator;
|
||||
import com.sun.org.apache.xml.internal.dtm.DTMManager;
|
||||
import com.sun.org.apache.xml.internal.utils.NodeVector;
|
||||
import com.sun.org.apache.xpath.internal.NodeSetDTM;
|
||||
import com.sun.org.apache.xpath.internal.XPathContext;
|
||||
import com.sun.org.apache.xpath.internal.objects.XObject;
|
||||
|
||||
/**
|
||||
* This class is the dynamic wrapper for a Xalan DTMIterator instance, and
|
||||
* provides random access capabilities.
|
||||
*/
|
||||
public class NodeSequence extends XObject
|
||||
implements DTMIterator, Cloneable, PathComponent
|
||||
{
|
||||
static final long serialVersionUID = 3866261934726581044L;
|
||||
/** The index of the last node in the iteration. */
|
||||
protected int m_last = -1;
|
||||
|
||||
/**
|
||||
* The index of the next node to be fetched. Useful if this
|
||||
* is a cached iterator, and is being used as random access
|
||||
* NodeList.
|
||||
*/
|
||||
protected int m_next = 0;
|
||||
|
||||
/**
|
||||
* A cache of a list of nodes obtained from the iterator so far.
|
||||
* This list is appended to until the iterator is exhausted and
|
||||
* the cache is complete.
|
||||
* <p>
|
||||
* Multiple NodeSequence objects may share the same cache.
|
||||
*/
|
||||
private IteratorCache m_cache;
|
||||
|
||||
/**
|
||||
* If this iterator needs to cache nodes that are fetched, they
|
||||
* are stored in the Vector in the generic object.
|
||||
*/
|
||||
protected NodeVector getVector() {
|
||||
NodeVector nv = (m_cache != null) ? m_cache.getVector() : null;
|
||||
return nv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the cache (if any) of nodes obtained from
|
||||
* the iterator so far. Note that the cache keeps
|
||||
* growing until the iterator is walked to exhaustion,
|
||||
* at which point the cache is "complete".
|
||||
*/
|
||||
private IteratorCache getCache() {
|
||||
return m_cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the vector where nodes will be cached.
|
||||
*/
|
||||
protected void SetVector(NodeVector v)
|
||||
{
|
||||
setObject(v);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* If the iterator needs to cache nodes as they are fetched,
|
||||
* then this method returns true.
|
||||
*/
|
||||
public boolean hasCache()
|
||||
{
|
||||
final NodeVector nv = getVector();
|
||||
return (nv != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* If this NodeSequence has a cache, and that cache is
|
||||
* fully populated then this method returns true, otherwise
|
||||
* if there is no cache or it is not complete it returns false.
|
||||
*/
|
||||
private boolean cacheComplete() {
|
||||
final boolean complete;
|
||||
if (m_cache != null) {
|
||||
complete = m_cache.isComplete();
|
||||
} else {
|
||||
complete = false;
|
||||
}
|
||||
return complete;
|
||||
}
|
||||
|
||||
/**
|
||||
* If this NodeSequence has a cache, mark that it is complete.
|
||||
* This method should be called after the iterator is exhausted.
|
||||
*/
|
||||
private void markCacheComplete() {
|
||||
NodeVector nv = getVector();
|
||||
if (nv != null) {
|
||||
m_cache.setCacheComplete(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The functional iterator that fetches nodes.
|
||||
*/
|
||||
protected DTMIterator m_iter;
|
||||
|
||||
/**
|
||||
* Set the functional iterator that fetches nodes.
|
||||
* @param iter The iterator that is to be contained.
|
||||
*/
|
||||
public final void setIter(DTMIterator iter)
|
||||
{
|
||||
m_iter = iter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the functional iterator that fetches nodes.
|
||||
* @return The contained iterator.
|
||||
*/
|
||||
public final DTMIterator getContainedIter()
|
||||
{
|
||||
return m_iter;
|
||||
}
|
||||
|
||||
/**
|
||||
* The DTMManager to use if we're using a NodeVector only.
|
||||
* We may well want to do away with this, and store it in the NodeVector.
|
||||
*/
|
||||
protected DTMManager m_dtmMgr;
|
||||
|
||||
// ==== Constructors ====
|
||||
|
||||
/**
|
||||
* Create a new NodeSequence from a (already cloned) iterator.
|
||||
*
|
||||
* @param iter Cloned (not static) DTMIterator.
|
||||
* @param context The initial context node.
|
||||
* @param xctxt The execution context.
|
||||
* @param shouldCacheNodes True if this sequence can random access.
|
||||
*/
|
||||
private NodeSequence(DTMIterator iter, int context, XPathContext xctxt, boolean shouldCacheNodes)
|
||||
{
|
||||
setIter(iter);
|
||||
setRoot(context, xctxt);
|
||||
setShouldCacheNodes(shouldCacheNodes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new NodeSequence from a (already cloned) iterator.
|
||||
*
|
||||
* @param nodeVector
|
||||
*/
|
||||
public NodeSequence(Object nodeVector)
|
||||
{
|
||||
super(nodeVector);
|
||||
if (nodeVector instanceof NodeVector) {
|
||||
SetVector((NodeVector) nodeVector);
|
||||
}
|
||||
if(null != nodeVector)
|
||||
{
|
||||
assertion(nodeVector instanceof NodeVector,
|
||||
"Must have a NodeVector as the object for NodeSequence!");
|
||||
if(nodeVector instanceof DTMIterator)
|
||||
{
|
||||
setIter((DTMIterator)nodeVector);
|
||||
m_last = ((DTMIterator)nodeVector).getLength();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an empty XNodeSet object. This is used to create a mutable
|
||||
* nodeset to which random nodes may be added.
|
||||
*/
|
||||
private NodeSequence(DTMManager dtmMgr)
|
||||
{
|
||||
super(new NodeVector());
|
||||
m_last = 0;
|
||||
m_dtmMgr = dtmMgr;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a new NodeSequence in an invalid (null) state.
|
||||
*/
|
||||
public NodeSequence()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see DTMIterator#getDTM(int)
|
||||
*/
|
||||
public DTM getDTM(int nodeHandle)
|
||||
{
|
||||
DTMManager mgr = getDTMManager();
|
||||
if(null != mgr)
|
||||
return getDTMManager().getDTM(nodeHandle);
|
||||
else
|
||||
{
|
||||
assertion(false, "Can not get a DTM Unless a DTMManager has been set!");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DTMIterator#getDTMManager()
|
||||
*/
|
||||
public DTMManager getDTMManager()
|
||||
{
|
||||
return m_dtmMgr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DTMIterator#getRoot()
|
||||
*/
|
||||
public int getRoot()
|
||||
{
|
||||
if(null != m_iter)
|
||||
return m_iter.getRoot();
|
||||
else
|
||||
{
|
||||
// NodeSetDTM will call this, and so it's not a good thing to throw
|
||||
// an assertion here.
|
||||
// assertion(false, "Can not get the root from a non-iterated NodeSequence!");
|
||||
return DTM.NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DTMIterator#setRoot(int, Object)
|
||||
*/
|
||||
public void setRoot(int nodeHandle, Object environment)
|
||||
{
|
||||
// If root is DTM.NULL, then something's wrong with the context
|
||||
if (nodeHandle == DTM.NULL)
|
||||
{
|
||||
throw new RuntimeException("Unable to evaluate expression using " +
|
||||
"this context");
|
||||
}
|
||||
|
||||
if(null != m_iter)
|
||||
{
|
||||
XPathContext xctxt = (XPathContext)environment;
|
||||
m_dtmMgr = xctxt.getDTMManager();
|
||||
m_iter.setRoot(nodeHandle, environment);
|
||||
if(!m_iter.isDocOrdered())
|
||||
{
|
||||
if(!hasCache())
|
||||
setShouldCacheNodes(true);
|
||||
runTo(-1);
|
||||
m_next=0;
|
||||
}
|
||||
}
|
||||
else
|
||||
assertion(false, "Can not setRoot on a non-iterated NodeSequence!");
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DTMIterator#reset()
|
||||
*/
|
||||
public void reset()
|
||||
{
|
||||
m_next = 0;
|
||||
// not resetting the iterator on purpose!!!
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DTMIterator#getWhatToShow()
|
||||
*/
|
||||
public int getWhatToShow()
|
||||
{
|
||||
return hasCache() ? (DTMFilter.SHOW_ALL & ~DTMFilter.SHOW_ENTITY_REFERENCE)
|
||||
: m_iter.getWhatToShow();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DTMIterator#getExpandEntityReferences()
|
||||
*/
|
||||
public boolean getExpandEntityReferences()
|
||||
{
|
||||
if(null != m_iter)
|
||||
return m_iter.getExpandEntityReferences();
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DTMIterator#nextNode()
|
||||
*/
|
||||
public int nextNode()
|
||||
{
|
||||
// If the cache is on, and the node has already been found, then
|
||||
// just return from the list.
|
||||
NodeVector vec = getVector();
|
||||
if (null != vec)
|
||||
{
|
||||
// There is a cache
|
||||
if(m_next < vec.size())
|
||||
{
|
||||
// The node is in the cache, so just return it.
|
||||
int next = vec.elementAt(m_next);
|
||||
m_next++;
|
||||
return next;
|
||||
}
|
||||
else if(cacheComplete() || (-1 != m_last) || (null == m_iter))
|
||||
{
|
||||
m_next++;
|
||||
return DTM.NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (null == m_iter)
|
||||
return DTM.NULL;
|
||||
|
||||
int next = m_iter.nextNode();
|
||||
if(DTM.NULL != next)
|
||||
{
|
||||
if(hasCache())
|
||||
{
|
||||
if(m_iter.isDocOrdered())
|
||||
{
|
||||
getVector().addElement(next);
|
||||
m_next++;
|
||||
}
|
||||
else
|
||||
{
|
||||
int insertIndex = addNodeInDocOrder(next);
|
||||
if(insertIndex >= 0)
|
||||
m_next++;
|
||||
}
|
||||
}
|
||||
else
|
||||
m_next++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// We have exhausted the iterator, and if there is a cache
|
||||
// it must have all nodes in it by now, so let the cache
|
||||
// know that it is complete.
|
||||
markCacheComplete();
|
||||
|
||||
m_last = m_next;
|
||||
m_next++;
|
||||
}
|
||||
|
||||
return next;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DTMIterator#previousNode()
|
||||
*/
|
||||
public int previousNode()
|
||||
{
|
||||
if(hasCache())
|
||||
{
|
||||
if(m_next <= 0)
|
||||
return DTM.NULL;
|
||||
else
|
||||
{
|
||||
m_next--;
|
||||
return item(m_next);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int n = m_iter.previousNode();
|
||||
m_next = m_iter.getCurrentPos();
|
||||
return m_next;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DTMIterator#detach()
|
||||
*/
|
||||
public void detach()
|
||||
{
|
||||
if(null != m_iter)
|
||||
m_iter.detach();
|
||||
super.detach();
|
||||
}
|
||||
|
||||
/**
|
||||
* Calling this with a value of false will cause the nodeset
|
||||
* to be cached.
|
||||
* @see DTMIterator#allowDetachToRelease(boolean)
|
||||
*/
|
||||
public void allowDetachToRelease(boolean allowRelease)
|
||||
{
|
||||
if((false == allowRelease) && !hasCache())
|
||||
{
|
||||
setShouldCacheNodes(true);
|
||||
}
|
||||
|
||||
if(null != m_iter)
|
||||
m_iter.allowDetachToRelease(allowRelease);
|
||||
super.allowDetachToRelease(allowRelease);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DTMIterator#getCurrentNode()
|
||||
*/
|
||||
public int getCurrentNode()
|
||||
{
|
||||
if(hasCache())
|
||||
{
|
||||
int currentIndex = m_next-1;
|
||||
NodeVector vec = getVector();
|
||||
if((currentIndex >= 0) && (currentIndex < vec.size()))
|
||||
return vec.elementAt(currentIndex);
|
||||
else
|
||||
return DTM.NULL;
|
||||
}
|
||||
|
||||
if(null != m_iter)
|
||||
{
|
||||
return m_iter.getCurrentNode();
|
||||
}
|
||||
else
|
||||
return DTM.NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DTMIterator#isFresh()
|
||||
*/
|
||||
public boolean isFresh()
|
||||
{
|
||||
return (0 == m_next);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DTMIterator#setShouldCacheNodes(boolean)
|
||||
*/
|
||||
public void setShouldCacheNodes(boolean b)
|
||||
{
|
||||
if (b)
|
||||
{
|
||||
if(!hasCache())
|
||||
{
|
||||
SetVector(new NodeVector());
|
||||
}
|
||||
// else
|
||||
// getVector().RemoveAllNoClear(); // Is this good?
|
||||
}
|
||||
else
|
||||
SetVector(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DTMIterator#isMutable()
|
||||
*/
|
||||
public boolean isMutable()
|
||||
{
|
||||
return hasCache(); // though may be surprising if it also has an iterator!
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DTMIterator#getCurrentPos()
|
||||
*/
|
||||
public int getCurrentPos()
|
||||
{
|
||||
return m_next;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DTMIterator#runTo(int)
|
||||
*/
|
||||
public void runTo(int index)
|
||||
{
|
||||
int n;
|
||||
|
||||
if (-1 == index)
|
||||
{
|
||||
int pos = m_next;
|
||||
while (DTM.NULL != (n = nextNode()));
|
||||
m_next = pos;
|
||||
}
|
||||
else if(m_next == index)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if(hasCache() && index < getVector().size())
|
||||
{
|
||||
m_next = index;
|
||||
}
|
||||
else if((null == getVector()) && (index < m_next))
|
||||
{
|
||||
while ((m_next >= index) && DTM.NULL != (n = previousNode()));
|
||||
}
|
||||
else
|
||||
{
|
||||
while ((m_next < index) && DTM.NULL != (n = nextNode()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DTMIterator#setCurrentPos(int)
|
||||
*/
|
||||
public void setCurrentPos(int i)
|
||||
{
|
||||
runTo(i);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DTMIterator#item(int)
|
||||
*/
|
||||
public int item(int index)
|
||||
{
|
||||
setCurrentPos(index);
|
||||
int n = nextNode();
|
||||
m_next = index;
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DTMIterator#setItem(int, int)
|
||||
*/
|
||||
public void setItem(int node, int index)
|
||||
{
|
||||
NodeVector vec = getVector();
|
||||
if(null != vec)
|
||||
{
|
||||
int oldNode = vec.elementAt(index);
|
||||
if (oldNode != node && m_cache.useCount() > 1) {
|
||||
/* If we are going to set the node at the given index
|
||||
* to a different value, and the cache is shared
|
||||
* (has a use count greater than 1)
|
||||
* then make a copy of the cache and use it
|
||||
* so we don't overwrite the value for other
|
||||
* users of the cache.
|
||||
*/
|
||||
IteratorCache newCache = new IteratorCache();
|
||||
final NodeVector nv;
|
||||
try {
|
||||
nv = (NodeVector) vec.clone();
|
||||
} catch (CloneNotSupportedException e) {
|
||||
// This should never happen
|
||||
e.printStackTrace();
|
||||
RuntimeException rte = new RuntimeException(e.getMessage());
|
||||
throw rte;
|
||||
}
|
||||
newCache.setVector(nv);
|
||||
newCache.setCacheComplete(true);
|
||||
m_cache = newCache;
|
||||
vec = nv;
|
||||
|
||||
// Keep our superclass informed of the current NodeVector
|
||||
super.setObject(nv);
|
||||
|
||||
/* When we get to here the new cache has
|
||||
* a use count of 1 and when setting a
|
||||
* bunch of values on the same NodeSequence,
|
||||
* such as when sorting, we will keep setting
|
||||
* values in that same copy which has a use count of 1.
|
||||
*/
|
||||
}
|
||||
vec.setElementAt(node, index);
|
||||
m_last = vec.size();
|
||||
}
|
||||
else
|
||||
m_iter.setItem(node, index);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DTMIterator#getLength()
|
||||
*/
|
||||
public int getLength()
|
||||
{
|
||||
IteratorCache cache = getCache();
|
||||
|
||||
if(cache != null)
|
||||
{
|
||||
// Nodes from the iterator are cached
|
||||
if (cache.isComplete()) {
|
||||
// All of the nodes from the iterator are cached
|
||||
// so just return the number of nodes in the cache
|
||||
NodeVector nv = cache.getVector();
|
||||
return nv.size();
|
||||
}
|
||||
|
||||
// If this NodeSequence wraps a mutable nodeset, then
|
||||
// m_last will not reflect the size of the nodeset if
|
||||
// it has been mutated...
|
||||
if (m_iter instanceof NodeSetDTM)
|
||||
{
|
||||
return m_iter.getLength();
|
||||
}
|
||||
|
||||
if(-1 == m_last)
|
||||
{
|
||||
int pos = m_next;
|
||||
runTo(-1);
|
||||
m_next = pos;
|
||||
}
|
||||
return m_last;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (-1 == m_last) ? (m_last = m_iter.getLength()) : m_last;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Note: Not a deep clone.
|
||||
* @see DTMIterator#cloneWithReset()
|
||||
*/
|
||||
public DTMIterator cloneWithReset() throws CloneNotSupportedException
|
||||
{
|
||||
NodeSequence seq = (NodeSequence)super.clone();
|
||||
seq.m_next = 0;
|
||||
if (m_cache != null) {
|
||||
// In making this clone of an iterator we are making
|
||||
// another NodeSequence object it has a reference
|
||||
// to the same IteratorCache object as the original
|
||||
// so we need to remember that more than one
|
||||
// NodeSequence object shares the cache.
|
||||
m_cache.increaseUseCount();
|
||||
}
|
||||
|
||||
return seq;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a clone of this iterator, but don't reset the iteration in the
|
||||
* process, so that it may be used from the current position.
|
||||
* Note: Not a deep clone.
|
||||
*
|
||||
* @return A clone of this object.
|
||||
*
|
||||
* @throws CloneNotSupportedException
|
||||
*/
|
||||
public Object clone() throws CloneNotSupportedException
|
||||
{
|
||||
NodeSequence clone = (NodeSequence) super.clone();
|
||||
if (null != m_iter) clone.m_iter = (DTMIterator) m_iter.clone();
|
||||
if (m_cache != null) {
|
||||
// In making this clone of an iterator we are making
|
||||
// another NodeSequence object it has a reference
|
||||
// to the same IteratorCache object as the original
|
||||
// so we need to remember that more than one
|
||||
// NodeSequence object shares the cache.
|
||||
m_cache.increaseUseCount();
|
||||
}
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see DTMIterator#isDocOrdered()
|
||||
*/
|
||||
public boolean isDocOrdered()
|
||||
{
|
||||
if(null != m_iter)
|
||||
return m_iter.isDocOrdered();
|
||||
else
|
||||
return true; // can't be sure?
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DTMIterator#getAxis()
|
||||
*/
|
||||
public int getAxis()
|
||||
{
|
||||
if(null != m_iter)
|
||||
return m_iter.getAxis();
|
||||
else
|
||||
{
|
||||
assertion(false, "Can not getAxis from a non-iterated node sequence!");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see PathComponent#getAnalysisBits()
|
||||
*/
|
||||
public int getAnalysisBits()
|
||||
{
|
||||
if((null != m_iter) && (m_iter instanceof PathComponent))
|
||||
return ((PathComponent)m_iter).getAnalysisBits();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.xpath.Expression#fixupVariables(Vector, int)
|
||||
*/
|
||||
public void fixupVariables(Vector vars, int globalsSize)
|
||||
{
|
||||
super.fixupVariables(vars, globalsSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the node into a vector of nodes where it should occur in
|
||||
* document order.
|
||||
* @param node The node to be added.
|
||||
* @return insertIndex.
|
||||
* @throws RuntimeException thrown if this NodeSetDTM is not of
|
||||
* a mutable type.
|
||||
*/
|
||||
protected int addNodeInDocOrder(int node)
|
||||
{
|
||||
assertion(hasCache(), "addNodeInDocOrder must be done on a mutable sequence!");
|
||||
|
||||
int insertIndex = -1;
|
||||
|
||||
NodeVector vec = getVector();
|
||||
|
||||
// This needs to do a binary search, but a binary search
|
||||
// is somewhat tough because the sequence test involves
|
||||
// two nodes.
|
||||
int size = vec.size(), i;
|
||||
|
||||
for (i = size - 1; i >= 0; i--)
|
||||
{
|
||||
int child = vec.elementAt(i);
|
||||
|
||||
if (child == node)
|
||||
{
|
||||
i = -2; // Duplicate, suppress insert
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
DTM dtm = m_dtmMgr.getDTM(node);
|
||||
if (!dtm.isNodeAfter(node, child))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i != -2)
|
||||
{
|
||||
insertIndex = i + 1;
|
||||
|
||||
vec.insertElementAt(node, insertIndex);
|
||||
}
|
||||
|
||||
// checkDups();
|
||||
return insertIndex;
|
||||
} // end addNodeInDocOrder(Vector v, Object obj)
|
||||
|
||||
/**
|
||||
* It used to be that many locations in the code simply
|
||||
* did an assignment to this.m_obj directly, rather than
|
||||
* calling the setObject(Object) method. The problem is
|
||||
* that our super-class would be updated on what the
|
||||
* cache associated with this NodeSequence, but
|
||||
* we wouldn't know ourselves.
|
||||
* <p>
|
||||
* All setting of m_obj is done through setObject() now,
|
||||
* and this method over-rides the super-class method.
|
||||
* So now we are in the loop have an opportunity
|
||||
* to update some caching information.
|
||||
*
|
||||
*/
|
||||
protected void setObject(Object obj) {
|
||||
if (obj instanceof NodeVector) {
|
||||
// Keep our superclass informed of the current NodeVector
|
||||
// ... if we don't the smoketest fails (don't know why).
|
||||
super.setObject(obj);
|
||||
|
||||
// A copy of the code of what SetVector() would do.
|
||||
NodeVector v = (NodeVector)obj;
|
||||
if (m_cache != null) {
|
||||
m_cache.setVector(v);
|
||||
} else if (v!=null) {
|
||||
m_cache = new IteratorCache();
|
||||
m_cache.setVector(v);
|
||||
}
|
||||
} else if (obj instanceof IteratorCache) {
|
||||
IteratorCache cache = (IteratorCache) obj;
|
||||
m_cache = cache;
|
||||
m_cache.increaseUseCount();
|
||||
|
||||
// Keep our superclass informed of the current NodeVector
|
||||
super.setObject(cache.getVector());
|
||||
} else {
|
||||
super.setObject(obj);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Each NodeSequence object has an iterator which is "walked".
|
||||
* As an iterator is walked one obtains nodes from it.
|
||||
* As those nodes are obtained they may be cached, making
|
||||
* the next walking of a copy or clone of the iterator faster.
|
||||
* This field (m_cache) is a reference to such a cache,
|
||||
* which is populated as the iterator is walked.
|
||||
* <p>
|
||||
* Note that multiple NodeSequence objects may hold a
|
||||
* reference to the same cache, and also
|
||||
* (and this is important) the same iterator.
|
||||
* The iterator and its cache may be shared among
|
||||
* many NodeSequence objects.
|
||||
* <p>
|
||||
* If one of the NodeSequence objects walks ahead
|
||||
* of the others it fills in the cache.
|
||||
* As the others NodeSequence objects catch up they
|
||||
* get their values from
|
||||
* the cache rather than the iterator itself, so
|
||||
* the iterator is only ever walked once and everyone
|
||||
* benefits from the cache.
|
||||
* <p>
|
||||
* At some point the cache may be
|
||||
* complete due to walking to the end of one of
|
||||
* the copies of the iterator, and the cache is
|
||||
* then marked as "complete".
|
||||
* and the cache will have no more nodes added to it.
|
||||
* <p>
|
||||
* Its use-count is the number of NodeSequence objects that use it.
|
||||
*/
|
||||
private final static class IteratorCache {
|
||||
/**
|
||||
* A list of nodes already obtained from the iterator.
|
||||
* As the iterator is walked the nodes obtained from
|
||||
* it are appended to this list.
|
||||
* <p>
|
||||
* Both an iterator and its corresponding cache can
|
||||
* be shared by multiple NodeSequence objects.
|
||||
* <p>
|
||||
* For example, consider three NodeSequence objects
|
||||
* ns1, ns2 and ns3 doing such sharing, and the
|
||||
* nodes to be obtaind from the iterator being
|
||||
* the sequence { 33, 11, 44, 22, 55 }.
|
||||
* <p>
|
||||
* If ns3.nextNode() is called 3 times the the
|
||||
* underlying iterator will have walked through
|
||||
* 33, 11, 55 and these three nodes will have been put
|
||||
* in the cache.
|
||||
* <p>
|
||||
* If ns2.nextNode() is called 2 times it will return
|
||||
* 33 and 11 from the cache, leaving the iterator alone.
|
||||
* <p>
|
||||
* If ns1.nextNode() is called 6 times it will return
|
||||
* 33 and 11 from the cache, then get 44, 22, 55 from
|
||||
* the iterator, and appending 44, 22, 55 to the cache.
|
||||
* On the sixth call it is found that the iterator is
|
||||
* exhausted and the cache is marked complete.
|
||||
* <p>
|
||||
* Should ns2 or ns3 have nextNode() called they will
|
||||
* know that the cache is complete, and they will
|
||||
* obtain all subsequent nodes from the cache.
|
||||
* <p>
|
||||
* Note that the underlying iterator, though shared
|
||||
* is only ever walked once.
|
||||
*/
|
||||
private NodeVector m_vec2;
|
||||
|
||||
/**
|
||||
* true if the associated iterator is exhausted and
|
||||
* all nodes obtained from it are in the cache.
|
||||
*/
|
||||
private boolean m_isComplete2;
|
||||
|
||||
private int m_useCount2;
|
||||
|
||||
IteratorCache() {
|
||||
m_vec2 = null;
|
||||
m_isComplete2 = false;
|
||||
m_useCount2 = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns count of how many NodeSequence objects share this
|
||||
* IteratorCache object.
|
||||
*/
|
||||
private int useCount() {
|
||||
return m_useCount2;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called when yet another
|
||||
* NodeSequence object uses, or shares
|
||||
* this same cache.
|
||||
*
|
||||
*/
|
||||
private void increaseUseCount() {
|
||||
if (m_vec2 != null)
|
||||
m_useCount2++;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the NodeVector that holds the
|
||||
* growing list of nodes as they are appended
|
||||
* to the cached list.
|
||||
*/
|
||||
private void setVector(NodeVector nv) {
|
||||
m_vec2 = nv;
|
||||
m_useCount2 = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the cached list of nodes obtained from
|
||||
* the iterator so far.
|
||||
*/
|
||||
private NodeVector getVector() {
|
||||
return m_vec2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this method with 'true' if the
|
||||
* iterator is exhausted and the cached list
|
||||
* is complete, or no longer growing.
|
||||
*/
|
||||
private void setCacheComplete(boolean b) {
|
||||
m_isComplete2 = b;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if no cache is complete
|
||||
* and immutable.
|
||||
*/
|
||||
private boolean isComplete() {
|
||||
return m_isComplete2;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the cached list of nodes appended with
|
||||
* values obtained from the iterator as
|
||||
* a NodeSequence is walked when its
|
||||
* nextNode() method is called.
|
||||
*/
|
||||
protected IteratorCache getIteratorCache() {
|
||||
return m_cache;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,346 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.axes;
|
||||
|
||||
import com.sun.org.apache.xml.internal.dtm.DTM;
|
||||
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
|
||||
import com.sun.org.apache.xml.internal.dtm.DTMFilter;
|
||||
import com.sun.org.apache.xml.internal.dtm.DTMIterator;
|
||||
import com.sun.org.apache.xpath.internal.Expression;
|
||||
import com.sun.org.apache.xpath.internal.XPathContext;
|
||||
import com.sun.org.apache.xpath.internal.compiler.Compiler;
|
||||
import com.sun.org.apache.xpath.internal.compiler.OpMap;
|
||||
|
||||
/**
|
||||
* This class implements a general iterator for
|
||||
* those LocationSteps with only one step, and perhaps a predicate.
|
||||
* @see com.sun.org.apache.xpath.internal.axes#LocPathIterator
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public class OneStepIterator extends ChildTestIterator
|
||||
{
|
||||
static final long serialVersionUID = 4623710779664998283L;
|
||||
/** The traversal axis from where the nodes will be filtered. */
|
||||
protected int m_axis = -1;
|
||||
|
||||
/** The DTM inner traversal class, that corresponds to the super axis. */
|
||||
protected DTMAxisIterator m_iterator;
|
||||
|
||||
/**
|
||||
* Create a OneStepIterator object.
|
||||
*
|
||||
* @param compiler A reference to the Compiler that contains the op map.
|
||||
* @param opPos The position within the op map, which contains the
|
||||
* location path expression for this itterator.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
OneStepIterator(Compiler compiler, int opPos, int analysis)
|
||||
throws javax.xml.transform.TransformerException
|
||||
{
|
||||
super(compiler, opPos, analysis);
|
||||
int firstStepPos = OpMap.getFirstChildPos(opPos);
|
||||
|
||||
m_axis = WalkerFactory.getAxisFromStep(compiler, firstStepPos);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a OneStepIterator object.
|
||||
*
|
||||
* @param iterator The DTM iterator which this iterator will use.
|
||||
* @param axis One of Axis.Child, etc., or -1 if the axis is unknown.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
public OneStepIterator(DTMAxisIterator iterator, int axis)
|
||||
throws javax.xml.transform.TransformerException
|
||||
{
|
||||
super(null);
|
||||
|
||||
m_iterator = iterator;
|
||||
m_axis = axis;
|
||||
int whatToShow = DTMFilter.SHOW_ALL;
|
||||
initNodeTest(whatToShow);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the context values for this expression
|
||||
* after it is cloned.
|
||||
*
|
||||
* @param context The XPath runtime context for this
|
||||
* transformation.
|
||||
*/
|
||||
public void setRoot(int context, Object environment)
|
||||
{
|
||||
super.setRoot(context, environment);
|
||||
if(m_axis > -1)
|
||||
m_iterator = m_cdtm.getAxisIterator(m_axis);
|
||||
m_iterator.setStartNode(m_context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Detaches the iterator from the set which it iterated over, releasing
|
||||
* any computational resources and placing the iterator in the INVALID
|
||||
* state. After<code>detach</code> has been invoked, calls to
|
||||
* <code>nextNode</code> or<code>previousNode</code> will raise the
|
||||
* exception INVALID_STATE_ERR.
|
||||
*/
|
||||
public void detach()
|
||||
{
|
||||
if(m_allowDetach)
|
||||
{
|
||||
if(m_axis > -1)
|
||||
m_iterator = null;
|
||||
|
||||
// Always call the superclass detach last!
|
||||
super.detach();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next node via getFirstAttribute && getNextAttribute.
|
||||
*/
|
||||
protected int getNextNode()
|
||||
{
|
||||
return m_lastFetched = m_iterator.next();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a cloned iterator.
|
||||
*
|
||||
* @return A new iterator that can be used without mutating this one.
|
||||
*
|
||||
* @throws CloneNotSupportedException
|
||||
*/
|
||||
public Object clone() throws CloneNotSupportedException
|
||||
{
|
||||
// Do not access the location path itterator during this operation!
|
||||
|
||||
OneStepIterator clone = (OneStepIterator) super.clone();
|
||||
|
||||
if(m_iterator != null)
|
||||
{
|
||||
clone.m_iterator = m_iterator.cloneIterator();
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a cloned Iterator that is reset to the beginning
|
||||
* of the query.
|
||||
*
|
||||
* @return A cloned NodeIterator set of the start of the query.
|
||||
*
|
||||
* @throws CloneNotSupportedException
|
||||
*/
|
||||
public DTMIterator cloneWithReset() throws CloneNotSupportedException
|
||||
{
|
||||
|
||||
OneStepIterator clone = (OneStepIterator) super.cloneWithReset();
|
||||
clone.m_iterator = m_iterator;
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Tells if this is a reverse axes. Overrides AxesWalker#isReverseAxes.
|
||||
*
|
||||
* @return true for this class.
|
||||
*/
|
||||
public boolean isReverseAxes()
|
||||
{
|
||||
return m_iterator.isReverse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current sub-context position. In order to do the
|
||||
* reverse axes count, for the moment this re-searches the axes
|
||||
* up to the predicate. An optimization on this is to cache
|
||||
* the nodes searched, but, for the moment, this case is probably
|
||||
* rare enough that the added complexity isn't worth it.
|
||||
*
|
||||
* @param predicateIndex The predicate index of the proximity position.
|
||||
*
|
||||
* @return The pridicate index, or -1.
|
||||
*/
|
||||
protected int getProximityPosition(int predicateIndex)
|
||||
{
|
||||
if(!isReverseAxes())
|
||||
return super.getProximityPosition(predicateIndex);
|
||||
|
||||
// A negative predicate index seems to occur with
|
||||
// (preceding-sibling::*|following-sibling::*)/ancestor::*[position()]/*[position()]
|
||||
// -sb
|
||||
if(predicateIndex < 0)
|
||||
return -1;
|
||||
|
||||
if (m_proximityPositions[predicateIndex] <= 0)
|
||||
{
|
||||
XPathContext xctxt = getXPathContext();
|
||||
try
|
||||
{
|
||||
OneStepIterator clone = (OneStepIterator) this.clone();
|
||||
|
||||
int root = getRoot();
|
||||
xctxt.pushCurrentNode(root);
|
||||
clone.setRoot(root, xctxt);
|
||||
|
||||
// clone.setPredicateCount(predicateIndex);
|
||||
clone.m_predCount = predicateIndex;
|
||||
|
||||
// Count 'em all
|
||||
int count = 1;
|
||||
int next;
|
||||
|
||||
while (DTM.NULL != (next = clone.nextNode()))
|
||||
{
|
||||
count++;
|
||||
}
|
||||
|
||||
m_proximityPositions[predicateIndex] += count;
|
||||
}
|
||||
catch (CloneNotSupportedException cnse)
|
||||
{
|
||||
|
||||
// can't happen
|
||||
}
|
||||
finally
|
||||
{
|
||||
xctxt.popCurrentNode();
|
||||
}
|
||||
}
|
||||
|
||||
return m_proximityPositions[predicateIndex];
|
||||
}
|
||||
|
||||
/**
|
||||
* The number of nodes in the list. The range of valid child node indices
|
||||
* is 0 to <code>length-1</code> inclusive.
|
||||
*
|
||||
* @return The number of nodes in the list, always greater or equal to zero.
|
||||
*/
|
||||
public int getLength()
|
||||
{
|
||||
if(!isReverseAxes())
|
||||
return super.getLength();
|
||||
|
||||
// Tell if this is being called from within a predicate.
|
||||
boolean isPredicateTest = (this == m_execContext.getSubContextList());
|
||||
|
||||
// And get how many total predicates are part of this step.
|
||||
int predCount = getPredicateCount();
|
||||
|
||||
// If we have already calculated the length, and the current predicate
|
||||
// is the first predicate, then return the length. We don't cache
|
||||
// the anything but the length of the list to the first predicate.
|
||||
if (-1 != m_length && isPredicateTest && m_predicateIndex < 1)
|
||||
return m_length;
|
||||
|
||||
int count = 0;
|
||||
|
||||
XPathContext xctxt = getXPathContext();
|
||||
try
|
||||
{
|
||||
OneStepIterator clone = (OneStepIterator) this.cloneWithReset();
|
||||
|
||||
int root = getRoot();
|
||||
xctxt.pushCurrentNode(root);
|
||||
clone.setRoot(root, xctxt);
|
||||
|
||||
clone.m_predCount = m_predicateIndex;
|
||||
|
||||
int next;
|
||||
|
||||
while (DTM.NULL != (next = clone.nextNode()))
|
||||
{
|
||||
count++;
|
||||
}
|
||||
}
|
||||
catch (CloneNotSupportedException cnse)
|
||||
{
|
||||
// can't happen
|
||||
}
|
||||
finally
|
||||
{
|
||||
xctxt.popCurrentNode();
|
||||
}
|
||||
if (isPredicateTest && m_predicateIndex < 1)
|
||||
m_length = count;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Count backwards one proximity position.
|
||||
*
|
||||
* @param i The predicate index.
|
||||
*/
|
||||
protected void countProximityPosition(int i)
|
||||
{
|
||||
if(!isReverseAxes())
|
||||
super.countProximityPosition(i);
|
||||
else if (i < m_proximityPositions.length)
|
||||
m_proximityPositions[i]--;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the iterator.
|
||||
*/
|
||||
public void reset()
|
||||
{
|
||||
|
||||
super.reset();
|
||||
if(null != m_iterator)
|
||||
m_iterator.reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the axis being iterated, if it is known.
|
||||
*
|
||||
* @return Axis.CHILD, etc., or -1 if the axis is not known or is of multiple
|
||||
* types.
|
||||
*/
|
||||
public int getAxis()
|
||||
{
|
||||
return m_axis;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Expression#deepEquals(Expression)
|
||||
*/
|
||||
public boolean deepEquals(Expression expr)
|
||||
{
|
||||
if(!super.deepEquals(expr))
|
||||
return false;
|
||||
|
||||
if(m_axis != ((OneStepIterator)expr).m_axis)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.axes;
|
||||
|
||||
import com.sun.org.apache.xml.internal.dtm.DTM;
|
||||
import com.sun.org.apache.xml.internal.dtm.DTMFilter;
|
||||
import com.sun.org.apache.xpath.internal.Expression;
|
||||
import com.sun.org.apache.xpath.internal.compiler.Compiler;
|
||||
import com.sun.org.apache.xpath.internal.compiler.OpMap;
|
||||
|
||||
/**
|
||||
* This class implements a general iterator for
|
||||
* those LocationSteps with only one step, and perhaps a predicate,
|
||||
* that only go forward (i.e. it can not be used with ancestors,
|
||||
* preceding, etc.)
|
||||
* @see com.sun.org.apache.xpath.internal.axes#ChildTestIterator
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public class OneStepIteratorForward extends ChildTestIterator
|
||||
{
|
||||
static final long serialVersionUID = -1576936606178190566L;
|
||||
/** The traversal axis from where the nodes will be filtered. */
|
||||
protected int m_axis = -1;
|
||||
|
||||
/**
|
||||
* Create a OneStepIterator object.
|
||||
*
|
||||
* @param compiler A reference to the Compiler that contains the op map.
|
||||
* @param opPos The position within the op map, which contains the
|
||||
* location path expression for this itterator.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
OneStepIteratorForward(Compiler compiler, int opPos, int analysis)
|
||||
throws javax.xml.transform.TransformerException
|
||||
{
|
||||
super(compiler, opPos, analysis);
|
||||
int firstStepPos = OpMap.getFirstChildPos(opPos);
|
||||
|
||||
m_axis = WalkerFactory.getAxisFromStep(compiler, firstStepPos);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a OneStepIterator object that will just traverse the self axes.
|
||||
*
|
||||
* @param axis One of the com.sun.org.apache.xml.internal.dtm.Axis integers.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
public OneStepIteratorForward(int axis)
|
||||
{
|
||||
super(null);
|
||||
|
||||
m_axis = axis;
|
||||
int whatToShow = DTMFilter.SHOW_ALL;
|
||||
initNodeTest(whatToShow);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Initialize the context values for this expression
|
||||
* after it is cloned.
|
||||
*
|
||||
* @param context The XPath runtime context for this
|
||||
* transformation.
|
||||
*/
|
||||
public void setRoot(int context, Object environment)
|
||||
{
|
||||
super.setRoot(context, environment);
|
||||
m_traverser = m_cdtm.getAxisTraverser(m_axis);
|
||||
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Return the first node out of the nodeset, if this expression is
|
||||
// * a nodeset expression. This is the default implementation for
|
||||
// * nodesets.
|
||||
// * <p>WARNING: Do not mutate this class from this function!</p>
|
||||
// * @param xctxt The XPath runtime context.
|
||||
// * @return the first node out of the nodeset, or DTM.NULL.
|
||||
// */
|
||||
// public int asNode(XPathContext xctxt)
|
||||
// throws javax.xml.transform.TransformerException
|
||||
// {
|
||||
// if(getPredicateCount() > 0)
|
||||
// return super.asNode(xctxt);
|
||||
//
|
||||
// int current = xctxt.getCurrentNode();
|
||||
//
|
||||
// DTM dtm = xctxt.getDTM(current);
|
||||
// DTMAxisTraverser traverser = dtm.getAxisTraverser(m_axis);
|
||||
//
|
||||
// String localName = getLocalName();
|
||||
// String namespace = getNamespace();
|
||||
// int what = m_whatToShow;
|
||||
//
|
||||
// // System.out.println("what: ");
|
||||
// // NodeTest.debugWhatToShow(what);
|
||||
// if(DTMFilter.SHOW_ALL == what
|
||||
// || ((DTMFilter.SHOW_ELEMENT & what) == 0)
|
||||
// || localName == NodeTest.WILD
|
||||
// || namespace == NodeTest.WILD)
|
||||
// {
|
||||
// return traverser.first(current);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// int type = getNodeTypeTest(what);
|
||||
// int extendedType = dtm.getExpandedTypeID(namespace, localName, type);
|
||||
// return traverser.first(current, extendedType);
|
||||
// }
|
||||
// }
|
||||
|
||||
/**
|
||||
* Get the next node via getFirstAttribute && getNextAttribute.
|
||||
*/
|
||||
protected int getNextNode()
|
||||
{
|
||||
m_lastFetched = (DTM.NULL == m_lastFetched)
|
||||
? m_traverser.first(m_context)
|
||||
: m_traverser.next(m_context, m_lastFetched);
|
||||
return m_lastFetched;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the axis being iterated, if it is known.
|
||||
*
|
||||
* @return Axis.CHILD, etc., or -1 if the axis is not known or is of multiple
|
||||
* types.
|
||||
*/
|
||||
public int getAxis()
|
||||
{
|
||||
return m_axis;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Expression#deepEquals(Expression)
|
||||
*/
|
||||
public boolean deepEquals(Expression expr)
|
||||
{
|
||||
if(!super.deepEquals(expr))
|
||||
return false;
|
||||
|
||||
if(m_axis != ((OneStepIteratorForward)expr).m_axis)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.axes;
|
||||
|
||||
/**
|
||||
* Classes who implement this information provide information needed for
|
||||
* static analysis of a path component.
|
||||
*/
|
||||
public interface PathComponent
|
||||
{
|
||||
/**
|
||||
* Get the analysis bits for this path component, as defined in the WalkerFactory.
|
||||
* @return One of WalkerFactory#BIT_DESCENDANT, etc.
|
||||
*/
|
||||
public int getAnalysisBits();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,655 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.axes;
|
||||
|
||||
import com.sun.org.apache.xml.internal.dtm.DTM;
|
||||
import com.sun.org.apache.xml.internal.dtm.DTMIterator;
|
||||
import com.sun.org.apache.xml.internal.utils.PrefixResolver;
|
||||
import com.sun.org.apache.xpath.internal.Expression;
|
||||
import com.sun.org.apache.xpath.internal.ExpressionOwner;
|
||||
import com.sun.org.apache.xpath.internal.XPathContext;
|
||||
import com.sun.org.apache.xpath.internal.XPathVisitor;
|
||||
import com.sun.org.apache.xpath.internal.compiler.Compiler;
|
||||
import com.sun.org.apache.xpath.internal.objects.XObject;
|
||||
import com.sun.org.apache.xpath.internal.patterns.NodeTest;
|
||||
|
||||
public abstract class PredicatedNodeTest extends NodeTest implements SubContextList
|
||||
{
|
||||
static final long serialVersionUID = -6193530757296377351L;
|
||||
|
||||
/**
|
||||
* Construct an AxesWalker using a LocPathIterator.
|
||||
*
|
||||
* @param locPathIterator non-null reference to the parent iterator.
|
||||
*/
|
||||
PredicatedNodeTest(LocPathIterator locPathIterator)
|
||||
{
|
||||
m_lpi = locPathIterator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an AxesWalker. The location path iterator will have to be set
|
||||
* before use.
|
||||
*/
|
||||
PredicatedNodeTest()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the object from a serialization stream.
|
||||
*
|
||||
* @param stream Input stream to read from
|
||||
*
|
||||
* @throws java.io.IOException
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
private void readObject(java.io.ObjectInputStream stream)
|
||||
throws java.io.IOException, javax.xml.transform.TransformerException
|
||||
{
|
||||
try
|
||||
{
|
||||
stream.defaultReadObject();
|
||||
m_predicateIndex = -1;
|
||||
|
||||
/**
|
||||
* Initialize to the declared value.
|
||||
* As noted at declaration, this variable is used only for clones for getLastPos,
|
||||
* it should have been excluded from serialization. For compatibility, we'll
|
||||
* keep it as is but initializing to the declared value.
|
||||
*/
|
||||
m_predCount = -1;
|
||||
resetProximityPositions();
|
||||
}
|
||||
catch (ClassNotFoundException cnfe)
|
||||
{
|
||||
throw new javax.xml.transform.TransformerException(cnfe);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a cloned PrdicatedNodeTest.
|
||||
*
|
||||
* @return A new PredicatedNodeTest that can be used without mutating this one.
|
||||
*
|
||||
* @throws CloneNotSupportedException
|
||||
*/
|
||||
public Object clone() throws CloneNotSupportedException
|
||||
{
|
||||
// Do not access the location path itterator during this operation!
|
||||
|
||||
PredicatedNodeTest clone = (PredicatedNodeTest) super.clone();
|
||||
|
||||
if ((null != this.m_proximityPositions)
|
||||
&& (this.m_proximityPositions == clone.m_proximityPositions))
|
||||
{
|
||||
clone.m_proximityPositions = new int[this.m_proximityPositions.length];
|
||||
|
||||
System.arraycopy(this.m_proximityPositions, 0,
|
||||
clone.m_proximityPositions, 0,
|
||||
this.m_proximityPositions.length);
|
||||
}
|
||||
|
||||
if(clone.m_lpi == this)
|
||||
clone.m_lpi = (LocPathIterator)clone;
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
// Only for clones for findLastPos. See bug4638.
|
||||
protected int m_predCount = -1;
|
||||
|
||||
/**
|
||||
* Get the number of predicates that this walker has.
|
||||
*
|
||||
* @return the number of predicates that this walker has.
|
||||
*/
|
||||
public int getPredicateCount()
|
||||
{
|
||||
if(-1 == m_predCount)
|
||||
return (null == m_predicates) ? 0 : m_predicates.length;
|
||||
else
|
||||
return m_predCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the number of predicates that this walker has. This does more
|
||||
* that one would think, as it creates a new predicate array of the
|
||||
* size of the count argument, and copies count predicates into the new
|
||||
* one from the old, and then reassigns the predicates value. All this
|
||||
* to keep from having to have a predicate count value.
|
||||
*
|
||||
* @param count The number of predicates, which must be equal or less
|
||||
* than the existing count.
|
||||
*/
|
||||
public void setPredicateCount(int count)
|
||||
{
|
||||
if(count > 0)
|
||||
{
|
||||
Expression[] newPredicates = new Expression[count];
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
newPredicates[i] = m_predicates[i];
|
||||
}
|
||||
m_predicates = newPredicates;
|
||||
}
|
||||
else
|
||||
m_predicates = null;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Init predicate info.
|
||||
*
|
||||
* @param compiler The Compiler object that has information about this
|
||||
* walker in the op map.
|
||||
* @param opPos The op code position of this location step.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
protected void initPredicateInfo(Compiler compiler, int opPos)
|
||||
throws javax.xml.transform.TransformerException
|
||||
{
|
||||
|
||||
int pos = compiler.getFirstPredicateOpPos(opPos);
|
||||
|
||||
if(pos > 0)
|
||||
{
|
||||
m_predicates = compiler.getCompiledPredicates(pos);
|
||||
if(null != m_predicates)
|
||||
{
|
||||
for(int i = 0; i < m_predicates.length; i++)
|
||||
{
|
||||
m_predicates[i].exprSetParent(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a predicate expression at the given index.
|
||||
*
|
||||
*
|
||||
* @param index Index of the predicate.
|
||||
*
|
||||
* @return A predicate expression.
|
||||
*/
|
||||
public Expression getPredicate(int index)
|
||||
{
|
||||
return m_predicates[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current sub-context position.
|
||||
*
|
||||
* @return The node position of this walker in the sub-context node list.
|
||||
*/
|
||||
public int getProximityPosition()
|
||||
{
|
||||
|
||||
// System.out.println("getProximityPosition - m_predicateIndex: "+m_predicateIndex);
|
||||
return getProximityPosition(m_predicateIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current sub-context position.
|
||||
*
|
||||
* @param xctxt The XPath runtime context.
|
||||
*
|
||||
* @return The node position of this walker in the sub-context node list.
|
||||
*/
|
||||
public int getProximityPosition(XPathContext xctxt)
|
||||
{
|
||||
return getProximityPosition();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the index of the last node that can be itterated to.
|
||||
*
|
||||
*
|
||||
* @param xctxt XPath runtime context.
|
||||
*
|
||||
* @return the index of the last node that can be itterated to.
|
||||
*/
|
||||
public abstract int getLastPos(XPathContext xctxt);
|
||||
|
||||
/**
|
||||
* Get the current sub-context position.
|
||||
*
|
||||
* @param predicateIndex The index of the predicate where the proximity
|
||||
* should be taken from.
|
||||
*
|
||||
* @return The node position of this walker in the sub-context node list.
|
||||
*/
|
||||
protected int getProximityPosition(int predicateIndex)
|
||||
{
|
||||
return (predicateIndex >= 0) ? m_proximityPositions[predicateIndex] : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the proximity positions counts.
|
||||
*/
|
||||
public void resetProximityPositions()
|
||||
{
|
||||
int nPredicates = getPredicateCount();
|
||||
if (nPredicates > 0)
|
||||
{
|
||||
if (null == m_proximityPositions)
|
||||
m_proximityPositions = new int[nPredicates];
|
||||
|
||||
for (int i = 0; i < nPredicates; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
initProximityPosition(i);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
// TODO: Fix this...
|
||||
throw new com.sun.org.apache.xml.internal.utils.WrappedRuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Init the proximity position to zero for a forward axes.
|
||||
*
|
||||
* @param i The index into the m_proximityPositions array.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
public void initProximityPosition(int i) throws javax.xml.transform.TransformerException
|
||||
{
|
||||
m_proximityPositions[i] = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Count forward one proximity position.
|
||||
*
|
||||
* @param i The index into the m_proximityPositions array, where the increment
|
||||
* will occur.
|
||||
*/
|
||||
protected void countProximityPosition(int i)
|
||||
{
|
||||
// Note that in the case of a UnionChildIterator, this may be a
|
||||
// static object and so m_proximityPositions may indeed be null!
|
||||
int[] pp = m_proximityPositions;
|
||||
if ((null != pp) && (i < pp.length))
|
||||
pp[i]++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells if this is a reverse axes.
|
||||
*
|
||||
* @return false, unless a derived class overrides.
|
||||
*/
|
||||
public boolean isReverseAxes()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get which predicate is executing.
|
||||
*
|
||||
* @return The current predicate index, or -1 if no predicate is executing.
|
||||
*/
|
||||
public int getPredicateIndex()
|
||||
{
|
||||
return m_predicateIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the predicates.
|
||||
*
|
||||
* @param context The current context node.
|
||||
* @param xctxt The XPath runtime context.
|
||||
*
|
||||
* @return the result of executing the predicate expressions.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
boolean executePredicates(int context, XPathContext xctxt)
|
||||
throws javax.xml.transform.TransformerException
|
||||
{
|
||||
|
||||
int nPredicates = getPredicateCount();
|
||||
// System.out.println("nPredicates: "+nPredicates);
|
||||
if (nPredicates == 0)
|
||||
return true;
|
||||
|
||||
PrefixResolver savedResolver = xctxt.getNamespaceContext();
|
||||
|
||||
try
|
||||
{
|
||||
m_predicateIndex = 0;
|
||||
xctxt.pushSubContextList(this);
|
||||
xctxt.pushNamespaceContext(m_lpi.getPrefixResolver());
|
||||
xctxt.pushCurrentNode(context);
|
||||
|
||||
for (int i = 0; i < nPredicates; i++)
|
||||
{
|
||||
// System.out.println("Executing predicate expression - waiting count: "+m_lpi.getWaitingCount());
|
||||
XObject pred = m_predicates[i].execute(xctxt);
|
||||
// System.out.println("\nBack from executing predicate expression - waiting count: "+m_lpi.getWaitingCount());
|
||||
// System.out.println("pred.getType(): "+pred.getType());
|
||||
if (XObject.CLASS_NUMBER == pred.getType())
|
||||
{
|
||||
if (DEBUG_PREDICATECOUNTING)
|
||||
{
|
||||
System.out.flush();
|
||||
System.out.println("\n===== start predicate count ========");
|
||||
System.out.println("m_predicateIndex: " + m_predicateIndex);
|
||||
// System.out.println("getProximityPosition(m_predicateIndex): "
|
||||
// + getProximityPosition(m_predicateIndex));
|
||||
System.out.println("pred.num(): " + pred.num());
|
||||
}
|
||||
|
||||
int proxPos = this.getProximityPosition(m_predicateIndex);
|
||||
int predIndex = (int) pred.num();
|
||||
if (proxPos != predIndex)
|
||||
{
|
||||
if (DEBUG_PREDICATECOUNTING)
|
||||
{
|
||||
System.out.println("\nnode context: "+nodeToString(context));
|
||||
System.out.println("index predicate is false: "+proxPos);
|
||||
System.out.println("\n===== end predicate count ========");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else if (DEBUG_PREDICATECOUNTING)
|
||||
{
|
||||
System.out.println("\nnode context: "+nodeToString(context));
|
||||
System.out.println("index predicate is true: "+proxPos);
|
||||
System.out.println("\n===== end predicate count ========");
|
||||
}
|
||||
|
||||
// If there is a proximity index that will not change during the
|
||||
// course of itteration, then we know there can be no more true
|
||||
// occurances of this predicate, so flag that we're done after
|
||||
// this.
|
||||
//
|
||||
// bugzilla 14365
|
||||
// We can't set m_foundLast = true unless we're sure that -all-
|
||||
// remaining parameters are stable, or else last() fails. Fixed so
|
||||
// only sets m_foundLast if on the last predicate
|
||||
if(m_predicates[i].isStableNumber() && i == nPredicates - 1)
|
||||
{
|
||||
m_foundLast = true;
|
||||
}
|
||||
}
|
||||
else if (!pred.bool())
|
||||
return false;
|
||||
|
||||
countProximityPosition(++m_predicateIndex);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
xctxt.popCurrentNode();
|
||||
xctxt.popNamespaceContext();
|
||||
xctxt.popSubContextList();
|
||||
m_predicateIndex = -1;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is used to fixup variables from QNames to stack frame
|
||||
* indexes at stylesheet build time.
|
||||
* @param vars List of QNames that correspond to variables. This list
|
||||
* should be searched backwards for the first qualified name that
|
||||
* corresponds to the variable reference qname. The position of the
|
||||
* QName in the vector from the start of the vector will be its position
|
||||
* in the stack frame (but variables above the globalsTop value will need
|
||||
* to be offset to the current stack frame).
|
||||
*/
|
||||
public void fixupVariables(java.util.Vector vars, int globalsSize)
|
||||
{
|
||||
super.fixupVariables(vars, globalsSize);
|
||||
|
||||
int nPredicates = getPredicateCount();
|
||||
|
||||
for (int i = 0; i < nPredicates; i++)
|
||||
{
|
||||
m_predicates[i].fixupVariables(vars, globalsSize);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Diagnostics.
|
||||
*
|
||||
* @param n Node to give diagnostic information about, or null.
|
||||
*
|
||||
* @return Informative string about the argument.
|
||||
*/
|
||||
protected String nodeToString(int n)
|
||||
{
|
||||
if(DTM.NULL != n)
|
||||
{
|
||||
DTM dtm = m_lpi.getXPathContext().getDTM(n);
|
||||
return dtm.getNodeName(n) + "{" + (n+1) + "}";
|
||||
}
|
||||
else
|
||||
{
|
||||
return "null";
|
||||
}
|
||||
}
|
||||
|
||||
//=============== NodeFilter Implementation ===============
|
||||
|
||||
/**
|
||||
* Test whether a specified node is visible in the logical view of a
|
||||
* TreeWalker or NodeIterator. This function will be called by the
|
||||
* implementation of TreeWalker and NodeIterator; it is not intended to
|
||||
* be called directly from user code.
|
||||
* @param n The node to check to see if it passes the filter or not.
|
||||
* @return a constant to determine whether the node is accepted,
|
||||
* rejected, or skipped, as defined above .
|
||||
*/
|
||||
public short acceptNode(int n)
|
||||
{
|
||||
|
||||
XPathContext xctxt = m_lpi.getXPathContext();
|
||||
|
||||
try
|
||||
{
|
||||
xctxt.pushCurrentNode(n);
|
||||
|
||||
XObject score = execute(xctxt, n);
|
||||
|
||||
// System.out.println("\n::acceptNode - score: "+score.num()+"::");
|
||||
if (score != NodeTest.SCORE_NONE)
|
||||
{
|
||||
if (getPredicateCount() > 0)
|
||||
{
|
||||
countProximityPosition(0);
|
||||
|
||||
if (!executePredicates(n, xctxt))
|
||||
return DTMIterator.FILTER_SKIP;
|
||||
}
|
||||
|
||||
return DTMIterator.FILTER_ACCEPT;
|
||||
}
|
||||
}
|
||||
catch (javax.xml.transform.TransformerException se)
|
||||
{
|
||||
|
||||
// TODO: Fix this.
|
||||
throw new RuntimeException(se.getMessage());
|
||||
}
|
||||
finally
|
||||
{
|
||||
xctxt.popCurrentNode();
|
||||
}
|
||||
|
||||
return DTMIterator.FILTER_SKIP;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the owning location path iterator.
|
||||
*
|
||||
* @return the owning location path iterator, which should not be null.
|
||||
*/
|
||||
public LocPathIterator getLocPathIterator()
|
||||
{
|
||||
return m_lpi;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the location path iterator owner for this walker. Besides
|
||||
* initialization, this function is called during cloning operations.
|
||||
*
|
||||
* @param li non-null reference to the owning location path iterator.
|
||||
*/
|
||||
public void setLocPathIterator(LocPathIterator li)
|
||||
{
|
||||
m_lpi = li;
|
||||
if(this != li)
|
||||
li.exprSetParent(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tell if this expression or it's subexpressions can traverse outside
|
||||
* the current subtree.
|
||||
*
|
||||
* @return true if traversal outside the context node's subtree can occur.
|
||||
*/
|
||||
public boolean canTraverseOutsideSubtree()
|
||||
{
|
||||
int n = getPredicateCount();
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
if(getPredicate(i).canTraverseOutsideSubtree())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This will traverse the heararchy, calling the visitor for
|
||||
* each member. If the called visitor method returns
|
||||
* false, the subtree should not be called.
|
||||
*
|
||||
* @param visitor The visitor whose appropriate method will be called.
|
||||
*/
|
||||
public void callPredicateVisitors(XPathVisitor visitor)
|
||||
{
|
||||
if (null != m_predicates)
|
||||
{
|
||||
int n = m_predicates.length;
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
ExpressionOwner predOwner = new PredOwner(i);
|
||||
if (visitor.visitPredicate(predOwner, m_predicates[i]))
|
||||
{
|
||||
m_predicates[i].callVisitors(predOwner, visitor);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Expression#deepEquals(Expression)
|
||||
*/
|
||||
public boolean deepEquals(Expression expr)
|
||||
{
|
||||
if (!super.deepEquals(expr))
|
||||
return false;
|
||||
|
||||
PredicatedNodeTest pnt = (PredicatedNodeTest) expr;
|
||||
if (null != m_predicates)
|
||||
{
|
||||
|
||||
int n = m_predicates.length;
|
||||
if ((null == pnt.m_predicates) || (pnt.m_predicates.length != n))
|
||||
return false;
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
if (!m_predicates[i].deepEquals(pnt.m_predicates[i]))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (null != pnt.m_predicates)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** This is true if nextNode returns null. */
|
||||
transient protected boolean m_foundLast = false;
|
||||
|
||||
/** The owning location path iterator.
|
||||
* @serial */
|
||||
protected LocPathIterator m_lpi;
|
||||
|
||||
/**
|
||||
* Which predicate we are executing.
|
||||
*/
|
||||
transient int m_predicateIndex = -1;
|
||||
|
||||
/** The list of predicate expressions. Is static and does not need
|
||||
* to be deep cloned.
|
||||
* @serial
|
||||
*/
|
||||
private Expression[] m_predicates;
|
||||
|
||||
/**
|
||||
* An array of counts that correspond to the number
|
||||
* of predicates the step contains.
|
||||
*/
|
||||
transient protected int[] m_proximityPositions;
|
||||
|
||||
/** If true, diagnostic messages about predicate execution will be posted. */
|
||||
static final boolean DEBUG_PREDICATECOUNTING = false;
|
||||
|
||||
class PredOwner implements ExpressionOwner
|
||||
{
|
||||
int m_index;
|
||||
|
||||
PredOwner(int index)
|
||||
{
|
||||
m_index = index;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ExpressionOwner#getExpression()
|
||||
*/
|
||||
public Expression getExpression()
|
||||
{
|
||||
return m_predicates[m_index];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see ExpressionOwner#setExpression(Expression)
|
||||
*/
|
||||
public void setExpression(Expression exp)
|
||||
{
|
||||
exp.exprSetParent(PredicatedNodeTest.this);
|
||||
m_predicates[m_index] = exp;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This class implements an RTF Iterator. Currently exists for sole
|
||||
* purpose of enabling EXSLT object-type function to return "RTF".
|
||||
*
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
package com.sun.org.apache.xpath.internal.axes;
|
||||
|
||||
import com.sun.org.apache.xml.internal.dtm.DTMManager;
|
||||
import com.sun.org.apache.xpath.internal.NodeSetDTM;
|
||||
|
||||
public class RTFIterator extends NodeSetDTM {
|
||||
static final long serialVersionUID = 7658117366258528996L;
|
||||
|
||||
/**
|
||||
* Constructor for RTFIterator
|
||||
*/
|
||||
public RTFIterator(int root, DTMManager manager) {
|
||||
super(root, manager);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,248 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.axes;
|
||||
|
||||
import com.sun.org.apache.xml.internal.dtm.DTM;
|
||||
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
|
||||
import com.sun.org.apache.xpath.internal.XPathContext;
|
||||
|
||||
/**
|
||||
* Walker for a reverse axes.
|
||||
* @see <a href="http://www.w3.org/TR/xpath#predicates">XPath 2.4 Predicates</a>
|
||||
*/
|
||||
public class ReverseAxesWalker extends AxesWalker
|
||||
{
|
||||
static final long serialVersionUID = 2847007647832768941L;
|
||||
|
||||
/**
|
||||
* Construct an AxesWalker using a LocPathIterator.
|
||||
*
|
||||
* @param locPathIterator The location path iterator that 'owns' this walker.
|
||||
*/
|
||||
ReverseAxesWalker(LocPathIterator locPathIterator, int axis)
|
||||
{
|
||||
super(locPathIterator, axis);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the root node of the TreeWalker.
|
||||
* (Not part of the DOM2 TreeWalker interface).
|
||||
*
|
||||
* @param root The context node of this step.
|
||||
*/
|
||||
public void setRoot(int root)
|
||||
{
|
||||
super.setRoot(root);
|
||||
m_iterator = getDTM(root).getAxisIterator(m_axis);
|
||||
m_iterator.setStartNode(root);
|
||||
}
|
||||
|
||||
/**
|
||||
* Detaches the walker from the set which it iterated over, releasing
|
||||
* any computational resources and placing the iterator in the INVALID
|
||||
* state.
|
||||
*/
|
||||
public void detach()
|
||||
{
|
||||
m_iterator = null;
|
||||
super.detach();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next node in document order on the axes.
|
||||
*
|
||||
* @return the next node in document order on the axes, or null.
|
||||
*/
|
||||
protected int getNextNode()
|
||||
{
|
||||
if (m_foundLast)
|
||||
return DTM.NULL;
|
||||
|
||||
int next = m_iterator.next();
|
||||
|
||||
if (m_isFresh)
|
||||
m_isFresh = false;
|
||||
|
||||
if (DTM.NULL == next)
|
||||
this.m_foundLast = true;
|
||||
|
||||
return next;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tells if this is a reverse axes. Overrides AxesWalker#isReverseAxes.
|
||||
*
|
||||
* @return true for this class.
|
||||
*/
|
||||
public boolean isReverseAxes()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Set the root node of the TreeWalker.
|
||||
// *
|
||||
// * @param root The context node of this step.
|
||||
// */
|
||||
// public void setRoot(int root)
|
||||
// {
|
||||
// super.setRoot(root);
|
||||
// }
|
||||
|
||||
/**
|
||||
* Get the current sub-context position. In order to do the
|
||||
* reverse axes count, for the moment this re-searches the axes
|
||||
* up to the predicate. An optimization on this is to cache
|
||||
* the nodes searched, but, for the moment, this case is probably
|
||||
* rare enough that the added complexity isn't worth it.
|
||||
*
|
||||
* @param predicateIndex The predicate index of the proximity position.
|
||||
*
|
||||
* @return The pridicate index, or -1.
|
||||
*/
|
||||
protected int getProximityPosition(int predicateIndex)
|
||||
{
|
||||
// A negative predicate index seems to occur with
|
||||
// (preceding-sibling::*|following-sibling::*)/ancestor::*[position()]/*[position()]
|
||||
// -sb
|
||||
if(predicateIndex < 0)
|
||||
return -1;
|
||||
|
||||
int count = m_proximityPositions[predicateIndex];
|
||||
|
||||
if (count <= 0)
|
||||
{
|
||||
AxesWalker savedWalker = wi().getLastUsedWalker();
|
||||
|
||||
try
|
||||
{
|
||||
ReverseAxesWalker clone = (ReverseAxesWalker) this.clone();
|
||||
|
||||
clone.setRoot(this.getRoot());
|
||||
|
||||
clone.setPredicateCount(predicateIndex);
|
||||
|
||||
clone.setPrevWalker(null);
|
||||
clone.setNextWalker(null);
|
||||
wi().setLastUsedWalker(clone);
|
||||
|
||||
// Count 'em all
|
||||
count++;
|
||||
int next;
|
||||
|
||||
while (DTM.NULL != (next = clone.nextNode()))
|
||||
{
|
||||
count++;
|
||||
}
|
||||
|
||||
m_proximityPositions[predicateIndex] = count;
|
||||
}
|
||||
catch (CloneNotSupportedException cnse)
|
||||
{
|
||||
|
||||
// can't happen
|
||||
}
|
||||
finally
|
||||
{
|
||||
wi().setLastUsedWalker(savedWalker);
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Count backwards one proximity position.
|
||||
*
|
||||
* @param i The predicate index.
|
||||
*/
|
||||
protected void countProximityPosition(int i)
|
||||
{
|
||||
if (i < m_proximityPositions.length)
|
||||
m_proximityPositions[i]--;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of nodes in this node list. The function is probably ill
|
||||
* named?
|
||||
*
|
||||
*
|
||||
* @param xctxt The XPath runtime context.
|
||||
*
|
||||
* @return the number of nodes in this node list.
|
||||
*/
|
||||
public int getLastPos(XPathContext xctxt)
|
||||
{
|
||||
|
||||
int count = 0;
|
||||
AxesWalker savedWalker = wi().getLastUsedWalker();
|
||||
|
||||
try
|
||||
{
|
||||
ReverseAxesWalker clone = (ReverseAxesWalker) this.clone();
|
||||
|
||||
clone.setRoot(this.getRoot());
|
||||
|
||||
clone.setPredicateCount(this.getPredicateCount() - 1);
|
||||
|
||||
clone.setPrevWalker(null);
|
||||
clone.setNextWalker(null);
|
||||
wi().setLastUsedWalker(clone);
|
||||
|
||||
// Count 'em all
|
||||
// count = 1;
|
||||
int next;
|
||||
|
||||
while (DTM.NULL != (next = clone.nextNode()))
|
||||
{
|
||||
count++;
|
||||
}
|
||||
}
|
||||
catch (CloneNotSupportedException cnse)
|
||||
{
|
||||
|
||||
// can't happen
|
||||
}
|
||||
finally
|
||||
{
|
||||
wi().setLastUsedWalker(savedWalker);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if all the nodes in the iteration well be returned in document
|
||||
* order.
|
||||
* Warning: This can only be called after setRoot has been called!
|
||||
*
|
||||
* @return false.
|
||||
*/
|
||||
public boolean isDocOrdered()
|
||||
{
|
||||
return false; // I think.
|
||||
}
|
||||
|
||||
/** The DTM inner traversal class, that corresponds to the super axis. */
|
||||
protected DTMAxisIterator m_iterator;
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.axes;
|
||||
|
||||
import com.sun.org.apache.xml.internal.dtm.DTM;
|
||||
import com.sun.org.apache.xpath.internal.XPathContext;
|
||||
import com.sun.org.apache.xpath.internal.compiler.Compiler;
|
||||
|
||||
/**
|
||||
* This class implements an optimized iterator for
|
||||
* "." patterns, that is, the self axes without any predicates.
|
||||
* @see com.sun.org.apache.xpath.internal.axes.LocPathIterator
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public class SelfIteratorNoPredicate extends LocPathIterator
|
||||
{
|
||||
static final long serialVersionUID = -4226887905279814201L;
|
||||
|
||||
/**
|
||||
* Create a SelfIteratorNoPredicate object.
|
||||
*
|
||||
* @param compiler A reference to the Compiler that contains the op map.
|
||||
* @param opPos The position within the op map, which contains the
|
||||
* location path expression for this itterator.
|
||||
* @param analysis Analysis bits.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
SelfIteratorNoPredicate(Compiler compiler, int opPos, int analysis)
|
||||
throws javax.xml.transform.TransformerException
|
||||
{
|
||||
super(compiler, opPos, analysis, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a SelfIteratorNoPredicate object.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
public SelfIteratorNoPredicate()
|
||||
throws javax.xml.transform.TransformerException
|
||||
{
|
||||
super(null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the next node in the set and advances the position of the
|
||||
* iterator in the set. After a NodeIterator is created, the first call
|
||||
* to nextNode() returns the first node in the set.
|
||||
*
|
||||
* @return The next <code>Node</code> in the set being iterated over, or
|
||||
* <code>null</code> if there are no more members in that set.
|
||||
*/
|
||||
public int nextNode()
|
||||
{
|
||||
if (m_foundLast)
|
||||
return DTM.NULL;
|
||||
|
||||
int next;
|
||||
DTM dtm = m_cdtm;
|
||||
|
||||
m_lastFetched = next = (DTM.NULL == m_lastFetched)
|
||||
? m_context
|
||||
: DTM.NULL;
|
||||
|
||||
// m_lastFetched = next;
|
||||
if (DTM.NULL != next)
|
||||
{
|
||||
m_pos++;
|
||||
|
||||
return next;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_foundLast = true;
|
||||
|
||||
return DTM.NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the first node out of the nodeset, if this expression is
|
||||
* a nodeset expression. This is the default implementation for
|
||||
* nodesets. Derived classes should try and override this and return a
|
||||
* value without having to do a clone operation.
|
||||
* @param xctxt The XPath runtime context.
|
||||
* @return the first node out of the nodeset, or DTM.NULL.
|
||||
*/
|
||||
public int asNode(XPathContext xctxt)
|
||||
throws javax.xml.transform.TransformerException
|
||||
{
|
||||
return xctxt.getCurrentNode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the index of the last node that can be itterated to.
|
||||
* This probably will need to be overridded by derived classes.
|
||||
*
|
||||
* @param xctxt XPath runtime context.
|
||||
*
|
||||
* @return the index of the last node that can be itterated to.
|
||||
*/
|
||||
public int getLastPos(XPathContext xctxt)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.axes;
|
||||
|
||||
import com.sun.org.apache.xpath.internal.XPathContext;
|
||||
|
||||
/**
|
||||
* A class that implements this interface is a sub context node list, meaning it
|
||||
* is a node list for a location path step for a predicate.
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public interface SubContextList
|
||||
{
|
||||
|
||||
/**
|
||||
* Get the number of nodes in the node list, which, in the XSLT 1 based
|
||||
* counting system, is the last index position.
|
||||
*
|
||||
*
|
||||
* @param xctxt The XPath runtime context.
|
||||
*
|
||||
* @return the number of nodes in the node list.
|
||||
*/
|
||||
public int getLastPos(XPathContext xctxt);
|
||||
|
||||
/**
|
||||
* Get the current sub-context position.
|
||||
*
|
||||
* @param xctxt The XPath runtime context.
|
||||
*
|
||||
* @return The position of the current node in the list.
|
||||
*/
|
||||
public int getProximityPosition(XPathContext xctxt);
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.axes;
|
||||
|
||||
import com.sun.org.apache.xml.internal.dtm.DTMIterator;
|
||||
import com.sun.org.apache.xpath.internal.XPathContext;
|
||||
import com.sun.org.apache.xpath.internal.objects.XObject;
|
||||
import com.sun.org.apache.xpath.internal.patterns.NodeTest;
|
||||
|
||||
/**
|
||||
* This class defines a simplified type of union iterator that only
|
||||
* tests along the child axes. If the conditions are right, it is
|
||||
* much faster than using a UnionPathIterator.
|
||||
*/
|
||||
public class UnionChildIterator extends ChildTestIterator
|
||||
{
|
||||
static final long serialVersionUID = 3500298482193003495L;
|
||||
/**
|
||||
* Even though these may hold full LocPathIterators, this array does
|
||||
* not have to be cloned, since only the node test and predicate
|
||||
* portion are used, and these only need static information. However,
|
||||
* also note that index predicates can not be used!
|
||||
*/
|
||||
private PredicatedNodeTest[] m_nodeTests = null;
|
||||
|
||||
/**
|
||||
* Constructor for UnionChildIterator
|
||||
*/
|
||||
public UnionChildIterator()
|
||||
{
|
||||
super(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a node test to the union list.
|
||||
*
|
||||
* @param test reference to a NodeTest, which will be added
|
||||
* directly to the list of node tests (in other words, it will
|
||||
* not be cloned). The parent of this test will be set to
|
||||
* this object.
|
||||
*/
|
||||
public void addNodeTest(PredicatedNodeTest test)
|
||||
{
|
||||
|
||||
// Increase array size by only 1 at a time. Fix this
|
||||
// if it looks to be a problem.
|
||||
if (null == m_nodeTests)
|
||||
{
|
||||
m_nodeTests = new PredicatedNodeTest[1];
|
||||
m_nodeTests[0] = test;
|
||||
}
|
||||
else
|
||||
{
|
||||
PredicatedNodeTest[] tests = m_nodeTests;
|
||||
int len = m_nodeTests.length;
|
||||
|
||||
m_nodeTests = new PredicatedNodeTest[len + 1];
|
||||
|
||||
System.arraycopy(tests, 0, m_nodeTests, 0, len);
|
||||
|
||||
m_nodeTests[len] = test;
|
||||
}
|
||||
test.exprSetParent(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is used to fixup variables from QNames to stack frame
|
||||
* indexes at stylesheet build time.
|
||||
* @param vars List of QNames that correspond to variables. This list
|
||||
* should be searched backwards for the first qualified name that
|
||||
* corresponds to the variable reference qname. The position of the
|
||||
* QName in the vector from the start of the vector will be its position
|
||||
* in the stack frame (but variables above the globalsTop value will need
|
||||
* to be offset to the current stack frame).
|
||||
*/
|
||||
public void fixupVariables(java.util.Vector vars, int globalsSize)
|
||||
{
|
||||
super.fixupVariables(vars, globalsSize);
|
||||
if (m_nodeTests != null) {
|
||||
for (int i = 0; i < m_nodeTests.length; i++) {
|
||||
m_nodeTests[i].fixupVariables(vars, globalsSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether a specified node is visible in the logical view of a
|
||||
* TreeWalker or NodeIterator. This function will be called by the
|
||||
* implementation of TreeWalker and NodeIterator; it is not intended to
|
||||
* be called directly from user code.
|
||||
* @param n The node to check to see if it passes the filter or not.
|
||||
* @return a constant to determine whether the node is accepted,
|
||||
* rejected, or skipped, as defined above .
|
||||
*/
|
||||
public short acceptNode(int n)
|
||||
{
|
||||
XPathContext xctxt = getXPathContext();
|
||||
try
|
||||
{
|
||||
xctxt.pushCurrentNode(n);
|
||||
for (int i = 0; i < m_nodeTests.length; i++)
|
||||
{
|
||||
PredicatedNodeTest pnt = m_nodeTests[i];
|
||||
XObject score = pnt.execute(xctxt, n);
|
||||
if (score != NodeTest.SCORE_NONE)
|
||||
{
|
||||
// Note that we are assuming there are no positional predicates!
|
||||
if (pnt.getPredicateCount() > 0)
|
||||
{
|
||||
if (pnt.executePredicates(n, xctxt))
|
||||
return DTMIterator.FILTER_ACCEPT;
|
||||
}
|
||||
else
|
||||
return DTMIterator.FILTER_ACCEPT;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (javax.xml.transform.TransformerException se)
|
||||
{
|
||||
|
||||
// TODO: Fix this.
|
||||
throw new RuntimeException(se.getMessage());
|
||||
}
|
||||
finally
|
||||
{
|
||||
xctxt.popCurrentNode();
|
||||
}
|
||||
return DTMIterator.FILTER_SKIP;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,585 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.axes;
|
||||
|
||||
import com.sun.org.apache.xml.internal.dtm.Axis;
|
||||
import com.sun.org.apache.xml.internal.dtm.DTM;
|
||||
import com.sun.org.apache.xml.internal.dtm.DTMIterator;
|
||||
import com.sun.org.apache.xpath.internal.Expression;
|
||||
import com.sun.org.apache.xpath.internal.ExpressionOwner;
|
||||
import com.sun.org.apache.xpath.internal.XPathVisitor;
|
||||
import com.sun.org.apache.xpath.internal.compiler.Compiler;
|
||||
import com.sun.org.apache.xpath.internal.compiler.OpCodes;
|
||||
import com.sun.org.apache.xpath.internal.compiler.OpMap;
|
||||
|
||||
/**
|
||||
* This class extends NodeSetDTM, which implements DTMIterator,
|
||||
* and fetches nodes one at a time in document order based on a XPath
|
||||
* <a href="http://www.w3.org/TR/xpath#NT-UnionExpr">UnionExpr</a>.
|
||||
* As each node is iterated via nextNode(), the node is also stored
|
||||
* in the NodeVector, so that previousNode() can easily be done.
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public class UnionPathIterator extends LocPathIterator
|
||||
implements Cloneable, DTMIterator, java.io.Serializable, PathComponent
|
||||
{
|
||||
static final long serialVersionUID = -3910351546843826781L;
|
||||
|
||||
/**
|
||||
* Constructor to create an instance which you can add location paths to.
|
||||
*/
|
||||
public UnionPathIterator()
|
||||
{
|
||||
|
||||
super();
|
||||
|
||||
// m_mutable = false;
|
||||
// m_cacheNodes = false;
|
||||
m_iterators = null;
|
||||
m_exprs = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the context values for this expression
|
||||
* after it is cloned.
|
||||
*
|
||||
* @param context The XPath runtime context for this
|
||||
* transformation.
|
||||
*/
|
||||
public void setRoot(int context, Object environment)
|
||||
{
|
||||
super.setRoot(context, environment);
|
||||
|
||||
try
|
||||
{
|
||||
if (null != m_exprs)
|
||||
{
|
||||
int n = m_exprs.length;
|
||||
DTMIterator newIters[] = new DTMIterator[n];
|
||||
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
DTMIterator iter = m_exprs[i].asIterator(m_execContext, context);
|
||||
newIters[i] = iter;
|
||||
iter.nextNode();
|
||||
}
|
||||
m_iterators = newIters;
|
||||
}
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
throw new com.sun.org.apache.xml.internal.utils.WrappedRuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an iterator to the union list.
|
||||
*
|
||||
* @param expr non-null reference to a location path iterator.
|
||||
*/
|
||||
public void addIterator(DTMIterator expr)
|
||||
{
|
||||
|
||||
// Increase array size by only 1 at a time. Fix this
|
||||
// if it looks to be a problem.
|
||||
if (null == m_iterators)
|
||||
{
|
||||
m_iterators = new DTMIterator[1];
|
||||
m_iterators[0] = expr;
|
||||
}
|
||||
else
|
||||
{
|
||||
DTMIterator[] exprs = m_iterators;
|
||||
int len = m_iterators.length;
|
||||
|
||||
m_iterators = new DTMIterator[len + 1];
|
||||
|
||||
System.arraycopy(exprs, 0, m_iterators, 0, len);
|
||||
|
||||
m_iterators[len] = expr;
|
||||
}
|
||||
expr.nextNode();
|
||||
if(expr instanceof Expression)
|
||||
((Expression)expr).exprSetParent(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Detaches the iterator from the set which it iterated over, releasing
|
||||
* any computational resources and placing the iterator in the INVALID
|
||||
* state. After<code>detach</code> has been invoked, calls to
|
||||
* <code>nextNode</code> or<code>previousNode</code> will raise the
|
||||
* exception INVALID_STATE_ERR.
|
||||
*/
|
||||
public void detach()
|
||||
{
|
||||
if(m_allowDetach && null != m_iterators){
|
||||
int n = m_iterators.length;
|
||||
for(int i = 0; i < n; i++)
|
||||
{
|
||||
m_iterators[i].detach();
|
||||
}
|
||||
m_iterators = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a UnionPathIterator object, including creation
|
||||
* of location path iterators from the opcode list, and call back
|
||||
* into the Compiler to create predicate expressions.
|
||||
*
|
||||
* @param compiler The Compiler which is creating
|
||||
* this expression.
|
||||
* @param opPos The position of this iterator in the
|
||||
* opcode list from the compiler.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
public UnionPathIterator(Compiler compiler, int opPos)
|
||||
throws javax.xml.transform.TransformerException
|
||||
{
|
||||
|
||||
super();
|
||||
|
||||
opPos = OpMap.getFirstChildPos(opPos);
|
||||
|
||||
loadLocationPaths(compiler, opPos, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* This will return an iterator capable of handling the union of paths given.
|
||||
*
|
||||
* @param compiler The Compiler which is creating
|
||||
* this expression.
|
||||
* @param opPos The position of this iterator in the
|
||||
* opcode list from the compiler.
|
||||
*
|
||||
* @return Object that is derived from LocPathIterator.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
public static LocPathIterator createUnionIterator(Compiler compiler, int opPos)
|
||||
throws javax.xml.transform.TransformerException
|
||||
{
|
||||
// For the moment, I'm going to first create a full UnionPathIterator, and
|
||||
// then see if I can reduce it to a UnionChildIterator. It would obviously
|
||||
// be more effecient to just test for the conditions for a UnionChildIterator,
|
||||
// and then create that directly.
|
||||
UnionPathIterator upi = new UnionPathIterator(compiler, opPos);
|
||||
int nPaths = upi.m_exprs.length;
|
||||
boolean isAllChildIterators = true;
|
||||
for(int i = 0; i < nPaths; i++)
|
||||
{
|
||||
LocPathIterator lpi = upi.m_exprs[i];
|
||||
|
||||
if(lpi.getAxis() != Axis.CHILD)
|
||||
{
|
||||
isAllChildIterators = false;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// check for positional predicates or position function, which won't work.
|
||||
if(HasPositionalPredChecker.check(lpi))
|
||||
{
|
||||
isAllChildIterators = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(isAllChildIterators)
|
||||
{
|
||||
UnionChildIterator uci = new UnionChildIterator();
|
||||
|
||||
for(int i = 0; i < nPaths; i++)
|
||||
{
|
||||
PredicatedNodeTest lpi = upi.m_exprs[i];
|
||||
// I could strip the lpi down to a pure PredicatedNodeTest, but
|
||||
// I don't think it's worth it. Note that the test can be used
|
||||
// as a static object... so it doesn't have to be cloned.
|
||||
uci.addNodeTest(lpi);
|
||||
}
|
||||
return uci;
|
||||
|
||||
}
|
||||
else
|
||||
return upi;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the analysis bits for this walker, as defined in the WalkerFactory.
|
||||
* @return One of WalkerFactory#BIT_DESCENDANT, etc.
|
||||
*/
|
||||
public int getAnalysisBits()
|
||||
{
|
||||
int bits = 0;
|
||||
|
||||
if (m_exprs != null)
|
||||
{
|
||||
int n = m_exprs.length;
|
||||
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
int bit = m_exprs[i].getAnalysisBits();
|
||||
bits |= bit;
|
||||
}
|
||||
}
|
||||
|
||||
return bits;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the object from a serialization stream.
|
||||
*
|
||||
* @param stream Input stream to read from
|
||||
*
|
||||
* @throws java.io.IOException
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
private void readObject(java.io.ObjectInputStream stream)
|
||||
throws java.io.IOException, javax.xml.transform.TransformerException
|
||||
{
|
||||
try
|
||||
{
|
||||
stream.defaultReadObject();
|
||||
m_clones = new IteratorPool(this);
|
||||
}
|
||||
catch (ClassNotFoundException cnfe)
|
||||
{
|
||||
throw new javax.xml.transform.TransformerException(cnfe);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a cloned LocPathIterator that holds the same
|
||||
* position as this iterator.
|
||||
*
|
||||
* @return A clone of this iterator that holds the same node position.
|
||||
*
|
||||
* @throws CloneNotSupportedException
|
||||
*/
|
||||
public Object clone() throws CloneNotSupportedException
|
||||
{
|
||||
|
||||
UnionPathIterator clone = (UnionPathIterator) super.clone();
|
||||
if (m_iterators != null)
|
||||
{
|
||||
int n = m_iterators.length;
|
||||
|
||||
clone.m_iterators = new DTMIterator[n];
|
||||
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
clone.m_iterators[i] = (DTMIterator)m_iterators[i].clone();
|
||||
}
|
||||
}
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a new location path iterator.
|
||||
*
|
||||
* @param compiler The Compiler which is creating
|
||||
* this expression.
|
||||
* @param opPos The position of this iterator in the
|
||||
*
|
||||
* @return New location path iterator.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
protected LocPathIterator createDTMIterator(
|
||||
Compiler compiler, int opPos) throws javax.xml.transform.TransformerException
|
||||
{
|
||||
LocPathIterator lpi = (LocPathIterator)WalkerFactory.newDTMIterator(compiler, opPos,
|
||||
(compiler.getLocationPathDepth() <= 0));
|
||||
return lpi;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the location path iterators. Recursive.
|
||||
*
|
||||
* @param compiler The Compiler which is creating
|
||||
* this expression.
|
||||
* @param opPos The position of this iterator in the
|
||||
* opcode list from the compiler.
|
||||
* @param count The insert position of the iterator.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
protected void loadLocationPaths(Compiler compiler, int opPos, int count)
|
||||
throws javax.xml.transform.TransformerException
|
||||
{
|
||||
|
||||
// TODO: Handle unwrapped FilterExpr
|
||||
int steptype = compiler.getOp(opPos);
|
||||
|
||||
if (steptype == OpCodes.OP_LOCATIONPATH)
|
||||
{
|
||||
loadLocationPaths(compiler, compiler.getNextOpPos(opPos), count + 1);
|
||||
|
||||
m_exprs[count] = createDTMIterator(compiler, opPos);
|
||||
m_exprs[count].exprSetParent(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// Have to check for unwrapped functions, which the LocPathIterator
|
||||
// doesn't handle.
|
||||
switch (steptype)
|
||||
{
|
||||
case OpCodes.OP_VARIABLE :
|
||||
case OpCodes.OP_EXTFUNCTION :
|
||||
case OpCodes.OP_FUNCTION :
|
||||
case OpCodes.OP_GROUP :
|
||||
loadLocationPaths(compiler, compiler.getNextOpPos(opPos), count + 1);
|
||||
|
||||
WalkingIterator iter =
|
||||
new WalkingIterator(compiler.getNamespaceContext());
|
||||
iter.exprSetParent(this);
|
||||
|
||||
if(compiler.getLocationPathDepth() <= 0)
|
||||
iter.setIsTopLevel(true);
|
||||
|
||||
iter.m_firstWalker = new com.sun.org.apache.xpath.internal.axes.FilterExprWalker(iter);
|
||||
|
||||
iter.m_firstWalker.init(compiler, opPos, steptype);
|
||||
|
||||
m_exprs[count] = iter;
|
||||
break;
|
||||
default :
|
||||
m_exprs = new LocPathIterator[count];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the next node in the set and advances the position of the
|
||||
* iterator in the set. After a DTMIterator is created, the first call
|
||||
* to nextNode() returns the first node in the set.
|
||||
* @return The next <code>Node</code> in the set being iterated over, or
|
||||
* <code>null</code> if there are no more members in that set.
|
||||
*/
|
||||
public int nextNode()
|
||||
{
|
||||
if(m_foundLast)
|
||||
return DTM.NULL;
|
||||
|
||||
// Loop through the iterators getting the current fetched
|
||||
// node, and get the earliest occuring in document order
|
||||
int earliestNode = DTM.NULL;
|
||||
|
||||
if (null != m_iterators)
|
||||
{
|
||||
int n = m_iterators.length;
|
||||
int iteratorUsed = -1;
|
||||
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
int node = m_iterators[i].getCurrentNode();
|
||||
|
||||
if (DTM.NULL == node)
|
||||
continue;
|
||||
else if (DTM.NULL == earliestNode)
|
||||
{
|
||||
iteratorUsed = i;
|
||||
earliestNode = node;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (node == earliestNode)
|
||||
{
|
||||
|
||||
// Found a duplicate, so skip past it.
|
||||
m_iterators[i].nextNode();
|
||||
}
|
||||
else
|
||||
{
|
||||
DTM dtm = getDTM(node);
|
||||
|
||||
if (dtm.isNodeAfter(node, earliestNode))
|
||||
{
|
||||
iteratorUsed = i;
|
||||
earliestNode = node;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (DTM.NULL != earliestNode)
|
||||
{
|
||||
m_iterators[iteratorUsed].nextNode();
|
||||
|
||||
incrementCurrentPos();
|
||||
}
|
||||
else
|
||||
m_foundLast = true;
|
||||
}
|
||||
|
||||
m_lastFetched = earliestNode;
|
||||
|
||||
return earliestNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is used to fixup variables from QNames to stack frame
|
||||
* indexes at stylesheet build time.
|
||||
* @param vars List of QNames that correspond to variables. This list
|
||||
* should be searched backwards for the first qualified name that
|
||||
* corresponds to the variable reference qname. The position of the
|
||||
* QName in the vector from the start of the vector will be its position
|
||||
* in the stack frame (but variables above the globalsTop value will need
|
||||
* to be offset to the current stack frame).
|
||||
*/
|
||||
public void fixupVariables(java.util.Vector vars, int globalsSize)
|
||||
{
|
||||
for (int i = 0; i < m_exprs.length; i++)
|
||||
{
|
||||
m_exprs[i].fixupVariables(vars, globalsSize);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The location path iterators, one for each
|
||||
* <a href="http://www.w3.org/TR/xpath#NT-LocationPath">location
|
||||
* path</a> contained in the union expression.
|
||||
* @serial
|
||||
*/
|
||||
protected LocPathIterator[] m_exprs;
|
||||
|
||||
|
||||
/**
|
||||
* The location path iterators, one for each
|
||||
* <a href="http://www.w3.org/TR/xpath#NT-LocationPath">location
|
||||
* path</a> contained in the union expression.
|
||||
* @serial
|
||||
*/
|
||||
protected DTMIterator[] m_iterators;
|
||||
|
||||
/**
|
||||
* Returns the axis being iterated, if it is known.
|
||||
*
|
||||
* @return Axis.CHILD, etc., or -1 if the axis is not known or is of multiple
|
||||
* types.
|
||||
*/
|
||||
public int getAxis()
|
||||
{
|
||||
// Could be smarter.
|
||||
return -1;
|
||||
}
|
||||
|
||||
class iterOwner implements ExpressionOwner
|
||||
{
|
||||
int m_index;
|
||||
|
||||
iterOwner(int index)
|
||||
{
|
||||
m_index = index;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ExpressionOwner#getExpression()
|
||||
*/
|
||||
public Expression getExpression()
|
||||
{
|
||||
return m_exprs[m_index];
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ExpressionOwner#setExpression(Expression)
|
||||
*/
|
||||
public void setExpression(Expression exp)
|
||||
{
|
||||
|
||||
if(!(exp instanceof LocPathIterator))
|
||||
{
|
||||
// Yuck. Need FilterExprIter. Or make it so m_exprs can be just
|
||||
// plain expressions?
|
||||
WalkingIterator wi = new WalkingIterator(getPrefixResolver());
|
||||
FilterExprWalker few = new FilterExprWalker(wi);
|
||||
wi.setFirstWalker(few);
|
||||
few.setInnerExpression(exp);
|
||||
wi.exprSetParent(UnionPathIterator.this);
|
||||
few.exprSetParent(wi);
|
||||
exp.exprSetParent(few);
|
||||
exp = wi;
|
||||
}
|
||||
else
|
||||
exp.exprSetParent(UnionPathIterator.this);
|
||||
m_exprs[m_index] = (LocPathIterator)exp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.sun.org.apache.xpath.internal.XPathVisitable#callVisitors(ExpressionOwner, XPathVisitor)
|
||||
*/
|
||||
public void callVisitors(ExpressionOwner owner, XPathVisitor visitor)
|
||||
{
|
||||
if(visitor.visitUnionPath(owner, this))
|
||||
{
|
||||
if(null != m_exprs)
|
||||
{
|
||||
int n = m_exprs.length;
|
||||
for(int i = 0; i < n; i++)
|
||||
{
|
||||
m_exprs[i].callVisitors(new iterOwner(i), visitor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Expression#deepEquals(Expression)
|
||||
*/
|
||||
public boolean deepEquals(Expression expr)
|
||||
{
|
||||
if (!super.deepEquals(expr))
|
||||
return false;
|
||||
|
||||
UnionPathIterator upi = (UnionPathIterator) expr;
|
||||
|
||||
if (null != m_exprs)
|
||||
{
|
||||
int n = m_exprs.length;
|
||||
|
||||
if((null == upi.m_exprs) || (upi.m_exprs.length != n))
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
if(!m_exprs[i].deepEquals(upi.m_exprs[i]))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (null != upi.m_exprs)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,364 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.axes;
|
||||
|
||||
import com.sun.org.apache.xml.internal.dtm.DTM;
|
||||
import com.sun.org.apache.xml.internal.utils.PrefixResolver;
|
||||
import com.sun.org.apache.xpath.internal.Expression;
|
||||
import com.sun.org.apache.xpath.internal.ExpressionOwner;
|
||||
import com.sun.org.apache.xpath.internal.VariableStack;
|
||||
import com.sun.org.apache.xpath.internal.XPathVisitor;
|
||||
import com.sun.org.apache.xpath.internal.compiler.Compiler;
|
||||
import com.sun.org.apache.xpath.internal.compiler.OpMap;
|
||||
|
||||
/**
|
||||
* Location path iterator that uses Walkers.
|
||||
*/
|
||||
|
||||
public class WalkingIterator extends LocPathIterator implements ExpressionOwner
|
||||
{
|
||||
static final long serialVersionUID = 9110225941815665906L;
|
||||
/**
|
||||
* Create a WalkingIterator iterator, including creation
|
||||
* of step walkers from the opcode list, and call back
|
||||
* into the Compiler to create predicate expressions.
|
||||
*
|
||||
* @param compiler The Compiler which is creating
|
||||
* this expression.
|
||||
* @param opPos The position of this iterator in the
|
||||
* opcode list from the compiler.
|
||||
* @param shouldLoadWalkers True if walkers should be
|
||||
* loaded, or false if this is a derived iterator and
|
||||
* it doesn't wish to load child walkers.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
WalkingIterator(
|
||||
Compiler compiler, int opPos, int analysis, boolean shouldLoadWalkers)
|
||||
throws javax.xml.transform.TransformerException
|
||||
{
|
||||
super(compiler, opPos, analysis, shouldLoadWalkers);
|
||||
|
||||
int firstStepPos = OpMap.getFirstChildPos(opPos);
|
||||
|
||||
if (shouldLoadWalkers)
|
||||
{
|
||||
m_firstWalker = WalkerFactory.loadWalkers(this, compiler, firstStepPos, 0);
|
||||
m_lastUsedWalker = m_firstWalker;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a WalkingIterator object.
|
||||
*
|
||||
* @param nscontext The namespace context for this iterator,
|
||||
* should be OK if null.
|
||||
*/
|
||||
public WalkingIterator(PrefixResolver nscontext)
|
||||
{
|
||||
|
||||
super(nscontext);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the analysis bits for this walker, as defined in the WalkerFactory.
|
||||
* @return One of WalkerFactory#BIT_DESCENDANT, etc.
|
||||
*/
|
||||
public int getAnalysisBits()
|
||||
{
|
||||
int bits = 0;
|
||||
if (null != m_firstWalker)
|
||||
{
|
||||
AxesWalker walker = m_firstWalker;
|
||||
|
||||
while (null != walker)
|
||||
{
|
||||
int bit = walker.getAnalysisBits();
|
||||
bits |= bit;
|
||||
walker = walker.getNextWalker();
|
||||
}
|
||||
}
|
||||
return bits;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a cloned WalkingIterator that holds the same
|
||||
* position as this iterator.
|
||||
*
|
||||
* @return A clone of this iterator that holds the same node position.
|
||||
*
|
||||
* @throws CloneNotSupportedException
|
||||
*/
|
||||
public Object clone() throws CloneNotSupportedException
|
||||
{
|
||||
|
||||
WalkingIterator clone = (WalkingIterator) super.clone();
|
||||
|
||||
// clone.m_varStackPos = this.m_varStackPos;
|
||||
// clone.m_varStackContext = this.m_varStackContext;
|
||||
if (null != m_firstWalker)
|
||||
{
|
||||
clone.m_firstWalker = m_firstWalker.cloneDeep(clone, null);
|
||||
}
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the iterator.
|
||||
*/
|
||||
public void reset()
|
||||
{
|
||||
|
||||
super.reset();
|
||||
|
||||
if (null != m_firstWalker)
|
||||
{
|
||||
m_lastUsedWalker = m_firstWalker;
|
||||
|
||||
m_firstWalker.setRoot(m_context);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the context values for this expression
|
||||
* after it is cloned.
|
||||
*
|
||||
* @param context The XPath runtime context for this
|
||||
* transformation.
|
||||
*/
|
||||
public void setRoot(int context, Object environment)
|
||||
{
|
||||
|
||||
super.setRoot(context, environment);
|
||||
|
||||
if(null != m_firstWalker)
|
||||
{
|
||||
m_firstWalker.setRoot(context);
|
||||
m_lastUsedWalker = m_firstWalker;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the next node in the set and advances the position of the
|
||||
* iterator in the set. After a NodeIterator is created, the first call
|
||||
* to nextNode() returns the first node in the set.
|
||||
* @return The next <code>Node</code> in the set being iterated over, or
|
||||
* <code>null</code> if there are no more members in that set.
|
||||
*/
|
||||
public int nextNode()
|
||||
{
|
||||
if(m_foundLast)
|
||||
return DTM.NULL;
|
||||
|
||||
// If the variable stack position is not -1, we'll have to
|
||||
// set our position in the variable stack, so our variable access
|
||||
// will be correct. Iterators that are at the top level of the
|
||||
// expression need to reset the variable stack, while iterators
|
||||
// in predicates do not need to, and should not, since their execution
|
||||
// may be much later than top-level iterators.
|
||||
// m_varStackPos is set in setRoot, which is called
|
||||
// from the execute method.
|
||||
if (-1 == m_stackFrame)
|
||||
{
|
||||
return returnNextNode(m_firstWalker.nextNode());
|
||||
}
|
||||
else
|
||||
{
|
||||
VariableStack vars = m_execContext.getVarStack();
|
||||
|
||||
// These three statements need to be combined into one operation.
|
||||
int savedStart = vars.getStackFrame();
|
||||
|
||||
vars.setStackFrame(m_stackFrame);
|
||||
|
||||
int n = returnNextNode(m_firstWalker.nextNode());
|
||||
|
||||
// These two statements need to be combined into one operation.
|
||||
vars.setStackFrame(savedStart);
|
||||
|
||||
return n;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the head of the walker list.
|
||||
*
|
||||
* @return The head of the walker list, or null
|
||||
* if this iterator does not implement walkers.
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public final AxesWalker getFirstWalker()
|
||||
{
|
||||
return m_firstWalker;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the head of the walker list.
|
||||
*
|
||||
* @param walker Should be a valid AxesWalker.
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public final void setFirstWalker(AxesWalker walker)
|
||||
{
|
||||
m_firstWalker = walker;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the last used walker.
|
||||
*
|
||||
* @param walker The last used walker, or null.
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public final void setLastUsedWalker(AxesWalker walker)
|
||||
{
|
||||
m_lastUsedWalker = walker;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the last used walker.
|
||||
*
|
||||
* @return The last used walker, or null.
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public final AxesWalker getLastUsedWalker()
|
||||
{
|
||||
return m_lastUsedWalker;
|
||||
}
|
||||
|
||||
/**
|
||||
* Detaches the iterator from the set which it iterated over, releasing
|
||||
* any computational resources and placing the iterator in the INVALID
|
||||
* state. After<code>detach</code> has been invoked, calls to
|
||||
* <code>nextNode</code> or<code>previousNode</code> will raise the
|
||||
* exception INVALID_STATE_ERR.
|
||||
*/
|
||||
public void detach()
|
||||
{
|
||||
if(m_allowDetach)
|
||||
{
|
||||
AxesWalker walker = m_firstWalker;
|
||||
while (null != walker)
|
||||
{
|
||||
walker.detach();
|
||||
walker = walker.getNextWalker();
|
||||
}
|
||||
|
||||
m_lastUsedWalker = null;
|
||||
|
||||
// Always call the superclass detach last!
|
||||
super.detach();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is used to fixup variables from QNames to stack frame
|
||||
* indexes at stylesheet build time.
|
||||
* @param vars List of QNames that correspond to variables. This list
|
||||
* should be searched backwards for the first qualified name that
|
||||
* corresponds to the variable reference qname. The position of the
|
||||
* QName in the vector from the start of the vector will be its position
|
||||
* in the stack frame (but variables above the globalsTop value will need
|
||||
* to be offset to the current stack frame).
|
||||
*/
|
||||
public void fixupVariables(java.util.Vector vars, int globalsSize)
|
||||
{
|
||||
m_predicateIndex = -1;
|
||||
|
||||
AxesWalker walker = m_firstWalker;
|
||||
|
||||
while (null != walker)
|
||||
{
|
||||
walker.fixupVariables(vars, globalsSize);
|
||||
walker = walker.getNextWalker();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.sun.org.apache.xpath.internal.XPathVisitable#callVisitors(ExpressionOwner, XPathVisitor)
|
||||
*/
|
||||
public void callVisitors(ExpressionOwner owner, XPathVisitor visitor)
|
||||
{
|
||||
if(visitor.visitLocationPath(owner, this))
|
||||
{
|
||||
if(null != m_firstWalker)
|
||||
{
|
||||
m_firstWalker.callVisitors(this, visitor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** The last used step walker in the walker list.
|
||||
* @serial */
|
||||
protected AxesWalker m_lastUsedWalker;
|
||||
|
||||
/** The head of the step walker list.
|
||||
* @serial */
|
||||
protected AxesWalker m_firstWalker;
|
||||
|
||||
/**
|
||||
* @see ExpressionOwner#getExpression()
|
||||
*/
|
||||
public Expression getExpression()
|
||||
{
|
||||
return m_firstWalker;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ExpressionOwner#setExpression(Expression)
|
||||
*/
|
||||
public void setExpression(Expression exp)
|
||||
{
|
||||
exp.exprSetParent(this);
|
||||
m_firstWalker = (AxesWalker)exp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Expression#deepEquals(Expression)
|
||||
*/
|
||||
public boolean deepEquals(Expression expr)
|
||||
{
|
||||
if (!super.deepEquals(expr))
|
||||
return false;
|
||||
|
||||
AxesWalker walker1 = m_firstWalker;
|
||||
AxesWalker walker2 = ((WalkingIterator)expr).m_firstWalker;
|
||||
while ((null != walker1) && (null != walker2))
|
||||
{
|
||||
if(!walker1.deepEquals(walker2))
|
||||
return false;
|
||||
walker1 = walker1.getNextWalker();
|
||||
walker2 = walker2.getNextWalker();
|
||||
}
|
||||
|
||||
if((null != walker1) || (null != walker2))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,215 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.axes;
|
||||
|
||||
import com.sun.org.apache.xml.internal.dtm.Axis;
|
||||
import com.sun.org.apache.xml.internal.utils.PrefixResolver;
|
||||
import com.sun.org.apache.xpath.internal.compiler.Compiler;
|
||||
|
||||
/**
|
||||
* This class iterates over set of nodes that needs to be sorted.
|
||||
* @xsl.usage internal
|
||||
*/
|
||||
public class WalkingIteratorSorted extends WalkingIterator
|
||||
{
|
||||
static final long serialVersionUID = -4512512007542368213L;
|
||||
|
||||
// /** True if the nodes will be found in document order */
|
||||
// protected boolean m_inNaturalOrder = false;
|
||||
|
||||
/** True if the nodes will be found in document order, and this can
|
||||
* be determined statically. */
|
||||
protected boolean m_inNaturalOrderStatic = false;
|
||||
|
||||
/**
|
||||
* Create a WalkingIteratorSorted object.
|
||||
*
|
||||
* @param nscontext The namespace context for this iterator,
|
||||
* should be OK if null.
|
||||
*/
|
||||
public WalkingIteratorSorted(PrefixResolver nscontext)
|
||||
{
|
||||
super(nscontext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a WalkingIterator iterator, including creation
|
||||
* of step walkers from the opcode list, and call back
|
||||
* into the Compiler to create predicate expressions.
|
||||
*
|
||||
* @param compiler The Compiler which is creating
|
||||
* this expression.
|
||||
* @param opPos The position of this iterator in the
|
||||
* opcode list from the compiler.
|
||||
* @param shouldLoadWalkers True if walkers should be
|
||||
* loaded, or false if this is a derived iterator and
|
||||
* it doesn't wish to load child walkers.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
WalkingIteratorSorted(
|
||||
Compiler compiler, int opPos, int analysis, boolean shouldLoadWalkers)
|
||||
throws javax.xml.transform.TransformerException
|
||||
{
|
||||
super(compiler, opPos, analysis, shouldLoadWalkers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if all the nodes in the iteration well be returned in document
|
||||
* order.
|
||||
*
|
||||
* @return true as a default.
|
||||
*/
|
||||
public boolean isDocOrdered()
|
||||
{
|
||||
return m_inNaturalOrderStatic;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tell if the nodeset can be walked in doc order, via static analysis.
|
||||
*
|
||||
*
|
||||
* @return true if the nodeset can be walked in doc order, without sorting.
|
||||
*/
|
||||
boolean canBeWalkedInNaturalDocOrderStatic()
|
||||
{
|
||||
|
||||
if (null != m_firstWalker)
|
||||
{
|
||||
AxesWalker walker = m_firstWalker;
|
||||
int prevAxis = -1;
|
||||
boolean prevIsSimpleDownAxis = true;
|
||||
|
||||
for(int i = 0; null != walker; i++)
|
||||
{
|
||||
int axis = walker.getAxis();
|
||||
|
||||
if(walker.isDocOrdered())
|
||||
{
|
||||
boolean isSimpleDownAxis = ((axis == Axis.CHILD)
|
||||
|| (axis == Axis.SELF)
|
||||
|| (axis == Axis.ROOT));
|
||||
// Catching the filtered list here is only OK because
|
||||
// FilterExprWalker#isDocOrdered() did the right thing.
|
||||
if(isSimpleDownAxis || (axis == -1))
|
||||
walker = walker.getNextWalker();
|
||||
else
|
||||
{
|
||||
boolean isLastWalker = (null == walker.getNextWalker());
|
||||
if(isLastWalker)
|
||||
{
|
||||
if(walker.isDocOrdered() && (axis == Axis.DESCENDANT ||
|
||||
axis == Axis.DESCENDANTORSELF || axis == Axis.DESCENDANTSFROMROOT
|
||||
|| axis == Axis.DESCENDANTSORSELFFROMROOT) || (axis == Axis.ATTRIBUTE))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// /**
|
||||
// * NEEDSDOC Method canBeWalkedInNaturalDocOrder
|
||||
// *
|
||||
// *
|
||||
// * NEEDSDOC (canBeWalkedInNaturalDocOrder) @return
|
||||
// */
|
||||
// boolean canBeWalkedInNaturalDocOrder()
|
||||
// {
|
||||
//
|
||||
// if (null != m_firstWalker)
|
||||
// {
|
||||
// AxesWalker walker = m_firstWalker;
|
||||
// int prevAxis = -1;
|
||||
// boolean prevIsSimpleDownAxis = true;
|
||||
//
|
||||
// for(int i = 0; null != walker; i++)
|
||||
// {
|
||||
// int axis = walker.getAxis();
|
||||
//
|
||||
// if(walker.isDocOrdered())
|
||||
// {
|
||||
// boolean isSimpleDownAxis = ((axis == Axis.CHILD)
|
||||
// || (axis == Axis.SELF)
|
||||
// || (axis == Axis.ROOT));
|
||||
// // Catching the filtered list here is only OK because
|
||||
// // FilterExprWalker#isDocOrdered() did the right thing.
|
||||
// if(isSimpleDownAxis || (axis == -1))
|
||||
// walker = walker.getNextWalker();
|
||||
// else
|
||||
// {
|
||||
// boolean isLastWalker = (null == walker.getNextWalker());
|
||||
// if(isLastWalker)
|
||||
// {
|
||||
// if(walker.isDocOrdered() && (axis == Axis.DESCENDANT ||
|
||||
// axis == Axis.DESCENDANTORSELF || axis == Axis.DESCENDANTSFROMROOT
|
||||
// || axis == Axis.DESCENDANTSORSELFFROMROOT) || (axis == Axis.ATTRIBUTE))
|
||||
// return true;
|
||||
// }
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// return false;
|
||||
// }
|
||||
// return true;
|
||||
// }
|
||||
// return false;
|
||||
// }
|
||||
|
||||
/**
|
||||
* This function is used to perform some extra analysis of the iterator.
|
||||
*
|
||||
* @param vars List of QNames that correspond to variables. This list
|
||||
* should be searched backwards for the first qualified name that
|
||||
* corresponds to the variable reference qname. The position of the
|
||||
* QName in the vector from the start of the vector will be its position
|
||||
* in the stack frame (but variables above the globalsTop value will need
|
||||
* to be offset to the current stack frame).
|
||||
*/
|
||||
public void fixupVariables(java.util.Vector vars, int globalsSize)
|
||||
{
|
||||
super.fixupVariables(vars, globalsSize);
|
||||
|
||||
int analysis = getAnalysisBits();
|
||||
if(WalkerFactory.isNaturalDocOrder(analysis))
|
||||
{
|
||||
m_inNaturalOrderStatic = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_inNaturalOrderStatic = false;
|
||||
// System.out.println("Setting natural doc order to false: "+
|
||||
// WalkerFactory.getAnalysisString(analysis));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
1297
jdkSrc/jdk8/com/sun/org/apache/xpath/internal/compiler/Compiler.java
Normal file
1297
jdkSrc/jdk8/com/sun/org/apache/xpath/internal/compiler/Compiler.java
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.compiler;
|
||||
|
||||
import javax.xml.transform.TransformerException;
|
||||
|
||||
import com.sun.org.apache.xpath.internal.functions.Function;
|
||||
import com.sun.org.apache.xalan.internal.utils.ObjectFactory;
|
||||
import com.sun.org.apache.xalan.internal.utils.ConfigurationError;
|
||||
|
||||
/**
|
||||
* Lazy load of functions into the function table as needed, so we don't
|
||||
* have to load all the functions allowed in XPath and XSLT on startup.
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public class FuncLoader
|
||||
{
|
||||
|
||||
/** The function ID, which may correspond to one of the FUNC_XXX values
|
||||
* found in {@link com.sun.org.apache.xpath.internal.compiler.FunctionTable}, but may
|
||||
* be a value installed by an external module. */
|
||||
private int m_funcID;
|
||||
|
||||
/** The class name of the function. Must not be null. */
|
||||
private String m_funcName;
|
||||
|
||||
/**
|
||||
* Get the local class name of the function class. If function name does
|
||||
* not have a '.' in it, it is assumed to be relative to
|
||||
* 'com.sun.org.apache.xpath.internal.functions'.
|
||||
*
|
||||
* @return The class name of the {com.sun.org.apache.xpath.internal.functions.Function} class.
|
||||
*/
|
||||
public String getName()
|
||||
{
|
||||
return m_funcName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a function loader
|
||||
*
|
||||
* @param funcName The class name of the {com.sun.org.apache.xpath.internal.functions.Function}
|
||||
* class, which, if it does not have a '.' in it, is assumed to
|
||||
* be relative to 'com.sun.org.apache.xpath.internal.functions'.
|
||||
* @param funcID The function ID, which may correspond to one of the FUNC_XXX
|
||||
* values found in {@link com.sun.org.apache.xpath.internal.compiler.FunctionTable}, but may
|
||||
* be a value installed by an external module.
|
||||
*/
|
||||
public FuncLoader(String funcName, int funcID)
|
||||
{
|
||||
|
||||
super();
|
||||
|
||||
m_funcID = funcID;
|
||||
m_funcName = funcName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a Function instance that this instance is liaisoning for.
|
||||
*
|
||||
* @return non-null reference to Function derivative.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException if ClassNotFoundException,
|
||||
* IllegalAccessException, or InstantiationException is thrown.
|
||||
*/
|
||||
Function getFunction() throws TransformerException
|
||||
{
|
||||
try
|
||||
{
|
||||
String className = m_funcName;
|
||||
if (className.indexOf(".") < 0) {
|
||||
className = "com.sun.org.apache.xpath.internal.functions." + className;
|
||||
}
|
||||
//hack for loading only built-in function classes.
|
||||
String subString = className.substring(0,className.lastIndexOf('.'));
|
||||
if(!(subString.equals ("com.sun.org.apache.xalan.internal.templates") ||
|
||||
subString.equals ("com.sun.org.apache.xpath.internal.functions"))) {
|
||||
throw new TransformerException("Application can't install his own xpath function.");
|
||||
}
|
||||
|
||||
return (Function) ObjectFactory.newInstance(className, true);
|
||||
|
||||
}
|
||||
catch (ConfigurationError e)
|
||||
{
|
||||
throw new TransformerException(e.getException());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,419 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
*/
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
/*
|
||||
* $Id: FunctionTable.java,v 1.3 2005/09/28 13:49:34 pvedula Exp $
|
||||
*/
|
||||
package com.sun.org.apache.xpath.internal.compiler;
|
||||
|
||||
import com.sun.org.apache.xpath.internal.Expression;
|
||||
import com.sun.org.apache.xpath.internal.functions.Function;
|
||||
import java.util.HashMap;
|
||||
import javax.xml.transform.TransformerException;
|
||||
|
||||
/**
|
||||
* The function table for XPath.
|
||||
*/
|
||||
public class FunctionTable
|
||||
{
|
||||
|
||||
/** The 'current()' id. */
|
||||
public static final int FUNC_CURRENT = 0;
|
||||
|
||||
/** The 'last()' id. */
|
||||
public static final int FUNC_LAST = 1;
|
||||
|
||||
/** The 'position()' id. */
|
||||
public static final int FUNC_POSITION = 2;
|
||||
|
||||
/** The 'count()' id. */
|
||||
public static final int FUNC_COUNT = 3;
|
||||
|
||||
/** The 'id()' id. */
|
||||
public static final int FUNC_ID = 4;
|
||||
|
||||
/** The 'key()' id (XSLT). */
|
||||
public static final int FUNC_KEY = 5;
|
||||
|
||||
/** The 'local-name()' id. */
|
||||
public static final int FUNC_LOCAL_PART = 7;
|
||||
|
||||
/** The 'namespace-uri()' id. */
|
||||
public static final int FUNC_NAMESPACE = 8;
|
||||
|
||||
/** The 'name()' id. */
|
||||
public static final int FUNC_QNAME = 9;
|
||||
|
||||
/** The 'generate-id()' id. */
|
||||
public static final int FUNC_GENERATE_ID = 10;
|
||||
|
||||
/** The 'not()' id. */
|
||||
public static final int FUNC_NOT = 11;
|
||||
|
||||
/** The 'true()' id. */
|
||||
public static final int FUNC_TRUE = 12;
|
||||
|
||||
/** The 'false()' id. */
|
||||
public static final int FUNC_FALSE = 13;
|
||||
|
||||
/** The 'boolean()' id. */
|
||||
public static final int FUNC_BOOLEAN = 14;
|
||||
|
||||
/** The 'number()' id. */
|
||||
public static final int FUNC_NUMBER = 15;
|
||||
|
||||
/** The 'floor()' id. */
|
||||
public static final int FUNC_FLOOR = 16;
|
||||
|
||||
/** The 'ceiling()' id. */
|
||||
public static final int FUNC_CEILING = 17;
|
||||
|
||||
/** The 'round()' id. */
|
||||
public static final int FUNC_ROUND = 18;
|
||||
|
||||
/** The 'sum()' id. */
|
||||
public static final int FUNC_SUM = 19;
|
||||
|
||||
/** The 'string()' id. */
|
||||
public static final int FUNC_STRING = 20;
|
||||
|
||||
/** The 'starts-with()' id. */
|
||||
public static final int FUNC_STARTS_WITH = 21;
|
||||
|
||||
/** The 'contains()' id. */
|
||||
public static final int FUNC_CONTAINS = 22;
|
||||
|
||||
/** The 'substring-before()' id. */
|
||||
public static final int FUNC_SUBSTRING_BEFORE = 23;
|
||||
|
||||
/** The 'substring-after()' id. */
|
||||
public static final int FUNC_SUBSTRING_AFTER = 24;
|
||||
|
||||
/** The 'normalize-space()' id. */
|
||||
public static final int FUNC_NORMALIZE_SPACE = 25;
|
||||
|
||||
/** The 'translate()' id. */
|
||||
public static final int FUNC_TRANSLATE = 26;
|
||||
|
||||
/** The 'concat()' id. */
|
||||
public static final int FUNC_CONCAT = 27;
|
||||
|
||||
/** The 'substring()' id. */
|
||||
public static final int FUNC_SUBSTRING = 29;
|
||||
|
||||
/** The 'string-length()' id. */
|
||||
public static final int FUNC_STRING_LENGTH = 30;
|
||||
|
||||
/** The 'system-property()' id. */
|
||||
public static final int FUNC_SYSTEM_PROPERTY = 31;
|
||||
|
||||
/** The 'lang()' id. */
|
||||
public static final int FUNC_LANG = 32;
|
||||
|
||||
/** The 'function-available()' id (XSLT). */
|
||||
public static final int FUNC_EXT_FUNCTION_AVAILABLE = 33;
|
||||
|
||||
/** The 'element-available()' id (XSLT). */
|
||||
public static final int FUNC_EXT_ELEM_AVAILABLE = 34;
|
||||
|
||||
/** The 'unparsed-entity-uri()' id (XSLT). */
|
||||
public static final int FUNC_UNPARSED_ENTITY_URI = 36;
|
||||
|
||||
/** The 'here()' id (XML Signature). */
|
||||
public static final int FUNC_HERE = 37;
|
||||
|
||||
// Proprietary
|
||||
|
||||
/** The 'document-location()' id (Proprietary). */
|
||||
public static final int FUNC_DOCLOCATION = 35;
|
||||
|
||||
/**
|
||||
* The function table.
|
||||
*/
|
||||
private static Class m_functions[];
|
||||
|
||||
/** Table of function name to function ID associations. */
|
||||
private static HashMap m_functionID = new HashMap();
|
||||
|
||||
/**
|
||||
* The function table contains customized functions
|
||||
*/
|
||||
private Class m_functions_customer[] = new Class[NUM_ALLOWABLE_ADDINS];
|
||||
|
||||
/**
|
||||
* Table of function name to function ID associations for customized functions
|
||||
*/
|
||||
private HashMap m_functionID_customer = new HashMap();
|
||||
|
||||
/**
|
||||
* Number of built in functions. Be sure to update this as
|
||||
* built-in functions are added.
|
||||
*/
|
||||
private static final int NUM_BUILT_IN_FUNCS = 38;
|
||||
|
||||
/**
|
||||
* Number of built-in functions that may be added.
|
||||
*/
|
||||
private static final int NUM_ALLOWABLE_ADDINS = 30;
|
||||
|
||||
/**
|
||||
* The index to the next free function index.
|
||||
*/
|
||||
private int m_funcNextFreeIndex = NUM_BUILT_IN_FUNCS;
|
||||
|
||||
static
|
||||
{
|
||||
m_functions = new Class[NUM_BUILT_IN_FUNCS];
|
||||
m_functions[FUNC_CURRENT] = com.sun.org.apache.xpath.internal.functions.FuncCurrent.class;
|
||||
m_functions[FUNC_LAST] = com.sun.org.apache.xpath.internal.functions.FuncLast.class;
|
||||
m_functions[FUNC_POSITION] = com.sun.org.apache.xpath.internal.functions.FuncPosition.class;
|
||||
m_functions[FUNC_COUNT] = com.sun.org.apache.xpath.internal.functions.FuncCount.class;
|
||||
m_functions[FUNC_ID] = com.sun.org.apache.xpath.internal.functions.FuncId.class;
|
||||
// J2SE does not support Xalan interpretive
|
||||
// m_functions[FUNC_KEY] =
|
||||
// com.sun.org.apache.xalan.internal.templates.FuncKey.class;
|
||||
m_functions[FUNC_LOCAL_PART] =
|
||||
com.sun.org.apache.xpath.internal.functions.FuncLocalPart.class;
|
||||
m_functions[FUNC_NAMESPACE] =
|
||||
com.sun.org.apache.xpath.internal.functions.FuncNamespace.class;
|
||||
m_functions[FUNC_QNAME] = com.sun.org.apache.xpath.internal.functions.FuncQname.class;
|
||||
m_functions[FUNC_GENERATE_ID] =
|
||||
com.sun.org.apache.xpath.internal.functions.FuncGenerateId.class;
|
||||
m_functions[FUNC_NOT] = com.sun.org.apache.xpath.internal.functions.FuncNot.class;
|
||||
m_functions[FUNC_TRUE] = com.sun.org.apache.xpath.internal.functions.FuncTrue.class;
|
||||
m_functions[FUNC_FALSE] = com.sun.org.apache.xpath.internal.functions.FuncFalse.class;
|
||||
m_functions[FUNC_BOOLEAN] = com.sun.org.apache.xpath.internal.functions.FuncBoolean.class;
|
||||
m_functions[FUNC_LANG] = com.sun.org.apache.xpath.internal.functions.FuncLang.class;
|
||||
m_functions[FUNC_NUMBER] = com.sun.org.apache.xpath.internal.functions.FuncNumber.class;
|
||||
m_functions[FUNC_FLOOR] = com.sun.org.apache.xpath.internal.functions.FuncFloor.class;
|
||||
m_functions[FUNC_CEILING] = com.sun.org.apache.xpath.internal.functions.FuncCeiling.class;
|
||||
m_functions[FUNC_ROUND] = com.sun.org.apache.xpath.internal.functions.FuncRound.class;
|
||||
m_functions[FUNC_SUM] = com.sun.org.apache.xpath.internal.functions.FuncSum.class;
|
||||
m_functions[FUNC_STRING] = com.sun.org.apache.xpath.internal.functions.FuncString.class;
|
||||
m_functions[FUNC_STARTS_WITH] =
|
||||
com.sun.org.apache.xpath.internal.functions.FuncStartsWith.class;
|
||||
m_functions[FUNC_CONTAINS] = com.sun.org.apache.xpath.internal.functions.FuncContains.class;
|
||||
m_functions[FUNC_SUBSTRING_BEFORE] =
|
||||
com.sun.org.apache.xpath.internal.functions.FuncSubstringBefore.class;
|
||||
m_functions[FUNC_SUBSTRING_AFTER] =
|
||||
com.sun.org.apache.xpath.internal.functions.FuncSubstringAfter.class;
|
||||
m_functions[FUNC_NORMALIZE_SPACE] =
|
||||
com.sun.org.apache.xpath.internal.functions.FuncNormalizeSpace.class;
|
||||
m_functions[FUNC_TRANSLATE] =
|
||||
com.sun.org.apache.xpath.internal.functions.FuncTranslate.class;
|
||||
m_functions[FUNC_CONCAT] = com.sun.org.apache.xpath.internal.functions.FuncConcat.class;
|
||||
m_functions[FUNC_SYSTEM_PROPERTY] =
|
||||
com.sun.org.apache.xpath.internal.functions.FuncSystemProperty.class;
|
||||
m_functions[FUNC_EXT_FUNCTION_AVAILABLE] =
|
||||
com.sun.org.apache.xpath.internal.functions.FuncExtFunctionAvailable.class;
|
||||
m_functions[FUNC_EXT_ELEM_AVAILABLE] =
|
||||
com.sun.org.apache.xpath.internal.functions.FuncExtElementAvailable.class;
|
||||
m_functions[FUNC_SUBSTRING] =
|
||||
com.sun.org.apache.xpath.internal.functions.FuncSubstring.class;
|
||||
m_functions[FUNC_STRING_LENGTH] =
|
||||
com.sun.org.apache.xpath.internal.functions.FuncStringLength.class;
|
||||
m_functions[FUNC_DOCLOCATION] =
|
||||
com.sun.org.apache.xpath.internal.functions.FuncDoclocation.class;
|
||||
m_functions[FUNC_UNPARSED_ENTITY_URI] =
|
||||
com.sun.org.apache.xpath.internal.functions.FuncUnparsedEntityURI.class;
|
||||
m_functions[FUNC_HERE] =
|
||||
com.sun.org.apache.xpath.internal.functions.FuncHere.class;
|
||||
}
|
||||
|
||||
static{
|
||||
m_functionID.put(Keywords.FUNC_CURRENT_STRING,
|
||||
new Integer(FunctionTable.FUNC_CURRENT));
|
||||
m_functionID.put(Keywords.FUNC_LAST_STRING,
|
||||
new Integer(FunctionTable.FUNC_LAST));
|
||||
m_functionID.put(Keywords.FUNC_POSITION_STRING,
|
||||
new Integer(FunctionTable.FUNC_POSITION));
|
||||
m_functionID.put(Keywords.FUNC_COUNT_STRING,
|
||||
new Integer(FunctionTable.FUNC_COUNT));
|
||||
m_functionID.put(Keywords.FUNC_ID_STRING,
|
||||
new Integer(FunctionTable.FUNC_ID));
|
||||
m_functionID.put(Keywords.FUNC_KEY_STRING,
|
||||
new Integer(FunctionTable.FUNC_KEY));
|
||||
m_functionID.put(Keywords.FUNC_LOCAL_PART_STRING,
|
||||
new Integer(FunctionTable.FUNC_LOCAL_PART));
|
||||
m_functionID.put(Keywords.FUNC_NAMESPACE_STRING,
|
||||
new Integer(FunctionTable.FUNC_NAMESPACE));
|
||||
m_functionID.put(Keywords.FUNC_NAME_STRING,
|
||||
new Integer(FunctionTable.FUNC_QNAME));
|
||||
m_functionID.put(Keywords.FUNC_GENERATE_ID_STRING,
|
||||
new Integer(FunctionTable.FUNC_GENERATE_ID));
|
||||
m_functionID.put(Keywords.FUNC_NOT_STRING,
|
||||
new Integer(FunctionTable.FUNC_NOT));
|
||||
m_functionID.put(Keywords.FUNC_TRUE_STRING,
|
||||
new Integer(FunctionTable.FUNC_TRUE));
|
||||
m_functionID.put(Keywords.FUNC_FALSE_STRING,
|
||||
new Integer(FunctionTable.FUNC_FALSE));
|
||||
m_functionID.put(Keywords.FUNC_BOOLEAN_STRING,
|
||||
new Integer(FunctionTable.FUNC_BOOLEAN));
|
||||
m_functionID.put(Keywords.FUNC_LANG_STRING,
|
||||
new Integer(FunctionTable.FUNC_LANG));
|
||||
m_functionID.put(Keywords.FUNC_NUMBER_STRING,
|
||||
new Integer(FunctionTable.FUNC_NUMBER));
|
||||
m_functionID.put(Keywords.FUNC_FLOOR_STRING,
|
||||
new Integer(FunctionTable.FUNC_FLOOR));
|
||||
m_functionID.put(Keywords.FUNC_CEILING_STRING,
|
||||
new Integer(FunctionTable.FUNC_CEILING));
|
||||
m_functionID.put(Keywords.FUNC_ROUND_STRING,
|
||||
new Integer(FunctionTable.FUNC_ROUND));
|
||||
m_functionID.put(Keywords.FUNC_SUM_STRING,
|
||||
new Integer(FunctionTable.FUNC_SUM));
|
||||
m_functionID.put(Keywords.FUNC_STRING_STRING,
|
||||
new Integer(FunctionTable.FUNC_STRING));
|
||||
m_functionID.put(Keywords.FUNC_STARTS_WITH_STRING,
|
||||
new Integer(FunctionTable.FUNC_STARTS_WITH));
|
||||
m_functionID.put(Keywords.FUNC_CONTAINS_STRING,
|
||||
new Integer(FunctionTable.FUNC_CONTAINS));
|
||||
m_functionID.put(Keywords.FUNC_SUBSTRING_BEFORE_STRING,
|
||||
new Integer(FunctionTable.FUNC_SUBSTRING_BEFORE));
|
||||
m_functionID.put(Keywords.FUNC_SUBSTRING_AFTER_STRING,
|
||||
new Integer(FunctionTable.FUNC_SUBSTRING_AFTER));
|
||||
m_functionID.put(Keywords.FUNC_NORMALIZE_SPACE_STRING,
|
||||
new Integer(FunctionTable.FUNC_NORMALIZE_SPACE));
|
||||
m_functionID.put(Keywords.FUNC_TRANSLATE_STRING,
|
||||
new Integer(FunctionTable.FUNC_TRANSLATE));
|
||||
m_functionID.put(Keywords.FUNC_CONCAT_STRING,
|
||||
new Integer(FunctionTable.FUNC_CONCAT));
|
||||
m_functionID.put(Keywords.FUNC_SYSTEM_PROPERTY_STRING,
|
||||
new Integer(FunctionTable.FUNC_SYSTEM_PROPERTY));
|
||||
m_functionID.put(Keywords.FUNC_EXT_FUNCTION_AVAILABLE_STRING,
|
||||
new Integer(FunctionTable.FUNC_EXT_FUNCTION_AVAILABLE));
|
||||
m_functionID.put(Keywords.FUNC_EXT_ELEM_AVAILABLE_STRING,
|
||||
new Integer(FunctionTable.FUNC_EXT_ELEM_AVAILABLE));
|
||||
m_functionID.put(Keywords.FUNC_SUBSTRING_STRING,
|
||||
new Integer(FunctionTable.FUNC_SUBSTRING));
|
||||
m_functionID.put(Keywords.FUNC_STRING_LENGTH_STRING,
|
||||
new Integer(FunctionTable.FUNC_STRING_LENGTH));
|
||||
m_functionID.put(Keywords.FUNC_UNPARSED_ENTITY_URI_STRING,
|
||||
new Integer(FunctionTable.FUNC_UNPARSED_ENTITY_URI));
|
||||
m_functionID.put(Keywords.FUNC_DOCLOCATION_STRING,
|
||||
new Integer(FunctionTable.FUNC_DOCLOCATION));
|
||||
m_functionID.put(Keywords.FUNC_HERE_STRING,
|
||||
new Integer(FunctionTable.FUNC_HERE));
|
||||
}
|
||||
|
||||
public FunctionTable(){
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of the a function in the static table. Needed to avoid
|
||||
* making the table publicly available.
|
||||
*/
|
||||
String getFunctionName(int funcID) {
|
||||
if (funcID < NUM_BUILT_IN_FUNCS) return m_functions[funcID].getName();
|
||||
else return m_functions_customer[funcID - NUM_BUILT_IN_FUNCS].getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain a new Function object from a function ID.
|
||||
*
|
||||
* @param which The function ID, which may correspond to one of the FUNC_XXX
|
||||
* values found in {@link com.sun.org.apache.xpath.internal.compiler.FunctionTable}, but may
|
||||
* be a value installed by an external module.
|
||||
*
|
||||
* @return a a new Function instance.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException if ClassNotFoundException,
|
||||
* IllegalAccessException, or InstantiationException is thrown.
|
||||
*/
|
||||
Function getFunction(int which)
|
||||
throws javax.xml.transform.TransformerException
|
||||
{
|
||||
try{
|
||||
if (which < NUM_BUILT_IN_FUNCS)
|
||||
return (Function) m_functions[which].newInstance();
|
||||
else
|
||||
return (Function) m_functions_customer[
|
||||
which-NUM_BUILT_IN_FUNCS].newInstance();
|
||||
}catch (IllegalAccessException ex){
|
||||
throw new TransformerException(ex.getMessage());
|
||||
}catch (InstantiationException ex){
|
||||
throw new TransformerException(ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain a function ID from a given function name
|
||||
* @param key the function name in a java.lang.String format.
|
||||
* @return a function ID, which may correspond to one of the FUNC_XXX values
|
||||
* found in {@link com.sun.org.apache.xpath.internal.compiler.FunctionTable}, but may be a
|
||||
* value installed by an external module.
|
||||
*/
|
||||
Object getFunctionID(String key){
|
||||
Object id = m_functionID_customer.get(key);
|
||||
if (null == id) id = m_functionID.get(key);
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Install a built-in function.
|
||||
* @param name The unqualified name of the function, must not be null
|
||||
* @param func A Implementation of an XPath Function object.
|
||||
* @return the position of the function in the internal index.
|
||||
*/
|
||||
public int installFunction(String name, Class func)
|
||||
{
|
||||
|
||||
int funcIndex;
|
||||
Object funcIndexObj = getFunctionID(name);
|
||||
|
||||
if (null != funcIndexObj)
|
||||
{
|
||||
funcIndex = ((Integer) funcIndexObj).intValue();
|
||||
|
||||
if (funcIndex < NUM_BUILT_IN_FUNCS){
|
||||
funcIndex = m_funcNextFreeIndex++;
|
||||
m_functionID_customer.put(name, new Integer(funcIndex));
|
||||
}
|
||||
m_functions_customer[funcIndex - NUM_BUILT_IN_FUNCS] = func;
|
||||
}
|
||||
else
|
||||
{
|
||||
funcIndex = m_funcNextFreeIndex++;
|
||||
|
||||
m_functions_customer[funcIndex-NUM_BUILT_IN_FUNCS] = func;
|
||||
|
||||
m_functionID_customer.put(name,
|
||||
new Integer(funcIndex));
|
||||
}
|
||||
return funcIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tell if a built-in, non-namespaced function is available.
|
||||
*
|
||||
* @param methName The local name of the function.
|
||||
*
|
||||
* @return True if the function can be executed.
|
||||
*/
|
||||
public boolean functionAvailable(String methName)
|
||||
{
|
||||
Object tblEntry = m_functionID.get(methName);
|
||||
if (null != tblEntry) return true;
|
||||
else{
|
||||
tblEntry = m_functionID_customer.get(methName);
|
||||
return (null != tblEntry)? true : false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,397 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
*/
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
/*
|
||||
* $Id: Keywords.java,v 1.2.4.1 2005/09/14 19:46:01 jeffsuttor Exp $
|
||||
*/
|
||||
package com.sun.org.apache.xpath.internal.compiler;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Table of strings to operation code lookups.
|
||||
*
|
||||
* @xsl.usage internal
|
||||
*/
|
||||
public class Keywords {
|
||||
|
||||
/**
|
||||
* Table of keywords to opcode associations.
|
||||
*/
|
||||
private static final Map<String, Integer> m_keywords;
|
||||
|
||||
/**
|
||||
* Table of axes names to opcode associations.
|
||||
*/
|
||||
private static final Map<String, Integer> m_axisnames;
|
||||
|
||||
/**
|
||||
* Table of function name to function ID associations.
|
||||
*/
|
||||
private static final Map<String, Integer> m_nodetests;
|
||||
|
||||
/**
|
||||
* Table of node type strings to opcode associations.
|
||||
*/
|
||||
private static final Map<String, Integer> m_nodetypes;
|
||||
|
||||
/**
|
||||
* ancestor axes string.
|
||||
*/
|
||||
private static final String FROM_ANCESTORS_STRING = "ancestor";
|
||||
|
||||
/**
|
||||
* ancestor-or-self axes string.
|
||||
*/
|
||||
private static final String FROM_ANCESTORS_OR_SELF_STRING
|
||||
= "ancestor-or-self";
|
||||
|
||||
/**
|
||||
* attribute axes string.
|
||||
*/
|
||||
private static final String FROM_ATTRIBUTES_STRING = "attribute";
|
||||
|
||||
/**
|
||||
* child axes string.
|
||||
*/
|
||||
private static final String FROM_CHILDREN_STRING = "child";
|
||||
|
||||
/**
|
||||
* descendant-or-self axes string.
|
||||
*/
|
||||
private static final String FROM_DESCENDANTS_STRING = "descendant";
|
||||
|
||||
/**
|
||||
* ancestor axes string.
|
||||
*/
|
||||
private static final String FROM_DESCENDANTS_OR_SELF_STRING
|
||||
= "descendant-or-self";
|
||||
|
||||
/**
|
||||
* following axes string.
|
||||
*/
|
||||
private static final String FROM_FOLLOWING_STRING = "following";
|
||||
|
||||
/**
|
||||
* following-sibling axes string.
|
||||
*/
|
||||
private static final String FROM_FOLLOWING_SIBLINGS_STRING
|
||||
= "following-sibling";
|
||||
|
||||
/**
|
||||
* parent axes string.
|
||||
*/
|
||||
private static final String FROM_PARENT_STRING = "parent";
|
||||
|
||||
/**
|
||||
* preceding axes string.
|
||||
*/
|
||||
private static final String FROM_PRECEDING_STRING = "preceding";
|
||||
|
||||
/**
|
||||
* preceding-sibling axes string.
|
||||
*/
|
||||
private static final String FROM_PRECEDING_SIBLINGS_STRING
|
||||
= "preceding-sibling";
|
||||
|
||||
/**
|
||||
* self axes string.
|
||||
*/
|
||||
private static final String FROM_SELF_STRING = "self";
|
||||
|
||||
/**
|
||||
* namespace axes string.
|
||||
*/
|
||||
private static final String FROM_NAMESPACE_STRING = "namespace";
|
||||
|
||||
/**
|
||||
* self axes abreviated string.
|
||||
*/
|
||||
private static final String FROM_SELF_ABBREVIATED_STRING = ".";
|
||||
|
||||
/**
|
||||
* comment node test string.
|
||||
*/
|
||||
private static final String NODETYPE_COMMENT_STRING = "comment";
|
||||
|
||||
/**
|
||||
* text node test string.
|
||||
*/
|
||||
private static final String NODETYPE_TEXT_STRING = "text";
|
||||
|
||||
/**
|
||||
* processing-instruction node test string.
|
||||
*/
|
||||
private static final String NODETYPE_PI_STRING = "processing-instruction";
|
||||
|
||||
/**
|
||||
* Any node test string.
|
||||
*/
|
||||
private static final String NODETYPE_NODE_STRING = "node";
|
||||
|
||||
/**
|
||||
* Wildcard element string.
|
||||
*/
|
||||
private static final String NODETYPE_ANYELEMENT_STRING = "*";
|
||||
|
||||
/**
|
||||
* current function string.
|
||||
*/
|
||||
public static final String FUNC_CURRENT_STRING = "current";
|
||||
|
||||
/**
|
||||
* last function string.
|
||||
*/
|
||||
public static final String FUNC_LAST_STRING = "last";
|
||||
|
||||
/**
|
||||
* position function string.
|
||||
*/
|
||||
public static final String FUNC_POSITION_STRING = "position";
|
||||
|
||||
/**
|
||||
* count function string.
|
||||
*/
|
||||
public static final String FUNC_COUNT_STRING = "count";
|
||||
|
||||
/**
|
||||
* id function string.
|
||||
*/
|
||||
static final String FUNC_ID_STRING = "id";
|
||||
|
||||
/**
|
||||
* key function string (XSLT).
|
||||
*/
|
||||
public static final String FUNC_KEY_STRING = "key";
|
||||
|
||||
/**
|
||||
* local-name function string.
|
||||
*/
|
||||
public static final String FUNC_LOCAL_PART_STRING = "local-name";
|
||||
|
||||
/**
|
||||
* namespace-uri function string.
|
||||
*/
|
||||
public static final String FUNC_NAMESPACE_STRING = "namespace-uri";
|
||||
|
||||
/**
|
||||
* name function string.
|
||||
*/
|
||||
public static final String FUNC_NAME_STRING = "name";
|
||||
|
||||
/**
|
||||
* generate-id function string (XSLT).
|
||||
*/
|
||||
public static final String FUNC_GENERATE_ID_STRING = "generate-id";
|
||||
|
||||
/**
|
||||
* not function string.
|
||||
*/
|
||||
public static final String FUNC_NOT_STRING = "not";
|
||||
|
||||
/**
|
||||
* true function string.
|
||||
*/
|
||||
public static final String FUNC_TRUE_STRING = "true";
|
||||
|
||||
/**
|
||||
* false function string.
|
||||
*/
|
||||
public static final String FUNC_FALSE_STRING = "false";
|
||||
|
||||
/**
|
||||
* boolean function string.
|
||||
*/
|
||||
public static final String FUNC_BOOLEAN_STRING = "boolean";
|
||||
|
||||
/**
|
||||
* lang function string.
|
||||
*/
|
||||
public static final String FUNC_LANG_STRING = "lang";
|
||||
|
||||
/**
|
||||
* number function string.
|
||||
*/
|
||||
public static final String FUNC_NUMBER_STRING = "number";
|
||||
|
||||
/**
|
||||
* floor function string.
|
||||
*/
|
||||
public static final String FUNC_FLOOR_STRING = "floor";
|
||||
|
||||
/**
|
||||
* ceiling function string.
|
||||
*/
|
||||
public static final String FUNC_CEILING_STRING = "ceiling";
|
||||
|
||||
/**
|
||||
* round function string.
|
||||
*/
|
||||
public static final String FUNC_ROUND_STRING = "round";
|
||||
|
||||
/**
|
||||
* sum function string.
|
||||
*/
|
||||
public static final String FUNC_SUM_STRING = "sum";
|
||||
|
||||
/**
|
||||
* string function string.
|
||||
*/
|
||||
public static final String FUNC_STRING_STRING = "string";
|
||||
|
||||
/**
|
||||
* starts-with function string.
|
||||
*/
|
||||
public static final String FUNC_STARTS_WITH_STRING = "starts-with";
|
||||
|
||||
/**
|
||||
* contains function string.
|
||||
*/
|
||||
public static final String FUNC_CONTAINS_STRING = "contains";
|
||||
|
||||
/**
|
||||
* substring-before function string.
|
||||
*/
|
||||
public static final String FUNC_SUBSTRING_BEFORE_STRING
|
||||
= "substring-before";
|
||||
|
||||
/**
|
||||
* substring-after function string.
|
||||
*/
|
||||
public static final String FUNC_SUBSTRING_AFTER_STRING = "substring-after";
|
||||
|
||||
/**
|
||||
* normalize-space function string.
|
||||
*/
|
||||
public static final String FUNC_NORMALIZE_SPACE_STRING = "normalize-space";
|
||||
|
||||
/**
|
||||
* translate function string.
|
||||
*/
|
||||
public static final String FUNC_TRANSLATE_STRING = "translate";
|
||||
|
||||
/**
|
||||
* concat function string.
|
||||
*/
|
||||
public static final String FUNC_CONCAT_STRING = "concat";
|
||||
|
||||
/**
|
||||
* system-property function string.
|
||||
*/
|
||||
public static final String FUNC_SYSTEM_PROPERTY_STRING = "system-property";
|
||||
|
||||
/**
|
||||
* function-available function string (XSLT).
|
||||
*/
|
||||
public static final String FUNC_EXT_FUNCTION_AVAILABLE_STRING
|
||||
= "function-available";
|
||||
|
||||
/**
|
||||
* element-available function string (XSLT).
|
||||
*/
|
||||
public static final String FUNC_EXT_ELEM_AVAILABLE_STRING
|
||||
= "element-available";
|
||||
|
||||
/**
|
||||
* substring function string.
|
||||
*/
|
||||
public static final String FUNC_SUBSTRING_STRING = "substring";
|
||||
|
||||
/**
|
||||
* string-length function string.
|
||||
*/
|
||||
public static final String FUNC_STRING_LENGTH_STRING = "string-length";
|
||||
|
||||
/**
|
||||
* unparsed-entity-uri function string (XSLT).
|
||||
*/
|
||||
public static final String FUNC_UNPARSED_ENTITY_URI_STRING
|
||||
= "unparsed-entity-uri";
|
||||
|
||||
/**
|
||||
* here function string (XML Signature).
|
||||
*/
|
||||
public static final String FUNC_HERE_STRING = "here";
|
||||
|
||||
// Proprietary, built in functions
|
||||
/**
|
||||
* current function string (Proprietary).
|
||||
*/
|
||||
public static final String FUNC_DOCLOCATION_STRING = "document-location";
|
||||
|
||||
static {
|
||||
Map<String, Integer> keywords = new HashMap<>();
|
||||
Map<String, Integer> axisnames = new HashMap<>();
|
||||
Map<String, Integer> nodetests = new HashMap<>();
|
||||
Map<String, Integer> nodetypes = new HashMap<>();
|
||||
|
||||
axisnames.put(FROM_ANCESTORS_STRING, OpCodes.FROM_ANCESTORS);
|
||||
axisnames.put(FROM_ANCESTORS_OR_SELF_STRING, OpCodes.FROM_ANCESTORS_OR_SELF);
|
||||
axisnames.put(FROM_ATTRIBUTES_STRING, OpCodes.FROM_ATTRIBUTES);
|
||||
axisnames.put(FROM_CHILDREN_STRING, OpCodes.FROM_CHILDREN);
|
||||
axisnames.put(FROM_DESCENDANTS_STRING, OpCodes.FROM_DESCENDANTS);
|
||||
axisnames.put(FROM_DESCENDANTS_OR_SELF_STRING, OpCodes.FROM_DESCENDANTS_OR_SELF);
|
||||
axisnames.put(FROM_FOLLOWING_STRING, OpCodes.FROM_FOLLOWING);
|
||||
axisnames.put(FROM_FOLLOWING_SIBLINGS_STRING, OpCodes.FROM_FOLLOWING_SIBLINGS);
|
||||
axisnames.put(FROM_PARENT_STRING, OpCodes.FROM_PARENT);
|
||||
axisnames.put(FROM_PRECEDING_STRING, OpCodes.FROM_PRECEDING);
|
||||
axisnames.put(FROM_PRECEDING_SIBLINGS_STRING, OpCodes.FROM_PRECEDING_SIBLINGS);
|
||||
axisnames.put(FROM_SELF_STRING, OpCodes.FROM_SELF);
|
||||
axisnames.put(FROM_NAMESPACE_STRING, OpCodes.FROM_NAMESPACE);
|
||||
m_axisnames = Collections.unmodifiableMap(axisnames);
|
||||
|
||||
nodetypes.put(NODETYPE_COMMENT_STRING, OpCodes.NODETYPE_COMMENT);
|
||||
nodetypes.put(NODETYPE_TEXT_STRING, OpCodes.NODETYPE_TEXT);
|
||||
nodetypes.put(NODETYPE_PI_STRING, OpCodes.NODETYPE_PI);
|
||||
nodetypes.put(NODETYPE_NODE_STRING, OpCodes.NODETYPE_NODE);
|
||||
nodetypes.put(NODETYPE_ANYELEMENT_STRING, OpCodes.NODETYPE_ANYELEMENT);
|
||||
m_nodetypes = Collections.unmodifiableMap(nodetypes);
|
||||
|
||||
keywords.put(FROM_SELF_ABBREVIATED_STRING, OpCodes.FROM_SELF);
|
||||
keywords.put(FUNC_ID_STRING, FunctionTable.FUNC_ID);
|
||||
keywords.put(FUNC_KEY_STRING, FunctionTable.FUNC_KEY);
|
||||
m_keywords = Collections.unmodifiableMap(keywords);
|
||||
|
||||
nodetests.put(NODETYPE_COMMENT_STRING, OpCodes.NODETYPE_COMMENT);
|
||||
nodetests.put(NODETYPE_TEXT_STRING, OpCodes.NODETYPE_TEXT);
|
||||
nodetests.put(NODETYPE_PI_STRING, OpCodes.NODETYPE_PI);
|
||||
nodetests.put(NODETYPE_NODE_STRING, OpCodes.NODETYPE_NODE);
|
||||
m_nodetests = Collections.unmodifiableMap(nodetests);
|
||||
}
|
||||
|
||||
static Integer getAxisName(String key) {
|
||||
return m_axisnames.get(key);
|
||||
}
|
||||
|
||||
static Integer lookupNodeTest(String key) {
|
||||
return m_nodetests.get(key);
|
||||
}
|
||||
|
||||
static Integer getKeyWord(String key) {
|
||||
return m_keywords.get(key);
|
||||
}
|
||||
|
||||
static Integer getNodeType(String key) {
|
||||
return m_nodetypes.get(key);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,741 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.compiler;
|
||||
|
||||
import java.util.Vector;
|
||||
|
||||
import com.sun.org.apache.xalan.internal.res.XSLMessages;
|
||||
import com.sun.org.apache.xml.internal.utils.PrefixResolver;
|
||||
import com.sun.org.apache.xpath.internal.res.XPATHErrorResources;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import jdk.xml.internal.XMLSecurityManager;
|
||||
import jdk.xml.internal.XMLSecurityManager.Limit;
|
||||
|
||||
/**
|
||||
* This class is in charge of lexical processing of the XPath
|
||||
* expression into tokens.
|
||||
*/
|
||||
class Lexer
|
||||
{
|
||||
|
||||
/**
|
||||
* The target XPath.
|
||||
*/
|
||||
private Compiler m_compiler;
|
||||
|
||||
/**
|
||||
* The prefix resolver to map prefixes to namespaces in the XPath.
|
||||
*/
|
||||
PrefixResolver m_namespaceContext;
|
||||
|
||||
/**
|
||||
* The XPath processor object.
|
||||
*/
|
||||
XPathParser m_processor;
|
||||
|
||||
/**
|
||||
* This value is added to each element name in the TARGETEXTRA
|
||||
* that is a 'target' (right-most top-level element name).
|
||||
*/
|
||||
static final int TARGETEXTRA = 10000;
|
||||
|
||||
/**
|
||||
* Ignore this, it is going away.
|
||||
* This holds a map to the m_tokenQueue that tells where the top-level elements are.
|
||||
* It is used for pattern matching so the m_tokenQueue can be walked backwards.
|
||||
* Each element that is a 'target', (right-most top level element name) has
|
||||
* TARGETEXTRA added to it.
|
||||
*
|
||||
*/
|
||||
private int m_patternMap[] = new int[100];
|
||||
|
||||
/**
|
||||
* Ignore this, it is going away.
|
||||
* The number of elements that m_patternMap maps;
|
||||
*/
|
||||
private int m_patternMapSize;
|
||||
|
||||
// XML security manager
|
||||
XMLSecurityManager m_xmlSecMgr;
|
||||
|
||||
// operator limit
|
||||
private int m_opCountLimit;
|
||||
|
||||
// group limit
|
||||
private int m_grpCountLimit;
|
||||
|
||||
// count of operators
|
||||
private int m_opCount;
|
||||
|
||||
// count of groups
|
||||
private int m_grpCount;
|
||||
|
||||
// indicate whether the current token is a literal
|
||||
private boolean isLiteral = false;
|
||||
|
||||
/**
|
||||
* Create a Lexer object.
|
||||
*
|
||||
* @param compiler The owning compiler for this lexer.
|
||||
* @param resolver The prefix resolver for mapping qualified name prefixes
|
||||
* to namespace URIs.
|
||||
* @param xpathProcessor The parser that is processing strings to opcodes.
|
||||
* @param xmlSecMgr the XML security manager
|
||||
*/
|
||||
Lexer(Compiler compiler, PrefixResolver resolver,
|
||||
XPathParser xpathProcessor, XMLSecurityManager xmlSecMgr)
|
||||
{
|
||||
m_compiler = compiler;
|
||||
m_namespaceContext = resolver;
|
||||
m_processor = xpathProcessor;
|
||||
m_xmlSecMgr = xmlSecMgr;
|
||||
/**
|
||||
* No limits if XML Security Manager is null. Applications using XPath through
|
||||
* the public API always have a XMLSecurityManager. Applications invoking
|
||||
* the internal XPath API shall consider using the public API instead.
|
||||
*/
|
||||
m_opCountLimit = (xmlSecMgr != null) ? xmlSecMgr.getLimit(Limit.XPATH_OP_LIMIT) : 0;
|
||||
m_grpCountLimit = (xmlSecMgr != null) ? xmlSecMgr.getLimit(Limit.XPATH_GROUP_LIMIT) : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Walk through the expression and build a token queue, and a map of the top-level
|
||||
* elements.
|
||||
* @param pat XSLT Expression.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
void tokenize(String pat) throws javax.xml.transform.TransformerException
|
||||
{
|
||||
tokenize(pat, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Walk through the expression and build a token queue, and a map of the top-level
|
||||
* elements.
|
||||
* @param pat XSLT Expression.
|
||||
* @param targetStrings Vector to hold Strings, may be null.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
void tokenize(String pat, Vector targetStrings)
|
||||
throws javax.xml.transform.TransformerException
|
||||
{
|
||||
|
||||
m_compiler.m_currentPattern = pat;
|
||||
m_patternMapSize = 0;
|
||||
|
||||
// This needs to grow too.
|
||||
m_compiler.m_opMap = new OpMapVector(OpMap.MAXTOKENQUEUESIZE * 5, OpMap.BLOCKTOKENQUEUESIZE * 5, OpMap.MAPINDEX_LENGTH);
|
||||
|
||||
int nChars = pat.length();
|
||||
int startSubstring = -1;
|
||||
int posOfNSSep = -1;
|
||||
boolean isStartOfPat = true;
|
||||
boolean isAttrName = false;
|
||||
boolean isNum = false;
|
||||
|
||||
// Nesting of '[' so we can know if the given element should be
|
||||
// counted inside the m_patternMap.
|
||||
int nesting = 0;
|
||||
|
||||
// char[] chars = pat.toCharArray();
|
||||
for (int i = 0; i < nChars; i++)
|
||||
{
|
||||
char c = pat.charAt(i);
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case Token.DQ :
|
||||
{
|
||||
if (startSubstring != -1)
|
||||
{
|
||||
isNum = false;
|
||||
isStartOfPat = mapPatternElemPos(nesting, isStartOfPat, isAttrName);
|
||||
isAttrName = false;
|
||||
|
||||
if (-1 != posOfNSSep)
|
||||
{
|
||||
posOfNSSep = mapNSTokens(pat, startSubstring, posOfNSSep, i);
|
||||
}
|
||||
else
|
||||
{
|
||||
addToTokenQueue(pat.substring(startSubstring, i));
|
||||
}
|
||||
}
|
||||
|
||||
startSubstring = i;
|
||||
|
||||
for (i++; (i < nChars) && ((c = pat.charAt(i)) != '\"'); i++);
|
||||
|
||||
if (c == '\"' && i < nChars)
|
||||
{
|
||||
addToTokenQueue(pat.substring(startSubstring, i + 1));
|
||||
|
||||
startSubstring = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_processor.error(XPATHErrorResources.ER_EXPECTED_DOUBLE_QUOTE,
|
||||
null); //"misquoted literal... expected double quote!");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Token.SQ :
|
||||
if (startSubstring != -1)
|
||||
{
|
||||
isNum = false;
|
||||
isStartOfPat = mapPatternElemPos(nesting, isStartOfPat, isAttrName);
|
||||
isAttrName = false;
|
||||
|
||||
if (-1 != posOfNSSep)
|
||||
{
|
||||
posOfNSSep = mapNSTokens(pat, startSubstring, posOfNSSep, i);
|
||||
}
|
||||
else
|
||||
{
|
||||
addToTokenQueue(pat.substring(startSubstring, i));
|
||||
}
|
||||
}
|
||||
|
||||
startSubstring = i;
|
||||
|
||||
for (i++; (i < nChars) && ((c = pat.charAt(i)) != Token.SQ); i++);
|
||||
|
||||
if (c == Token.SQ && i < nChars)
|
||||
{
|
||||
addToTokenQueue(pat.substring(startSubstring, i + 1));
|
||||
|
||||
startSubstring = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_processor.error(XPATHErrorResources.ER_EXPECTED_SINGLE_QUOTE,
|
||||
null); //"misquoted literal... expected single quote!");
|
||||
}
|
||||
break;
|
||||
case 0x0A :
|
||||
case 0x0D :
|
||||
case ' ' :
|
||||
case '\t' :
|
||||
if (startSubstring != -1)
|
||||
{
|
||||
isNum = false;
|
||||
isStartOfPat = mapPatternElemPos(nesting, isStartOfPat, isAttrName);
|
||||
isAttrName = false;
|
||||
|
||||
if (-1 != posOfNSSep)
|
||||
{
|
||||
posOfNSSep = mapNSTokens(pat, startSubstring, posOfNSSep, i);
|
||||
}
|
||||
else
|
||||
{
|
||||
// check operator symbol
|
||||
String s = pat.substring(startSubstring, i);
|
||||
if (Token.contains(s)) {
|
||||
m_opCount++;
|
||||
isLiteral = false;
|
||||
}
|
||||
addToTokenQueue(s);
|
||||
}
|
||||
|
||||
startSubstring = -1;
|
||||
}
|
||||
break;
|
||||
case Token.AT :
|
||||
isAttrName = true;
|
||||
|
||||
// fall-through on purpose
|
||||
case Token.MINUS :
|
||||
if (Token.MINUS == c)
|
||||
{
|
||||
if (!(isNum || (startSubstring == -1)))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
isNum = false;
|
||||
}
|
||||
|
||||
// fall-through on purpose
|
||||
case Token.LPAREN :
|
||||
case Token.LBRACK :
|
||||
case Token.RPAREN :
|
||||
case Token.RBRACK :
|
||||
case Token.VBAR :
|
||||
case Token.SLASH :
|
||||
case Token.STAR :
|
||||
case Token.PLUS :
|
||||
case Token.EQ :
|
||||
case Token.COMMA :
|
||||
case '\\' : // Unused at the moment
|
||||
case '^' : // Unused at the moment
|
||||
case Token.EM : // Unused at the moment
|
||||
case Token.DOLLAR :
|
||||
case Token.LT :
|
||||
case Token.GT :
|
||||
if (startSubstring != -1)
|
||||
{
|
||||
isNum = false;
|
||||
isStartOfPat = mapPatternElemPos(nesting, isStartOfPat, isAttrName);
|
||||
isAttrName = false;
|
||||
|
||||
if (-1 != posOfNSSep)
|
||||
{
|
||||
posOfNSSep = mapNSTokens(pat, startSubstring, posOfNSSep, i);
|
||||
}
|
||||
else
|
||||
{
|
||||
addToTokenQueue(pat.substring(startSubstring, i));
|
||||
}
|
||||
|
||||
startSubstring = -1;
|
||||
}
|
||||
else if ((Token.SLASH == c) && isStartOfPat)
|
||||
{
|
||||
isStartOfPat = mapPatternElemPos(nesting, isStartOfPat, isAttrName);
|
||||
}
|
||||
else if (Token.STAR == c)
|
||||
{
|
||||
isStartOfPat = mapPatternElemPos(nesting, isStartOfPat, isAttrName);
|
||||
isAttrName = false;
|
||||
}
|
||||
|
||||
if (0 == nesting)
|
||||
{
|
||||
if (Token.VBAR == c)
|
||||
{
|
||||
if (null != targetStrings)
|
||||
{
|
||||
recordTokenString(targetStrings);
|
||||
}
|
||||
|
||||
isStartOfPat = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ((Token.RPAREN == c) || (Token.RBRACK == c))
|
||||
{
|
||||
nesting--;
|
||||
}
|
||||
else if ((Token.LPAREN == c) || (Token.LBRACK == c))
|
||||
{
|
||||
nesting++;
|
||||
if (!isLiteral && (Token.LPAREN == c)) {
|
||||
m_grpCount++;
|
||||
m_opCount++;
|
||||
isLiteral = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ((Token.GT == c || Token.LT == c || Token.EQ == c) && Token.EQ != peekNext(pat, i)) {
|
||||
m_opCount++;
|
||||
isLiteral = false;
|
||||
}
|
||||
else if ((Token.LPAREN != c) && (Token.RPAREN != c) && (Token.RBRACK != c)) {
|
||||
m_opCount++;
|
||||
isLiteral = false;
|
||||
}
|
||||
|
||||
addToTokenQueue(pat.substring(i, i + 1));
|
||||
break;
|
||||
case Token.COLON :
|
||||
if (i>0)
|
||||
{
|
||||
if (posOfNSSep == (i - 1))
|
||||
{
|
||||
if (startSubstring != -1)
|
||||
{
|
||||
if (startSubstring < (i - 1))
|
||||
addToTokenQueue(pat.substring(startSubstring, i - 1));
|
||||
}
|
||||
|
||||
isNum = false;
|
||||
isAttrName = false;
|
||||
startSubstring = -1;
|
||||
posOfNSSep = -1;
|
||||
m_opCount++;
|
||||
addToTokenQueue(pat.substring(i - 1, i + 1));
|
||||
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
posOfNSSep = i;
|
||||
}
|
||||
}
|
||||
|
||||
// fall through on purpose
|
||||
default :
|
||||
isLiteral = true;
|
||||
if (-1 == startSubstring)
|
||||
{
|
||||
startSubstring = i;
|
||||
isNum = Character.isDigit(c);
|
||||
}
|
||||
else if (isNum)
|
||||
{
|
||||
isNum = Character.isDigit(c);
|
||||
}
|
||||
}
|
||||
if (m_grpCountLimit > 0 && m_grpCount > m_grpCountLimit) {
|
||||
throw new TransformerException(XSLMessages.createXPATHMessage(
|
||||
XPATHErrorResources.ER_XPATH_GROUP_LIMIT,
|
||||
new Object[]{Integer.toString(m_grpCount),
|
||||
Integer.toString(m_grpCountLimit),
|
||||
m_xmlSecMgr.getStateLiteral(Limit.XPATH_GROUP_LIMIT)}));
|
||||
}
|
||||
if (m_opCountLimit > 0 && m_opCount > m_opCountLimit) {
|
||||
throw new TransformerException(XSLMessages.createXPATHMessage(
|
||||
XPATHErrorResources.ER_XPATH_OPERATOR_LIMIT,
|
||||
new Object[]{Integer.toString(m_opCount),
|
||||
Integer.toString(m_opCountLimit),
|
||||
m_xmlSecMgr.getStateLiteral(Limit.XPATH_OP_LIMIT)}));
|
||||
}
|
||||
}
|
||||
|
||||
if (startSubstring != -1)
|
||||
{
|
||||
isNum = false;
|
||||
isStartOfPat = mapPatternElemPos(nesting, isStartOfPat, isAttrName);
|
||||
|
||||
if ((-1 != posOfNSSep) ||
|
||||
((m_namespaceContext != null) && (m_namespaceContext.handlesNullPrefixes())))
|
||||
{
|
||||
posOfNSSep = mapNSTokens(pat, startSubstring, posOfNSSep, nChars);
|
||||
}
|
||||
else
|
||||
{
|
||||
addToTokenQueue(pat.substring(startSubstring, nChars));
|
||||
}
|
||||
}
|
||||
|
||||
if (0 == m_compiler.getTokenQueueSize())
|
||||
{
|
||||
m_processor.error(XPATHErrorResources.ER_EMPTY_EXPRESSION, null); //"Empty expression!");
|
||||
}
|
||||
else if (null != targetStrings)
|
||||
{
|
||||
recordTokenString(targetStrings);
|
||||
}
|
||||
|
||||
m_processor.m_queueMark = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Peeks at the next character without advancing the index.
|
||||
* @param s the input string
|
||||
* @param index the current index
|
||||
* @return the next char
|
||||
*/
|
||||
private char peekNext(String s, int index) {
|
||||
if (index >= 0 && index < s.length() - 1) {
|
||||
return s.charAt(index + 1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Record the current position on the token queue as long as
|
||||
* this is a top-level element. Must be called before the
|
||||
* next token is added to the m_tokenQueue.
|
||||
*
|
||||
* @param nesting The nesting count for the pattern element.
|
||||
* @param isStart true if this is the start of a pattern.
|
||||
* @param isAttrName true if we have determined that this is an attribute name.
|
||||
*
|
||||
* @return true if this is the start of a pattern.
|
||||
*/
|
||||
private boolean mapPatternElemPos(int nesting, boolean isStart,
|
||||
boolean isAttrName)
|
||||
{
|
||||
|
||||
if (0 == nesting)
|
||||
{
|
||||
if(m_patternMapSize >= m_patternMap.length)
|
||||
{
|
||||
int patternMap[] = m_patternMap;
|
||||
int len = m_patternMap.length;
|
||||
m_patternMap = new int[m_patternMapSize + 100];
|
||||
System.arraycopy(patternMap, 0, m_patternMap, 0, len);
|
||||
}
|
||||
if (!isStart)
|
||||
{
|
||||
m_patternMap[m_patternMapSize - 1] -= TARGETEXTRA;
|
||||
}
|
||||
m_patternMap[m_patternMapSize] =
|
||||
(m_compiler.getTokenQueueSize() - (isAttrName ? 1 : 0)) + TARGETEXTRA;
|
||||
|
||||
m_patternMapSize++;
|
||||
|
||||
isStart = false;
|
||||
}
|
||||
|
||||
return isStart;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a map pos, return the corresponding token queue pos.
|
||||
*
|
||||
* @param i The index in the m_patternMap.
|
||||
*
|
||||
* @return the token queue position.
|
||||
*/
|
||||
private int getTokenQueuePosFromMap(int i)
|
||||
{
|
||||
|
||||
int pos = m_patternMap[i];
|
||||
|
||||
return (pos >= TARGETEXTRA) ? (pos - TARGETEXTRA) : pos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset token queue mark and m_token to a
|
||||
* given position.
|
||||
* @param mark The new position.
|
||||
*/
|
||||
private final void resetTokenMark(int mark)
|
||||
{
|
||||
|
||||
int qsz = m_compiler.getTokenQueueSize();
|
||||
|
||||
m_processor.m_queueMark = (mark > 0)
|
||||
? ((mark <= qsz) ? mark - 1 : mark) : 0;
|
||||
|
||||
if (m_processor.m_queueMark < qsz)
|
||||
{
|
||||
m_processor.m_token =
|
||||
(String) m_compiler.getTokenQueue().elementAt(m_processor.m_queueMark++);
|
||||
m_processor.m_tokenChar = m_processor.m_token.charAt(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_processor.m_token = null;
|
||||
m_processor.m_tokenChar = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a string, return the corresponding keyword token.
|
||||
*
|
||||
* @param key The keyword.
|
||||
*
|
||||
* @return An opcode value.
|
||||
*/
|
||||
final int getKeywordToken(String key)
|
||||
{
|
||||
|
||||
int tok;
|
||||
|
||||
try
|
||||
{
|
||||
Integer itok = (Integer) Keywords.getKeyWord(key);
|
||||
|
||||
tok = (null != itok) ? itok.intValue() : 0;
|
||||
}
|
||||
catch (NullPointerException npe)
|
||||
{
|
||||
tok = 0;
|
||||
}
|
||||
catch (ClassCastException cce)
|
||||
{
|
||||
tok = 0;
|
||||
}
|
||||
|
||||
return tok;
|
||||
}
|
||||
|
||||
/**
|
||||
* Record the current token in the passed vector.
|
||||
*
|
||||
* @param targetStrings Vector of string.
|
||||
*/
|
||||
private void recordTokenString(Vector targetStrings)
|
||||
{
|
||||
|
||||
int tokPos = getTokenQueuePosFromMap(m_patternMapSize - 1);
|
||||
|
||||
resetTokenMark(tokPos + 1);
|
||||
|
||||
if (m_processor.lookahead(Token.LPAREN, 1))
|
||||
{
|
||||
int tok = getKeywordToken(m_processor.m_token);
|
||||
|
||||
switch (tok)
|
||||
{
|
||||
case OpCodes.NODETYPE_COMMENT :
|
||||
targetStrings.addElement(PsuedoNames.PSEUDONAME_COMMENT);
|
||||
break;
|
||||
case OpCodes.NODETYPE_TEXT :
|
||||
targetStrings.addElement(PsuedoNames.PSEUDONAME_TEXT);
|
||||
break;
|
||||
case OpCodes.NODETYPE_NODE :
|
||||
targetStrings.addElement(PsuedoNames.PSEUDONAME_ANY);
|
||||
break;
|
||||
case OpCodes.NODETYPE_ROOT :
|
||||
targetStrings.addElement(PsuedoNames.PSEUDONAME_ROOT);
|
||||
break;
|
||||
case OpCodes.NODETYPE_ANYELEMENT :
|
||||
targetStrings.addElement(PsuedoNames.PSEUDONAME_ANY);
|
||||
break;
|
||||
case OpCodes.NODETYPE_PI :
|
||||
targetStrings.addElement(PsuedoNames.PSEUDONAME_ANY);
|
||||
break;
|
||||
default :
|
||||
targetStrings.addElement(PsuedoNames.PSEUDONAME_ANY);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_processor.tokenIs(Token.AT))
|
||||
{
|
||||
tokPos++;
|
||||
|
||||
resetTokenMark(tokPos + 1);
|
||||
}
|
||||
|
||||
if (m_processor.lookahead(Token.COLON, 1))
|
||||
{
|
||||
tokPos += 2;
|
||||
}
|
||||
|
||||
targetStrings.addElement(m_compiler.getTokenQueue().elementAt(tokPos));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a token to the token queue.
|
||||
*
|
||||
*
|
||||
* @param s The token.
|
||||
*/
|
||||
private final void addToTokenQueue(String s)
|
||||
{
|
||||
m_compiler.getTokenQueue().addElement(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* When a seperator token is found, see if there's a element name or
|
||||
* the like to map.
|
||||
*
|
||||
* @param pat The XPath name string.
|
||||
* @param startSubstring The start of the name string.
|
||||
* @param posOfNSSep The position of the namespace seperator (':').
|
||||
* @param posOfScan The end of the name index.
|
||||
*
|
||||
* @throws TransformerException
|
||||
*
|
||||
* @return -1 always.
|
||||
*/
|
||||
private int mapNSTokens(String pat, int startSubstring, int posOfNSSep,
|
||||
int posOfScan)
|
||||
throws TransformerException
|
||||
{
|
||||
|
||||
String prefix = "";
|
||||
|
||||
if ((startSubstring >= 0) && (posOfNSSep >= 0))
|
||||
{
|
||||
prefix = pat.substring(startSubstring, posOfNSSep);
|
||||
}
|
||||
String uName;
|
||||
|
||||
if ((null != m_namespaceContext) &&!prefix.equals("*")
|
||||
&&!prefix.equals("xmlns"))
|
||||
{
|
||||
try
|
||||
{
|
||||
if (prefix.length() > 0)
|
||||
uName = ((PrefixResolver) m_namespaceContext).getNamespaceForPrefix(
|
||||
prefix);
|
||||
else
|
||||
{
|
||||
|
||||
// Assume last was wildcard. This is not legal according
|
||||
// to the draft. Set the below to true to make namespace
|
||||
// wildcards work.
|
||||
if (false)
|
||||
{
|
||||
addToTokenQueue(":");
|
||||
|
||||
String s = pat.substring(posOfNSSep + 1, posOfScan);
|
||||
|
||||
if (s.length() > 0)
|
||||
addToTokenQueue(s);
|
||||
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
uName =
|
||||
((PrefixResolver) m_namespaceContext).getNamespaceForPrefix(
|
||||
prefix);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (ClassCastException cce)
|
||||
{
|
||||
uName = m_namespaceContext.getNamespaceForPrefix(prefix);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uName = prefix;
|
||||
}
|
||||
|
||||
if ((null != uName) && (uName.length() > 0))
|
||||
{
|
||||
addToTokenQueue(uName);
|
||||
addToTokenQueue(":");
|
||||
|
||||
String s = pat.substring(posOfNSSep + 1, posOfScan);
|
||||
|
||||
if (s.length() > 0)
|
||||
addToTokenQueue(s);
|
||||
}
|
||||
else
|
||||
{
|
||||
// To older XPath code it doesn't matter if
|
||||
// error() is called or errorForDOM3().
|
||||
m_processor.errorForDOM3(XPATHErrorResources.ER_PREFIX_MUST_RESOLVE,
|
||||
new String[] {prefix}); //"Prefix must resolve to a namespace: {0}";
|
||||
|
||||
/** old code commented out 17-Sep-2004
|
||||
// error("Could not locate namespace for prefix: "+prefix);
|
||||
// m_processor.error(XPATHErrorResources.ER_PREFIX_MUST_RESOLVE,
|
||||
// new String[] {prefix}); //"Prefix must resolve to a namespace: {0}";
|
||||
*/
|
||||
|
||||
/*** Old code commented out 10-Jan-2001
|
||||
addToTokenQueue(prefix);
|
||||
addToTokenQueue(":");
|
||||
|
||||
String s = pat.substring(posOfNSSep + 1, posOfScan);
|
||||
|
||||
if (s.length() > 0)
|
||||
addToTokenQueue(s);
|
||||
***/
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,633 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.compiler;
|
||||
|
||||
/**
|
||||
* Operations codes for XPath.
|
||||
*
|
||||
* Code for the descriptions of the operations codes:
|
||||
* [UPPER CASE] indicates a literal value,
|
||||
* [lower case] is a description of a value,
|
||||
* ([length] always indicates the length of the operation,
|
||||
* including the operations code and the length integer.)
|
||||
* {UPPER CASE} indicates the given production,
|
||||
* {description} is the description of a new production,
|
||||
* (For instance, {boolean expression} means some expression
|
||||
* that should be resolved to a boolean.)
|
||||
* * means that it occurs zero or more times,
|
||||
* + means that it occurs one or more times,
|
||||
* ? means that it is optional.
|
||||
*
|
||||
* returns: indicates what the production should return.
|
||||
*/
|
||||
public class OpCodes
|
||||
{
|
||||
|
||||
/**
|
||||
* [ENDOP]
|
||||
* Some operators may like to have a terminator.
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public static final int ENDOP = -1;
|
||||
|
||||
/**
|
||||
* [EMPTY]
|
||||
* Empty slot to indicate NULL.
|
||||
*/
|
||||
public static final int EMPTY = -2;
|
||||
|
||||
/**
|
||||
* [ELEMWILDCARD]
|
||||
* Means ELEMWILDCARD ("*"), used instead
|
||||
* of string index in some places.
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public static final int ELEMWILDCARD = -3;
|
||||
|
||||
/**
|
||||
* [OP_XPATH]
|
||||
* [length]
|
||||
* {expression}
|
||||
*
|
||||
* returns:
|
||||
* XNodeSet
|
||||
* XNumber
|
||||
* XString
|
||||
* XBoolean
|
||||
* XRTree
|
||||
* XObject
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public static final int OP_XPATH = 1;
|
||||
|
||||
/**
|
||||
* [OP_OR]
|
||||
* [length]
|
||||
* {boolean expression}
|
||||
* {boolean expression}
|
||||
*
|
||||
* returns:
|
||||
* XBoolean
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public static final int OP_OR = 2;
|
||||
|
||||
/**
|
||||
* [OP_AND]
|
||||
* [length]
|
||||
* {boolean expression}
|
||||
* {boolean expression}
|
||||
*
|
||||
* returns:
|
||||
* XBoolean
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public static final int OP_AND = 3;
|
||||
|
||||
/**
|
||||
* [OP_NOTEQUALS]
|
||||
* [length]
|
||||
* {expression}
|
||||
* {expression}
|
||||
*
|
||||
* returns:
|
||||
* XBoolean
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public static final int OP_NOTEQUALS = 4;
|
||||
|
||||
/**
|
||||
* [OP_EQUALS]
|
||||
* [length]
|
||||
* {expression}
|
||||
* {expression}
|
||||
*
|
||||
* returns:
|
||||
* XBoolean
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public static final int OP_EQUALS = 5;
|
||||
|
||||
/**
|
||||
* [OP_LTE] (less-than-or-equals)
|
||||
* [length]
|
||||
* {number expression}
|
||||
* {number expression}
|
||||
*
|
||||
* returns:
|
||||
* XBoolean
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public static final int OP_LTE = 6;
|
||||
|
||||
/**
|
||||
* [OP_LT] (less-than)
|
||||
* [length]
|
||||
* {number expression}
|
||||
* {number expression}
|
||||
*
|
||||
* returns:
|
||||
* XBoolean
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public static final int OP_LT = 7;
|
||||
|
||||
/**
|
||||
* [OP_GTE] (greater-than-or-equals)
|
||||
* [length]
|
||||
* {number expression}
|
||||
* {number expression}
|
||||
*
|
||||
* returns:
|
||||
* XBoolean
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public static final int OP_GTE = 8;
|
||||
|
||||
/**
|
||||
* [OP_GT] (greater-than)
|
||||
* [length]
|
||||
* {number expression}
|
||||
* {number expression}
|
||||
*
|
||||
* returns:
|
||||
* XBoolean
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public static final int OP_GT = 9;
|
||||
|
||||
/**
|
||||
* [OP_PLUS]
|
||||
* [length]
|
||||
* {number expression}
|
||||
* {number expression}
|
||||
*
|
||||
* returns:
|
||||
* XNumber
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public static final int OP_PLUS = 10;
|
||||
|
||||
/**
|
||||
* [OP_MINUS]
|
||||
* [length]
|
||||
* {number expression}
|
||||
* {number expression}
|
||||
*
|
||||
* returns:
|
||||
* XNumber
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public static final int OP_MINUS = 11;
|
||||
|
||||
/**
|
||||
* [OP_MULT]
|
||||
* [length]
|
||||
* {number expression}
|
||||
* {number expression}
|
||||
*
|
||||
* returns:
|
||||
* XNumber
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public static final int OP_MULT = 12;
|
||||
|
||||
/**
|
||||
* [OP_DIV]
|
||||
* [length]
|
||||
* {number expression}
|
||||
* {number expression}
|
||||
*
|
||||
* returns:
|
||||
* XNumber
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public static final int OP_DIV = 13;
|
||||
|
||||
/**
|
||||
* [OP_MOD]
|
||||
* [length]
|
||||
* {number expression}
|
||||
* {number expression}
|
||||
*
|
||||
* returns:
|
||||
* XNumber
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public static final int OP_MOD = 14;
|
||||
|
||||
/**
|
||||
* [OP_QUO]
|
||||
* [length]
|
||||
* {number expression}
|
||||
* {number expression}
|
||||
*
|
||||
* returns:
|
||||
* XNumber
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public static final int OP_QUO = 15;
|
||||
|
||||
/**
|
||||
* [OP_NEG]
|
||||
* [length]
|
||||
* {number expression}
|
||||
*
|
||||
* returns:
|
||||
* XNumber
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public static final int OP_NEG = 16;
|
||||
|
||||
/**
|
||||
* [OP_STRING] (cast operation)
|
||||
* [length]
|
||||
* {expression}
|
||||
*
|
||||
* returns:
|
||||
* XString
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public static final int OP_STRING = 17;
|
||||
|
||||
/**
|
||||
* [OP_BOOL] (cast operation)
|
||||
* [length]
|
||||
* {expression}
|
||||
*
|
||||
* returns:
|
||||
* XBoolean
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public static final int OP_BOOL = 18;
|
||||
|
||||
/**
|
||||
* [OP_NUMBER] (cast operation)
|
||||
* [length]
|
||||
* {expression}
|
||||
*
|
||||
* returns:
|
||||
* XBoolean
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public static final int OP_NUMBER = 19;
|
||||
|
||||
/**
|
||||
* [OP_UNION]
|
||||
* [length]
|
||||
* {PathExpr}+
|
||||
*
|
||||
* returns:
|
||||
* XNodeSet
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public static final int OP_UNION = 20;
|
||||
|
||||
/**
|
||||
* [OP_LITERAL]
|
||||
* [3]
|
||||
* [index to token]
|
||||
*
|
||||
* returns:
|
||||
* XString
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public static final int OP_LITERAL = 21;
|
||||
|
||||
/** The low opcode for nodesets, needed by getFirstPredicateOpPos and
|
||||
* getNextStepPos. */
|
||||
static final int FIRST_NODESET_OP = 22;
|
||||
|
||||
/**
|
||||
* [OP_VARIABLE]
|
||||
* [4]
|
||||
* [index to namespace token, or EMPTY]
|
||||
* [index to function name token]
|
||||
*
|
||||
* returns:
|
||||
* XString
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public static final int OP_VARIABLE = 22;
|
||||
|
||||
/**
|
||||
* [OP_GROUP]
|
||||
* [length]
|
||||
* {expression}
|
||||
*
|
||||
* returns:
|
||||
* XNodeSet
|
||||
* XNumber
|
||||
* XString
|
||||
* XBoolean
|
||||
* XRTree
|
||||
* XObject
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public static final int OP_GROUP = 23;
|
||||
|
||||
/**
|
||||
* [OP_EXTFUNCTION] (Extension function.)
|
||||
* [length]
|
||||
* [index to namespace token]
|
||||
* [index to function name token]
|
||||
* {OP_ARGUMENT}
|
||||
*
|
||||
* returns:
|
||||
* XNodeSet
|
||||
* XNumber
|
||||
* XString
|
||||
* XBoolean
|
||||
* XRTree
|
||||
* XObject
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public static final int OP_EXTFUNCTION = 24;
|
||||
|
||||
/**
|
||||
* [OP_FUNCTION]
|
||||
* [length]
|
||||
* [FUNC_name]
|
||||
* {OP_ARGUMENT}
|
||||
* [ENDOP]
|
||||
*
|
||||
* returns:
|
||||
* XNodeSet
|
||||
* XNumber
|
||||
* XString
|
||||
* XBoolean
|
||||
* XRTree
|
||||
* XObject
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public static final int OP_FUNCTION = 25;
|
||||
|
||||
/** The last opcode for stuff that can be a nodeset. */
|
||||
static final int LAST_NODESET_OP = 25;
|
||||
|
||||
/**
|
||||
* [OP_ARGUMENT] (Function argument.)
|
||||
* [length]
|
||||
* {expression}
|
||||
*
|
||||
* returns:
|
||||
* XNodeSet
|
||||
* XNumber
|
||||
* XString
|
||||
* XBoolean
|
||||
* XRTree
|
||||
* XObject
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public static final int OP_ARGUMENT = 26;
|
||||
|
||||
/**
|
||||
* [OP_NUMBERLIT] (Number literal.)
|
||||
* [3]
|
||||
* [index to token]
|
||||
*
|
||||
* returns:
|
||||
* XString
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public static final int OP_NUMBERLIT = 27;
|
||||
|
||||
/**
|
||||
* [OP_LOCATIONPATH]
|
||||
* [length]
|
||||
* {FROM_stepType}
|
||||
* | {function}
|
||||
* {predicate}
|
||||
* [ENDOP]
|
||||
*
|
||||
* (Note that element and attribute namespaces and
|
||||
* names can be wildcarded '*'.)
|
||||
*
|
||||
* returns:
|
||||
* XNodeSet
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public static final int OP_LOCATIONPATH = 28;
|
||||
|
||||
// public static final int LOCATIONPATHEX_MASK = 0x0000FFFF;
|
||||
// public static final int LOCATIONPATHEX_ISSIMPLE = 0x00010000;
|
||||
// public static final int OP_LOCATIONPATH_EX = (28 | 0x00010000);
|
||||
|
||||
/**
|
||||
* [OP_PREDICATE]
|
||||
* [length]
|
||||
* {expression}
|
||||
* [ENDOP] (For safety)
|
||||
*
|
||||
* returns:
|
||||
* XBoolean or XNumber
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public static final int OP_PREDICATE = 29;
|
||||
|
||||
/**
|
||||
* [OP_MATCHPATTERN]
|
||||
* [length]
|
||||
* {PathExpr}+
|
||||
*
|
||||
* returns:
|
||||
* XNodeSet
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public static final int OP_MATCHPATTERN = 30;
|
||||
|
||||
/**
|
||||
* [OP_LOCATIONPATHPATTERN]
|
||||
* [length]
|
||||
* {FROM_stepType}
|
||||
* | {function}{predicate}
|
||||
* [ENDOP]
|
||||
* returns:
|
||||
* XNodeSet
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public static final int OP_LOCATIONPATHPATTERN = 31;
|
||||
|
||||
/**
|
||||
* [NODETYPE_COMMENT]
|
||||
* No size or arguments.
|
||||
* Note: must not overlap function OP number!
|
||||
*
|
||||
* returns:
|
||||
* XBoolean
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public static final int NODETYPE_COMMENT = 1030;
|
||||
|
||||
/**
|
||||
* [NODETYPE_TEXT]
|
||||
* No size or arguments.
|
||||
* Note: must not overlap function OP number!
|
||||
*
|
||||
* returns:
|
||||
* XBoolean
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public static final int NODETYPE_TEXT = 1031;
|
||||
|
||||
/**
|
||||
* [NODETYPE_PI]
|
||||
* [index to token]
|
||||
* Note: must not overlap function OP number!
|
||||
*
|
||||
* returns:
|
||||
* XBoolean
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public static final int NODETYPE_PI = 1032;
|
||||
|
||||
/**
|
||||
* [NODETYPE_NODE]
|
||||
* No size or arguments.
|
||||
* Note: must not overlap function OP number!
|
||||
*
|
||||
* returns:
|
||||
* XBoolean
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public static final int NODETYPE_NODE = 1033;
|
||||
|
||||
/**
|
||||
* [NODENAME]
|
||||
* [index to ns token or EMPTY]
|
||||
* [index to name token]
|
||||
*
|
||||
* returns:
|
||||
* XBoolean
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public static final int NODENAME = 34;
|
||||
|
||||
/**
|
||||
* [NODETYPE_ROOT]
|
||||
* No size or arguments.
|
||||
*
|
||||
* returns:
|
||||
* XBoolean
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public static final int NODETYPE_ROOT = 35;
|
||||
|
||||
/**
|
||||
* [NODETYPE_ANY]
|
||||
* No size or arguments.
|
||||
*
|
||||
* returns:
|
||||
* XBoolean
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public static final int NODETYPE_ANYELEMENT = 36;
|
||||
|
||||
/**
|
||||
* [NODETYPE_ANY]
|
||||
* No size or arguments.
|
||||
*
|
||||
* returns:
|
||||
* XBoolean
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public static final int NODETYPE_FUNCTEST = 1034;
|
||||
|
||||
/**
|
||||
* [FROM_stepType]
|
||||
* [length, including predicates]
|
||||
* [length of just the step, without the predicates]
|
||||
* {node test}
|
||||
* {predicates}?
|
||||
*
|
||||
* returns:
|
||||
* XBoolean
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public static final int AXES_START_TYPES = 37;
|
||||
|
||||
/** ancestor axes opcode. */
|
||||
public static final int FROM_ANCESTORS = 37;
|
||||
|
||||
/** ancestor-or-self axes opcode. */
|
||||
public static final int FROM_ANCESTORS_OR_SELF = 38;
|
||||
|
||||
/** attribute axes opcode. */
|
||||
public static final int FROM_ATTRIBUTES = 39;
|
||||
|
||||
/** children axes opcode. */
|
||||
public static final int FROM_CHILDREN = 40;
|
||||
|
||||
/** descendants axes opcode. */
|
||||
public static final int FROM_DESCENDANTS = 41;
|
||||
|
||||
/** descendants-of-self axes opcode. */
|
||||
public static final int FROM_DESCENDANTS_OR_SELF = 42;
|
||||
|
||||
/** following axes opcode. */
|
||||
public static final int FROM_FOLLOWING = 43;
|
||||
|
||||
/** following-siblings axes opcode. */
|
||||
public static final int FROM_FOLLOWING_SIBLINGS = 44;
|
||||
|
||||
/** parent axes opcode. */
|
||||
public static final int FROM_PARENT = 45;
|
||||
|
||||
/** preceding axes opcode. */
|
||||
public static final int FROM_PRECEDING = 46;
|
||||
|
||||
/** preceding-sibling axes opcode. */
|
||||
public static final int FROM_PRECEDING_SIBLINGS = 47;
|
||||
|
||||
/** self axes opcode. */
|
||||
public static final int FROM_SELF = 48;
|
||||
|
||||
/** namespace axes opcode. */
|
||||
public static final int FROM_NAMESPACE = 49;
|
||||
|
||||
/** '/' axes opcode. */
|
||||
public static final int FROM_ROOT = 50;
|
||||
|
||||
/**
|
||||
* For match patterns.
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public static final int MATCH_ATTRIBUTE = 51;
|
||||
|
||||
/**
|
||||
* For match patterns.
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public static final int MATCH_ANY_ANCESTOR = 52;
|
||||
|
||||
/**
|
||||
* For match patterns.
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public static final int MATCH_IMMEDIATE_ANCESTOR = 53;
|
||||
|
||||
/** The end of the axes types. */
|
||||
public static final int AXES_END_TYPES = 53;
|
||||
|
||||
/** The next free ID. Please keep this up to date. */
|
||||
private static final int NEXT_FREE_ID = 99;
|
||||
}
|
||||
@@ -0,0 +1,456 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.compiler;
|
||||
|
||||
import com.sun.org.apache.xalan.internal.res.XSLMessages;
|
||||
import com.sun.org.apache.xml.internal.utils.ObjectVector;
|
||||
import com.sun.org.apache.xpath.internal.patterns.NodeTest;
|
||||
import com.sun.org.apache.xpath.internal.res.XPATHErrorResources;
|
||||
|
||||
/**
|
||||
* This class represents the data structure basics of the XPath
|
||||
* object.
|
||||
*/
|
||||
public class OpMap
|
||||
{
|
||||
|
||||
/**
|
||||
* The current pattern string, for diagnostics purposes
|
||||
*/
|
||||
protected String m_currentPattern;
|
||||
|
||||
/**
|
||||
* Return the expression as a string for diagnostics.
|
||||
*
|
||||
* @return The expression string.
|
||||
*/
|
||||
public String toString()
|
||||
{
|
||||
return m_currentPattern;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the expression as a string for diagnostics.
|
||||
*
|
||||
* @return The expression string.
|
||||
*/
|
||||
public String getPatternString()
|
||||
{
|
||||
return m_currentPattern;
|
||||
}
|
||||
|
||||
/**
|
||||
* The starting size of the token queue.
|
||||
*/
|
||||
static final int MAXTOKENQUEUESIZE = 500;
|
||||
|
||||
/*
|
||||
* Amount to grow token queue when it becomes full
|
||||
*/
|
||||
static final int BLOCKTOKENQUEUESIZE = 500;
|
||||
|
||||
/**
|
||||
* TokenStack is the queue of used tokens. The current token is the token at the
|
||||
* end of the m_tokenQueue. The idea is that the queue can be marked and a sequence
|
||||
* of tokens can be reused.
|
||||
*/
|
||||
ObjectVector m_tokenQueue = new ObjectVector(MAXTOKENQUEUESIZE, BLOCKTOKENQUEUESIZE);
|
||||
|
||||
/**
|
||||
* Get the XPath as a list of tokens.
|
||||
*
|
||||
* @return ObjectVector of tokens.
|
||||
*/
|
||||
public ObjectVector getTokenQueue()
|
||||
{
|
||||
return m_tokenQueue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the XPath as a list of tokens.
|
||||
*
|
||||
* @param pos index into token queue.
|
||||
*
|
||||
* @return The token, normally a string.
|
||||
*/
|
||||
public Object getToken(int pos)
|
||||
{
|
||||
return m_tokenQueue.elementAt(pos);
|
||||
}
|
||||
|
||||
/**
|
||||
* The current size of the token queue.
|
||||
*/
|
||||
// public int m_tokenQueueSize = 0;
|
||||
|
||||
/**
|
||||
* Get size of the token queue.
|
||||
*
|
||||
* @return The size of the token queue.
|
||||
*/
|
||||
public int getTokenQueueSize()
|
||||
{
|
||||
return m_tokenQueue.size();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* An operations map is used instead of a proper parse tree. It contains
|
||||
* operations codes and indexes into the m_tokenQueue.
|
||||
* I use an array instead of a full parse tree in order to cut down
|
||||
* on the number of objects created.
|
||||
*/
|
||||
OpMapVector m_opMap = null;
|
||||
|
||||
/**
|
||||
* Get the opcode list that describes the XPath operations. It contains
|
||||
* operations codes and indexes into the m_tokenQueue.
|
||||
* I use an array instead of a full parse tree in order to cut down
|
||||
* on the number of objects created.
|
||||
*
|
||||
* @return An IntVector that is the opcode list that describes the XPath operations.
|
||||
*/
|
||||
public OpMapVector getOpMap()
|
||||
{
|
||||
return m_opMap;
|
||||
}
|
||||
|
||||
// Position indexes
|
||||
|
||||
/**
|
||||
* The length is always the opcode position + 1.
|
||||
* Length is always expressed as the opcode+length bytes,
|
||||
* so it is always 2 or greater.
|
||||
*/
|
||||
public static final int MAPINDEX_LENGTH = 1;
|
||||
|
||||
/**
|
||||
* Replace the large arrays
|
||||
* with a small array.
|
||||
*/
|
||||
void shrink()
|
||||
{
|
||||
|
||||
int n = m_opMap.elementAt(MAPINDEX_LENGTH);
|
||||
m_opMap.setToSize(n + 4);
|
||||
|
||||
m_opMap.setElementAt(0,n);
|
||||
m_opMap.setElementAt(0,n+1);
|
||||
m_opMap.setElementAt(0,n+2);
|
||||
|
||||
|
||||
n = m_tokenQueue.size();
|
||||
m_tokenQueue.setToSize(n + 4);
|
||||
|
||||
m_tokenQueue.setElementAt(null,n);
|
||||
m_tokenQueue.setElementAt(null,n + 1);
|
||||
m_tokenQueue.setElementAt(null,n + 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an operation position, return the current op.
|
||||
*
|
||||
* @param opPos index into op map.
|
||||
* @return the op that corresponds to the opPos argument.
|
||||
*/
|
||||
public int getOp(int opPos)
|
||||
{
|
||||
return m_opMap.elementAt(opPos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the op at index to the given int.
|
||||
*
|
||||
* @param opPos index into op map.
|
||||
* @param value Value to set
|
||||
*/
|
||||
public void setOp(int opPos, int value)
|
||||
{
|
||||
m_opMap.setElementAt(value,opPos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an operation position, return the end position, i.e. the
|
||||
* beginning of the next operation.
|
||||
*
|
||||
* @param opPos An op position of an operation for which there is a size
|
||||
* entry following.
|
||||
* @return position of next operation in m_opMap.
|
||||
*/
|
||||
public int getNextOpPos(int opPos)
|
||||
{
|
||||
return opPos + m_opMap.elementAt(opPos + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a location step position, return the end position, i.e. the
|
||||
* beginning of the next step.
|
||||
*
|
||||
* @param opPos the position of a location step.
|
||||
* @return the position of the next location step.
|
||||
*/
|
||||
public int getNextStepPos(int opPos)
|
||||
{
|
||||
|
||||
int stepType = getOp(opPos);
|
||||
|
||||
if ((stepType >= OpCodes.AXES_START_TYPES)
|
||||
&& (stepType <= OpCodes.AXES_END_TYPES))
|
||||
{
|
||||
return getNextOpPos(opPos);
|
||||
}
|
||||
else if ((stepType >= OpCodes.FIRST_NODESET_OP)
|
||||
&& (stepType <= OpCodes.LAST_NODESET_OP))
|
||||
{
|
||||
int newOpPos = getNextOpPos(opPos);
|
||||
|
||||
while (OpCodes.OP_PREDICATE == getOp(newOpPos))
|
||||
{
|
||||
newOpPos = getNextOpPos(newOpPos);
|
||||
}
|
||||
|
||||
stepType = getOp(newOpPos);
|
||||
|
||||
if (!((stepType >= OpCodes.AXES_START_TYPES)
|
||||
&& (stepType <= OpCodes.AXES_END_TYPES)))
|
||||
{
|
||||
return OpCodes.ENDOP;
|
||||
}
|
||||
|
||||
return newOpPos;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new RuntimeException(
|
||||
XSLMessages.createXPATHMessage(XPATHErrorResources.ER_UNKNOWN_STEP, new Object[]{String.valueOf(stepType)}));
|
||||
//"Programmer's assertion in getNextStepPos: unknown stepType: " + stepType);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an operation position, return the end position, i.e. the
|
||||
* beginning of the next operation.
|
||||
*
|
||||
* @param opMap The operations map.
|
||||
* @param opPos index to operation, for which there is a size entry following.
|
||||
* @return position of next operation in m_opMap.
|
||||
*/
|
||||
public static int getNextOpPos(int[] opMap, int opPos)
|
||||
{
|
||||
return opPos + opMap[opPos + 1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an FROM_stepType position, return the position of the
|
||||
* first predicate, if there is one, or else this will point
|
||||
* to the end of the FROM_stepType.
|
||||
* Example:
|
||||
* int posOfPredicate = xpath.getNextOpPos(stepPos);
|
||||
* boolean hasPredicates =
|
||||
* OpCodes.OP_PREDICATE == xpath.getOp(posOfPredicate);
|
||||
*
|
||||
* @param opPos position of FROM_stepType op.
|
||||
* @return position of predicate in FROM_stepType structure.
|
||||
*/
|
||||
public int getFirstPredicateOpPos(int opPos)
|
||||
throws javax.xml.transform.TransformerException
|
||||
{
|
||||
|
||||
int stepType = m_opMap.elementAt(opPos);
|
||||
|
||||
if ((stepType >= OpCodes.AXES_START_TYPES)
|
||||
&& (stepType <= OpCodes.AXES_END_TYPES))
|
||||
{
|
||||
return opPos + m_opMap.elementAt(opPos + 2);
|
||||
}
|
||||
else if ((stepType >= OpCodes.FIRST_NODESET_OP)
|
||||
&& (stepType <= OpCodes.LAST_NODESET_OP))
|
||||
{
|
||||
return opPos + m_opMap.elementAt(opPos + 1);
|
||||
}
|
||||
else if(-2 == stepType)
|
||||
{
|
||||
return -2;
|
||||
}
|
||||
else
|
||||
{
|
||||
error(com.sun.org.apache.xpath.internal.res.XPATHErrorResources.ER_UNKNOWN_OPCODE,
|
||||
new Object[]{ String.valueOf(stepType) }); //"ERROR! Unknown op code: "+m_opMap[opPos]);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tell the user of an error, and probably throw an
|
||||
* exception.
|
||||
*
|
||||
* @param msg An error msgkey that corresponds to one of the constants found
|
||||
* in {@link com.sun.org.apache.xpath.internal.res.XPATHErrorResources}, which is
|
||||
* a key for a format string.
|
||||
* @param args An array of arguments represented in the format string, which
|
||||
* may be null.
|
||||
*
|
||||
* @throws TransformerException if the current ErrorListoner determines to
|
||||
* throw an exception.
|
||||
*/
|
||||
public void error(String msg, Object[] args) throws javax.xml.transform.TransformerException
|
||||
{
|
||||
|
||||
java.lang.String fmsg = com.sun.org.apache.xalan.internal.res.XSLMessages.createXPATHMessage(msg, args);
|
||||
|
||||
|
||||
throw new javax.xml.transform.TransformerException(fmsg);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Go to the first child of a given operation.
|
||||
*
|
||||
* @param opPos position of operation.
|
||||
*
|
||||
* @return The position of the first child of the operation.
|
||||
*/
|
||||
public static int getFirstChildPos(int opPos)
|
||||
{
|
||||
return opPos + 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the length of an operation.
|
||||
*
|
||||
* @param opPos The position of the operation in the op map.
|
||||
*
|
||||
* @return The size of the operation.
|
||||
*/
|
||||
public int getArgLength(int opPos)
|
||||
{
|
||||
return m_opMap.elementAt(opPos + MAPINDEX_LENGTH);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a location step, get the length of that step.
|
||||
*
|
||||
* @param opPos Position of location step in op map.
|
||||
*
|
||||
* @return The length of the step.
|
||||
*/
|
||||
public int getArgLengthOfStep(int opPos)
|
||||
{
|
||||
return m_opMap.elementAt(opPos + MAPINDEX_LENGTH + 1) - 3;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the first child position of a given location step.
|
||||
*
|
||||
* @param opPos Position of location step in the location map.
|
||||
*
|
||||
* @return The first child position of the step.
|
||||
*/
|
||||
public static int getFirstChildPosOfStep(int opPos)
|
||||
{
|
||||
return opPos + 3;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the test type of the step, i.e. NODETYPE_XXX value.
|
||||
*
|
||||
* @param opPosOfStep The position of the FROM_XXX step.
|
||||
*
|
||||
* @return NODETYPE_XXX value.
|
||||
*/
|
||||
public int getStepTestType(int opPosOfStep)
|
||||
{
|
||||
return m_opMap.elementAt(opPosOfStep + 3); // skip past op, len, len without predicates
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the namespace of the step.
|
||||
*
|
||||
* @param opPosOfStep The position of the FROM_XXX step.
|
||||
*
|
||||
* @return The step's namespace, NodeTest.WILD, or null for null namespace.
|
||||
*/
|
||||
public String getStepNS(int opPosOfStep)
|
||||
{
|
||||
|
||||
int argLenOfStep = getArgLengthOfStep(opPosOfStep);
|
||||
|
||||
// System.out.println("getStepNS.argLenOfStep: "+argLenOfStep);
|
||||
if (argLenOfStep == 3)
|
||||
{
|
||||
int index = m_opMap.elementAt(opPosOfStep + 4);
|
||||
|
||||
if (index >= 0)
|
||||
return (String) m_tokenQueue.elementAt(index);
|
||||
else if (OpCodes.ELEMWILDCARD == index)
|
||||
return NodeTest.WILD;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the local name of the step.
|
||||
* @param opPosOfStep The position of the FROM_XXX step.
|
||||
*
|
||||
* @return OpCodes.EMPTY, OpCodes.ELEMWILDCARD, or the local name.
|
||||
*/
|
||||
public String getStepLocalName(int opPosOfStep)
|
||||
{
|
||||
|
||||
int argLenOfStep = getArgLengthOfStep(opPosOfStep);
|
||||
|
||||
// System.out.println("getStepLocalName.argLenOfStep: "+argLenOfStep);
|
||||
int index;
|
||||
|
||||
switch (argLenOfStep)
|
||||
{
|
||||
case 0 :
|
||||
index = OpCodes.EMPTY;
|
||||
break;
|
||||
case 1 :
|
||||
index = OpCodes.ELEMWILDCARD;
|
||||
break;
|
||||
case 2 :
|
||||
index = m_opMap.elementAt(opPosOfStep + 4);
|
||||
break;
|
||||
case 3 :
|
||||
index = m_opMap.elementAt(opPosOfStep + 5);
|
||||
break;
|
||||
default :
|
||||
index = OpCodes.EMPTY;
|
||||
break; // Should assert error
|
||||
}
|
||||
|
||||
// int index = (argLenOfStep == 3) ? m_opMap[opPosOfStep+5]
|
||||
// : ((argLenOfStep == 1) ? -3 : -2);
|
||||
if (index >= 0)
|
||||
return (String) m_tokenQueue.elementAt(index).toString();
|
||||
else if (OpCodes.ELEMWILDCARD == index)
|
||||
return NodeTest.WILD;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.compiler;
|
||||
|
||||
/**
|
||||
*
|
||||
* Like IntVector, but used only for the OpMap array. Length of array
|
||||
* is kept in the m_lengthPos position of the array. Only the required methods
|
||||
* are in included here.
|
||||
* @xsl.usage internal
|
||||
*/
|
||||
public class OpMapVector {
|
||||
|
||||
/** Size of blocks to allocate */
|
||||
protected int m_blocksize;
|
||||
|
||||
/** Array of ints */
|
||||
protected int m_map[]; // IntStack is trying to see this directly
|
||||
|
||||
/** Position where size of array is kept */
|
||||
protected int m_lengthPos = 0;
|
||||
|
||||
/** Size of array */
|
||||
protected int m_mapSize;
|
||||
|
||||
/**
|
||||
* Construct a OpMapVector, using the given block size.
|
||||
*
|
||||
* @param blocksize Size of block to allocate
|
||||
*/
|
||||
public OpMapVector(int blocksize, int increaseSize, int lengthPos)
|
||||
{
|
||||
|
||||
m_blocksize = increaseSize;
|
||||
m_mapSize = blocksize;
|
||||
m_lengthPos = lengthPos;
|
||||
m_map = new int[blocksize];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the nth element.
|
||||
*
|
||||
* @param i index of object to get
|
||||
*
|
||||
* @return object at given index
|
||||
*/
|
||||
public final int elementAt(int i)
|
||||
{
|
||||
return m_map[i];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the component at the specified index of this vector to be the
|
||||
* specified object. The previous component at that position is discarded.
|
||||
*
|
||||
* The index must be a value greater than or equal to 0 and less
|
||||
* than the current size of the vector.
|
||||
*
|
||||
* @param value object to set
|
||||
* @param index Index of where to set the object
|
||||
*/
|
||||
public final void setElementAt(int value, int index)
|
||||
{
|
||||
if (index >= m_mapSize)
|
||||
{
|
||||
int oldSize = m_mapSize;
|
||||
|
||||
m_mapSize += m_blocksize;
|
||||
|
||||
int newMap[] = new int[m_mapSize];
|
||||
|
||||
System.arraycopy(m_map, 0, newMap, 0, oldSize);
|
||||
|
||||
m_map = newMap;
|
||||
}
|
||||
|
||||
m_map[index] = value;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Reset the array to the supplied size. No checking is done.
|
||||
*
|
||||
* @param size The size to trim to.
|
||||
*/
|
||||
public final void setToSize(int size) {
|
||||
|
||||
int newMap[] = new int[size];
|
||||
|
||||
System.arraycopy(m_map, 0, newMap, 0, m_map[m_lengthPos]);
|
||||
|
||||
m_mapSize = size;
|
||||
m_map = newMap;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.compiler;
|
||||
|
||||
/**
|
||||
* This is used to represent names of nodes that may not be named, like a
|
||||
* comment node.
|
||||
*/
|
||||
public class PsuedoNames
|
||||
{
|
||||
|
||||
/**
|
||||
* Psuedo name for a wild card pattern ('*').
|
||||
*/
|
||||
public static final String PSEUDONAME_ANY = "*";
|
||||
|
||||
/**
|
||||
* Psuedo name for the root node.
|
||||
*/
|
||||
public static final String PSEUDONAME_ROOT = "/";
|
||||
|
||||
/**
|
||||
* Psuedo name for a text node.
|
||||
*/
|
||||
public static final String PSEUDONAME_TEXT = "#text";
|
||||
|
||||
/**
|
||||
* Psuedo name for a comment node.
|
||||
*/
|
||||
public static final String PSEUDONAME_COMMENT = "#comment";
|
||||
|
||||
/**
|
||||
* Psuedo name for a processing instruction node.
|
||||
*/
|
||||
public static final String PSEUDONAME_PI = "#pi";
|
||||
|
||||
/**
|
||||
* Psuedo name for an unknown type value.
|
||||
*/
|
||||
public static final String PSEUDONAME_OTHER = "*";
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.org.apache.xpath.internal.compiler;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* XPath tokens
|
||||
*/
|
||||
public final class Token {
|
||||
static final char EM = '!';
|
||||
static final char EQ = '=';
|
||||
static final char LT = '<';
|
||||
static final char GT = '>';
|
||||
static final char PLUS = '+';
|
||||
static final char MINUS = '-';
|
||||
static final char STAR = '*';
|
||||
static final char VBAR = '|';
|
||||
static final char SLASH = '/';
|
||||
static final char LBRACK = '[';
|
||||
static final char RBRACK = ']';
|
||||
static final char LPAREN = '(';
|
||||
static final char RPAREN = ')';
|
||||
static final char COMMA = ',';
|
||||
static final char DOT = '.';
|
||||
static final char AT = '@';
|
||||
static final char US = '_';
|
||||
static final char COLON = ':';
|
||||
static final char SQ = '\'';
|
||||
static final char DQ = '"';
|
||||
static final char DOLLAR = '$';
|
||||
|
||||
static final String OR = "or";
|
||||
static final String AND = "and";
|
||||
static final String DIV = "div";
|
||||
static final String MOD = "mod";
|
||||
static final String QUO = "quo";
|
||||
static final String DOT_STR = ".";
|
||||
static final String DDOT = "..";
|
||||
static final String DCOLON = "::";
|
||||
static final String ATTR = "attribute";
|
||||
static final String CHILD = "child";
|
||||
|
||||
static final String[] OPERATORS = {OR, AND, DIV, MOD, QUO,
|
||||
DDOT, DCOLON, ATTR, CHILD};
|
||||
|
||||
public static boolean contains(String str) {
|
||||
for (String op : OPERATORS) {
|
||||
if (op.equals(str)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private Token() {
|
||||
//to prevent instantiation
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.compiler;
|
||||
|
||||
|
||||
/**
|
||||
* Class for XPath diagnostic functions.
|
||||
*/
|
||||
public class XPathDumper
|
||||
{
|
||||
|
||||
// deleted for the time being.
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,273 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* Copyright 2002-2005 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.
|
||||
*/
|
||||
/*
|
||||
* $Id: XPathEvaluatorImpl.java,v 1.2.4.1 2005/09/10 04:04:07 jeffsuttor Exp $
|
||||
*/
|
||||
|
||||
package com.sun.org.apache.xpath.internal.domapi;
|
||||
|
||||
import javax.xml.transform.TransformerException;
|
||||
|
||||
import com.sun.org.apache.xml.internal.utils.PrefixResolver;
|
||||
import com.sun.org.apache.xpath.internal.XPath;
|
||||
import com.sun.org.apache.xpath.internal.res.XPATHErrorResources;
|
||||
import com.sun.org.apache.xpath.internal.res.XPATHMessages;
|
||||
import org.w3c.dom.DOMException;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.xpath.XPathEvaluator;
|
||||
import org.w3c.dom.xpath.XPathException;
|
||||
import org.w3c.dom.xpath.XPathExpression;
|
||||
import org.w3c.dom.xpath.XPathNSResolver;
|
||||
|
||||
/**
|
||||
*
|
||||
* The class provides an implementation of XPathEvaluator according
|
||||
* to the DOM L3 XPath Specification, Working Group Note 26 February 2004.
|
||||
*
|
||||
* <p>See also the <a href='http://www.w3.org/TR/2004/NOTE-DOM-Level-3-XPath-20040226'>Document Object Model (DOM) Level 3 XPath Specification</a>.</p>
|
||||
*
|
||||
* </p>The evaluation of XPath expressions is provided by
|
||||
* <code>XPathEvaluator</code>, which will provide evaluation of XPath 1.0
|
||||
* expressions with no specialized extension functions or variables. It is
|
||||
* expected that the <code>XPathEvaluator</code> interface will be
|
||||
* implemented on the same object which implements the <code>Document</code>
|
||||
* interface in an implementation which supports the XPath DOM module.
|
||||
* <code>XPathEvaluator</code> implementations may be available from other
|
||||
* sources that may provide support for special extension functions or
|
||||
* variables which are not defined in this specification.</p>
|
||||
*
|
||||
* @see org.w3c.dom.xpath.XPathEvaluator
|
||||
*
|
||||
* @xsl.usage internal
|
||||
*/
|
||||
public final class XPathEvaluatorImpl implements XPathEvaluator {
|
||||
|
||||
/**
|
||||
* This prefix resolver is created whenever null is passed to the
|
||||
* evaluate method. Its purpose is to satisfy the DOM L3 XPath API
|
||||
* requirement that if a null prefix resolver is used, an exception
|
||||
* should only be thrown when an attempt is made to resolve a prefix.
|
||||
*/
|
||||
private class DummyPrefixResolver implements PrefixResolver {
|
||||
|
||||
/**
|
||||
* Constructor for DummyPrefixResolver.
|
||||
*/
|
||||
DummyPrefixResolver() {}
|
||||
|
||||
/**
|
||||
* @exception DOMException
|
||||
* NAMESPACE_ERR: Always throws this exceptionn
|
||||
*
|
||||
* @see com.sun.org.apache.xml.internal.utils.PrefixResolver#getNamespaceForPrefix(String, Node)
|
||||
*/
|
||||
public String getNamespaceForPrefix(String prefix, Node context) {
|
||||
String fmsg = XPATHMessages.createXPATHMessage(XPATHErrorResources.ER_NULL_RESOLVER, null);
|
||||
throw new DOMException(DOMException.NAMESPACE_ERR, fmsg); // Unable to resolve prefix with null prefix resolver.
|
||||
}
|
||||
|
||||
/**
|
||||
* @exception DOMException
|
||||
* NAMESPACE_ERR: Always throws this exceptionn
|
||||
*
|
||||
* @see com.sun.org.apache.xml.internal.utils.PrefixResolver#getNamespaceForPrefix(String)
|
||||
*/
|
||||
public String getNamespaceForPrefix(String prefix) {
|
||||
return getNamespaceForPrefix(prefix,null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.sun.org.apache.xml.internal.utils.PrefixResolver#handlesNullPrefixes()
|
||||
*/
|
||||
public boolean handlesNullPrefixes() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.sun.org.apache.xml.internal.utils.PrefixResolver#getBaseIdentifier()
|
||||
*/
|
||||
public String getBaseIdentifier() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The document to be searched to parallel the case where the XPathEvaluator
|
||||
* is obtained by casting a Document.
|
||||
*/
|
||||
private final Document m_doc;
|
||||
|
||||
/**
|
||||
* Constructor for XPathEvaluatorImpl.
|
||||
*
|
||||
* @param doc The document to be searched, to parallel the case where''
|
||||
* the XPathEvaluator is obtained by casting the document.
|
||||
*/
|
||||
public XPathEvaluatorImpl(Document doc) {
|
||||
m_doc = doc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor in the case that the XPath expression can be evaluated
|
||||
* without needing an XML document at all.
|
||||
*
|
||||
*/
|
||||
public XPathEvaluatorImpl() {
|
||||
m_doc = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a parsed XPath expression with resolved namespaces. This is
|
||||
* useful when an expression will be reused in an application since it
|
||||
* makes it possible to compile the expression string into a more
|
||||
* efficient internal form and preresolve all namespace prefixes which
|
||||
* occur within the expression.
|
||||
*
|
||||
* @param expression The XPath expression string to be parsed.
|
||||
* @param resolver The <code>resolver</code> permits translation of
|
||||
* prefixes within the XPath expression into appropriate namespace URIs
|
||||
* . If this is specified as <code>null</code>, any namespace prefix
|
||||
* within the expression will result in <code>DOMException</code>
|
||||
* being thrown with the code <code>NAMESPACE_ERR</code>.
|
||||
* @return The compiled form of the XPath expression.
|
||||
* @exception XPathException
|
||||
* INVALID_EXPRESSION_ERR: Raised if the expression is not legal
|
||||
* according to the rules of the <code>XPathEvaluator</code>i
|
||||
* @exception DOMException
|
||||
* NAMESPACE_ERR: Raised if the expression contains namespace prefixes
|
||||
* which cannot be resolved by the specified
|
||||
* <code>XPathNSResolver</code>.
|
||||
*
|
||||
* @see org.w3c.dom.xpath.XPathEvaluator#createExpression(String, XPathNSResolver)
|
||||
*/
|
||||
public XPathExpression createExpression(
|
||||
String expression,
|
||||
XPathNSResolver resolver)
|
||||
throws XPathException, DOMException {
|
||||
|
||||
try {
|
||||
|
||||
// If the resolver is null, create a dummy prefix resolver
|
||||
XPath xpath = new XPath(expression,null,
|
||||
((null == resolver) ? new DummyPrefixResolver() : ((PrefixResolver)resolver)),
|
||||
XPath.SELECT);
|
||||
|
||||
return new XPathExpressionImpl(xpath, m_doc);
|
||||
|
||||
} catch (TransformerException e) {
|
||||
// Need to pass back exception code DOMException.NAMESPACE_ERR also.
|
||||
// Error found in DOM Level 3 XPath Test Suite.
|
||||
if(e instanceof XPathStylesheetDOM3Exception)
|
||||
throw new DOMException(DOMException.NAMESPACE_ERR,e.getMessageAndLocation());
|
||||
else
|
||||
throw new XPathException(XPathException.INVALID_EXPRESSION_ERR,e.getMessageAndLocation());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adapts any DOM node to resolve namespaces so that an XPath expression
|
||||
* can be easily evaluated relative to the context of the node where it
|
||||
* appeared within the document. This adapter works like the DOM Level 3
|
||||
* method <code>lookupNamespaceURI</code> on nodes in resolving the
|
||||
* namespaceURI from a given prefix using the current information available
|
||||
* in the node's hierarchy at the time lookupNamespaceURI is called, also
|
||||
* correctly resolving the implicit xml prefix.
|
||||
*
|
||||
* @param nodeResolver The node to be used as a context for namespace
|
||||
* resolution.
|
||||
* @return <code>XPathNSResolver</code> which resolves namespaces with
|
||||
* respect to the definitions in scope for a specified node.
|
||||
*
|
||||
* @see org.w3c.dom.xpath.XPathEvaluator#createNSResolver(Node)
|
||||
*/
|
||||
public XPathNSResolver createNSResolver(Node nodeResolver) {
|
||||
|
||||
return new XPathNSResolverImpl((nodeResolver.getNodeType() == Node.DOCUMENT_NODE)
|
||||
? ((Document) nodeResolver).getDocumentElement() : nodeResolver);
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluates an XPath expression string and returns a result of the
|
||||
* specified type if possible.
|
||||
*
|
||||
* @param expression The XPath expression string to be parsed and
|
||||
* evaluated.
|
||||
* @param contextNode The <code>context</code> is context node for the
|
||||
* evaluation of this XPath expression. If the XPathEvaluator was
|
||||
* obtained by casting the <code>Document</code> then this must be
|
||||
* owned by the same document and must be a <code>Document</code>,
|
||||
* <code>Element</code>, <code>Attribute</code>, <code>Text</code>,
|
||||
* <code>CDATASection</code>, <code>Comment</code>,
|
||||
* <code>ProcessingInstruction</code>, or <code>XPathNamespace</code>
|
||||
* node. If the context node is a <code>Text</code> or a
|
||||
* <code>CDATASection</code>, then the context is interpreted as the
|
||||
* whole logical text node as seen by XPath, unless the node is empty
|
||||
* in which case it may not serve as the XPath context.
|
||||
* @param resolver The <code>resolver</code> permits translation of
|
||||
* prefixes within the XPath expression into appropriate namespace URIs
|
||||
* . If this is specified as <code>null</code>, any namespace prefix
|
||||
* within the expression will result in <code>DOMException</code>
|
||||
* being thrown with the code <code>NAMESPACE_ERR</code>.
|
||||
* @param type If a specific <code>type</code> is specified, then the
|
||||
* result will be coerced to return the specified type relying on
|
||||
* XPath type conversions and fail if the desired coercion is not
|
||||
* possible. This must be one of the type codes of
|
||||
* <code>XPathResult</code>.
|
||||
* @param result The <code>result</code> specifies a specific result
|
||||
* object which may be reused and returned by this method. If this is
|
||||
* specified as <code>null</code>or the implementation does not reuse
|
||||
* the specified result, a new result object will be constructed and
|
||||
* returned.For XPath 1.0 results, this object will be of type
|
||||
* <code>XPathResult</code>.
|
||||
* @return The result of the evaluation of the XPath expression.For XPath
|
||||
* 1.0 results, this object will be of type <code>XPathResult</code>.
|
||||
* @exception XPathException
|
||||
* INVALID_EXPRESSION_ERR: Raised if the expression is not legal
|
||||
* according to the rules of the <code>XPathEvaluator</code>i
|
||||
* <br>TYPE_ERR: Raised if the result cannot be converted to return the
|
||||
* specified type.
|
||||
* @exception DOMException
|
||||
* NAMESPACE_ERR: Raised if the expression contains namespace prefixes
|
||||
* which cannot be resolved by the specified
|
||||
* <code>XPathNSResolver</code>.
|
||||
* <br>WRONG_DOCUMENT_ERR: The Node is from a document that is not
|
||||
* supported by this XPathEvaluator.
|
||||
* <br>NOT_SUPPORTED_ERR: The Node is not a type permitted as an XPath
|
||||
* context node.
|
||||
*
|
||||
* @see org.w3c.dom.xpath.XPathEvaluator#evaluate(String, Node, XPathNSResolver, short, XPathResult)
|
||||
*/
|
||||
public Object evaluate(
|
||||
String expression,
|
||||
Node contextNode,
|
||||
XPathNSResolver resolver,
|
||||
short type,
|
||||
Object result)
|
||||
throws XPathException, DOMException {
|
||||
|
||||
XPathExpression xpathExpression = createExpression(expression, resolver);
|
||||
|
||||
return xpathExpression.evaluate(contextNode, type, result);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* Copyright 2002-2005 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.
|
||||
*/
|
||||
/*
|
||||
* $Id: XPathExpressionImpl.java,v 1.2.4.1 2005/09/10 04:06:55 jeffsuttor Exp $
|
||||
*/
|
||||
|
||||
|
||||
package com.sun.org.apache.xpath.internal.domapi;
|
||||
|
||||
import javax.xml.transform.TransformerException;
|
||||
|
||||
import com.sun.org.apache.xpath.internal.XPath;
|
||||
import com.sun.org.apache.xpath.internal.XPathContext;
|
||||
import com.sun.org.apache.xpath.internal.objects.XObject;
|
||||
import com.sun.org.apache.xpath.internal.res.XPATHErrorResources;
|
||||
import com.sun.org.apache.xpath.internal.res.XPATHMessages;
|
||||
import org.w3c.dom.DOMException;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.xpath.XPathException;
|
||||
import org.w3c.dom.xpath.XPathExpression;
|
||||
import org.w3c.dom.xpath.XPathNamespace;
|
||||
|
||||
/**
|
||||
*
|
||||
* The class provides an implementation of XPathExpression according
|
||||
* to the DOM L3 XPath Specification, Working Group Note 26 February 2004.
|
||||
*
|
||||
* <p>See also the <a href='http://www.w3.org/TR/2004/NOTE-DOM-Level-3-XPath-20040226'>Document Object Model (DOM) Level 3 XPath Specification</a>.</p>
|
||||
*
|
||||
* <p>The <code>XPathExpression</code> interface represents a parsed and resolved
|
||||
* XPath expression.</p>
|
||||
*
|
||||
* @see org.w3c.dom.xpath.XPathExpression
|
||||
*
|
||||
* @xsl.usage internal
|
||||
*/
|
||||
class XPathExpressionImpl implements XPathExpression {
|
||||
|
||||
/**
|
||||
* The xpath object that this expression wraps
|
||||
*/
|
||||
final private XPath m_xpath;
|
||||
|
||||
/**
|
||||
* The document to be searched to parallel the case where the XPathEvaluator
|
||||
* is obtained by casting a Document.
|
||||
*/
|
||||
final private Document m_doc;
|
||||
|
||||
/**
|
||||
* Constructor for XPathExpressionImpl.
|
||||
*
|
||||
* @param xpath The wrapped XPath object.
|
||||
* @param doc The document to be searched, to parallel the case where''
|
||||
* the XPathEvaluator is obtained by casting the document.
|
||||
*/
|
||||
XPathExpressionImpl(XPath xpath, Document doc) {
|
||||
m_xpath = xpath;
|
||||
m_doc = doc;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* This method provides an implementation XPathResult.evaluate according
|
||||
* to the DOM L3 XPath Specification, Working Group Note 26 February 2004.
|
||||
*
|
||||
* <p>See also the <a href='http://www.w3.org/TR/2004/NOTE-DOM-Level-3-XPath-20040226'>Document Object Model (DOM) Level 3 XPath Specification</a>.</p>
|
||||
*
|
||||
* <p>Evaluates this XPath expression and returns a result.</p>
|
||||
* @param contextNode The <code>context</code> is context node for the
|
||||
* evaluation of this XPath expression.If the XPathEvaluator was
|
||||
* obtained by casting the <code>Document</code> then this must be
|
||||
* owned by the same document and must be a <code>Document</code>,
|
||||
* <code>Element</code>, <code>Attribute</code>, <code>Text</code>,
|
||||
* <code>CDATASection</code>, <code>Comment</code>,
|
||||
* <code>ProcessingInstruction</code>, or <code>XPathNamespace</code>
|
||||
* node.If the context node is a <code>Text</code> or a
|
||||
* <code>CDATASection</code>, then the context is interpreted as the
|
||||
* whole logical text node as seen by XPath, unless the node is empty
|
||||
* in which case it may not serve as the XPath context.
|
||||
* @param type If a specific <code>type</code> is specified, then the
|
||||
* result will be coerced to return the specified type relying on
|
||||
* XPath conversions and fail if the desired coercion is not possible.
|
||||
* This must be one of the type codes of <code>XPathResult</code>.
|
||||
* @param result The <code>result</code> specifies a specific result
|
||||
* object which may be reused and returned by this method. If this is
|
||||
* specified as <code>null</code>or the implementation does not reuse
|
||||
* the specified result, a new result object will be constructed and
|
||||
* returned.For XPath 1.0 results, this object will be of type
|
||||
* <code>XPathResult</code>.
|
||||
* @return The result of the evaluation of the XPath expression.For XPath
|
||||
* 1.0 results, this object will be of type <code>XPathResult</code>.
|
||||
* @exception XPathException
|
||||
* TYPE_ERR: Raised if the result cannot be converted to return the
|
||||
* specified type.
|
||||
* @exception DOMException
|
||||
* WRONG_DOCUMENT_ERR: The Node is from a document that is not supported
|
||||
* by the XPathEvaluator that created this
|
||||
* <code>XPathExpression</code>.
|
||||
* <br>NOT_SUPPORTED_ERR: The Node is not a type permitted as an XPath
|
||||
* context node.
|
||||
*
|
||||
* @see org.w3c.dom.xpath.XPathExpression#evaluate(Node, short, XPathResult)
|
||||
* @xsl.usage internal
|
||||
*/
|
||||
public Object evaluate(
|
||||
Node contextNode,
|
||||
short type,
|
||||
Object result)
|
||||
throws XPathException, DOMException {
|
||||
|
||||
// If the XPathEvaluator was determined by "casting" the document
|
||||
if (m_doc != null) {
|
||||
|
||||
// Check that the context node is owned by the same document
|
||||
if ((contextNode != m_doc) && (!contextNode.getOwnerDocument().equals(m_doc))) {
|
||||
String fmsg = XPATHMessages.createXPATHMessage(XPATHErrorResources.ER_WRONG_DOCUMENT, null);
|
||||
throw new DOMException(DOMException.WRONG_DOCUMENT_ERR, fmsg);
|
||||
}
|
||||
|
||||
// Check that the context node is an acceptable node type
|
||||
short nodeType = contextNode.getNodeType();
|
||||
if ((nodeType != Document.DOCUMENT_NODE) &&
|
||||
(nodeType != Document.ELEMENT_NODE) &&
|
||||
(nodeType != Document.ATTRIBUTE_NODE) &&
|
||||
(nodeType != Document.TEXT_NODE) &&
|
||||
(nodeType != Document.CDATA_SECTION_NODE) &&
|
||||
(nodeType != Document.COMMENT_NODE) &&
|
||||
(nodeType != Document.PROCESSING_INSTRUCTION_NODE) &&
|
||||
(nodeType != XPathNamespace.XPATH_NAMESPACE_NODE)) {
|
||||
String fmsg = XPATHMessages.createXPATHMessage(XPATHErrorResources.ER_WRONG_NODETYPE, null);
|
||||
throw new DOMException(DOMException.NOT_SUPPORTED_ERR, fmsg);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// If the type is not a supported type, throw an exception and be
|
||||
// done with it!
|
||||
if (!XPathResultImpl.isValidType(type)) {
|
||||
String fmsg = XPATHMessages.createXPATHMessage(XPATHErrorResources.ER_INVALID_XPATH_TYPE, new Object[] {new Integer(type)});
|
||||
throw new XPathException(XPathException.TYPE_ERR,fmsg); // Invalid XPath type argument: {0}
|
||||
}
|
||||
|
||||
// Cache xpath context?
|
||||
XPathContext xpathSupport = new XPathContext();
|
||||
|
||||
// if m_document is not null, build the DTM from the document
|
||||
if (null != m_doc) {
|
||||
xpathSupport.getDTMHandleFromNode(m_doc);
|
||||
}
|
||||
|
||||
XObject xobj = null;
|
||||
try {
|
||||
xobj = m_xpath.execute(xpathSupport, contextNode, null);
|
||||
} catch (TransformerException te) {
|
||||
// What should we do here?
|
||||
throw new XPathException(XPathException.INVALID_EXPRESSION_ERR,te.getMessageAndLocation());
|
||||
}
|
||||
|
||||
// Create a new XPathResult object
|
||||
// Reuse result object passed in?
|
||||
// The constructor will check the compatibility of type and xobj and
|
||||
// throw an exception if they are not compatible.
|
||||
return new XPathResultImpl(type,xobj,contextNode, m_xpath);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* Copyright 2002-2005 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.
|
||||
*/
|
||||
/*
|
||||
* $Id: XPathNSResolverImpl.java,v 1.2.4.1 2005/09/10 04:13:19 jeffsuttor Exp $
|
||||
*/
|
||||
|
||||
package com.sun.org.apache.xpath.internal.domapi;
|
||||
|
||||
import com.sun.org.apache.xml.internal.utils.PrefixResolverDefault;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.xpath.XPathNSResolver;
|
||||
|
||||
/**
|
||||
*
|
||||
* The class provides an implementation XPathNSResolver according
|
||||
* to the DOM L3 XPath Specification, Working Group Note 26 February 2004.
|
||||
*
|
||||
* <p>See also the <a href='http://www.w3.org/TR/2004/NOTE-DOM-Level-3-XPath-20040226'>Document Object Model (DOM) Level 3 XPath Specification</a>.</p>
|
||||
*
|
||||
* <p>The <code>XPathNSResolver</code> interface permit <code>prefix</code>
|
||||
* strings in the expression to be properly bound to
|
||||
* <code>namespaceURI</code> strings. <code>XPathEvaluator</code> can
|
||||
* construct an implementation of <code>XPathNSResolver</code> from a node,
|
||||
* or the interface may be implemented by any application.</p>
|
||||
*
|
||||
* @see org.w3c.dom.xpath.XPathNSResolver
|
||||
* @xsl.usage internal
|
||||
*/
|
||||
class XPathNSResolverImpl extends PrefixResolverDefault implements XPathNSResolver {
|
||||
|
||||
/**
|
||||
* Constructor for XPathNSResolverImpl.
|
||||
* @param xpathExpressionContext
|
||||
*/
|
||||
public XPathNSResolverImpl(Node xpathExpressionContext) {
|
||||
super(xpathExpressionContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.w3c.dom.xpath.XPathNSResolver#lookupNamespaceURI(String)
|
||||
*/
|
||||
public String lookupNamespaceURI(String prefix) {
|
||||
return super.getNamespaceForPrefix(prefix);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,324 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* Copyright 2002-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.
|
||||
*/
|
||||
/*
|
||||
* $Id: XPathNamespaceImpl.java,v 1.2.4.1 2005/09/10 04:10:02 jeffsuttor Exp $
|
||||
*/
|
||||
|
||||
|
||||
package com.sun.org.apache.xpath.internal.domapi;
|
||||
|
||||
import org.w3c.dom.Attr;
|
||||
import org.w3c.dom.DOMException;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.NamedNodeMap;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.w3c.dom.xpath.XPathNamespace;
|
||||
|
||||
import org.w3c.dom.UserDataHandler;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* The <code>XPathNamespace</code> interface is returned by
|
||||
* <code>XPathResult</code> interfaces to represent the XPath namespace node
|
||||
* type that DOM lacks. There is no public constructor for this node type.
|
||||
* Attempts to place it into a hierarchy or a NamedNodeMap result in a
|
||||
* <code>DOMException</code> with the code <code>HIERARCHY_REQUEST_ERR</code>
|
||||
* . This node is read only, so methods or setting of attributes that would
|
||||
* mutate the node result in a DOMException with the code
|
||||
* <code>NO_MODIFICATION_ALLOWED_ERR</code>.
|
||||
* <p>The core specification describes attributes of the <code>Node</code>
|
||||
* interface that are different for different node node types but does not
|
||||
* describe <code>XPATH_NAMESPACE_NODE</code>, so here is a description of
|
||||
* those attributes for this node type. All attributes of <code>Node</code>
|
||||
* not described in this section have a <code>null</code> or
|
||||
* <code>false</code> value.
|
||||
* <p><code>ownerDocument</code> matches the <code>ownerDocument</code> of the
|
||||
* <code>ownerElement</code> even if the element is later adopted.
|
||||
* <p><code>prefix</code> is the prefix of the namespace represented by the
|
||||
* node.
|
||||
* <p><code>nodeName</code> is the same as <code>prefix</code>.
|
||||
* <p><code>nodeType</code> is equal to <code>XPATH_NAMESPACE_NODE</code>.
|
||||
* <p><code>namespaceURI</code> is the namespace URI of the namespace
|
||||
* represented by the node.
|
||||
* <p><code>adoptNode</code>, <code>cloneNode</code>, and
|
||||
* <code>importNode</code> fail on this node type by raising a
|
||||
* <code>DOMException</code> with the code <code>NOT_SUPPORTED_ERR</code>.In
|
||||
* future versions of the XPath specification, the definition of a namespace
|
||||
* node may be changed incomatibly, in which case incompatible changes to
|
||||
* field values may be required to implement versions beyond XPath 1.0.
|
||||
* <p>See also the <a href='http://www.w3.org/TR/2004/NOTE-DOM-Level-3-XPath-20040226'>Document Object Model (DOM) Level 3 XPath Specification</a>.
|
||||
*
|
||||
* This implementation wraps the DOM attribute node that contained the
|
||||
* namespace declaration.
|
||||
* @xsl.usage internal
|
||||
*/
|
||||
|
||||
class XPathNamespaceImpl implements XPathNamespace {
|
||||
|
||||
// Node that XPathNamespaceImpl wraps
|
||||
final private Node m_attributeNode;
|
||||
|
||||
/**
|
||||
* Constructor for XPathNamespaceImpl.
|
||||
*/
|
||||
XPathNamespaceImpl(Node node) {
|
||||
m_attributeNode = node;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.sun.org.apache.xalan.internal.dom3.xpath.XPathNamespace#getOwnerElement()
|
||||
*/
|
||||
public Element getOwnerElement() {
|
||||
return ((Attr)m_attributeNode).getOwnerElement();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.w3c.dom.Node#getNodeName()
|
||||
*/
|
||||
public String getNodeName() {
|
||||
return "#namespace";
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.w3c.dom.Node#getNodeValue()
|
||||
*/
|
||||
public String getNodeValue() throws DOMException {
|
||||
return m_attributeNode.getNodeValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.w3c.dom.Node#setNodeValue(String)
|
||||
*/
|
||||
public void setNodeValue(String arg0) throws DOMException {
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.w3c.dom.Node#getNodeType()
|
||||
*/
|
||||
public short getNodeType() {
|
||||
return XPathNamespace.XPATH_NAMESPACE_NODE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.w3c.dom.Node#getParentNode()
|
||||
*/
|
||||
public Node getParentNode() {
|
||||
return m_attributeNode.getParentNode();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.w3c.dom.Node#getChildNodes()
|
||||
*/
|
||||
public NodeList getChildNodes() {
|
||||
return m_attributeNode.getChildNodes();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.w3c.dom.Node#getFirstChild()
|
||||
*/
|
||||
public Node getFirstChild() {
|
||||
return m_attributeNode.getFirstChild();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.w3c.dom.Node#getLastChild()
|
||||
*/
|
||||
public Node getLastChild() {
|
||||
return m_attributeNode.getLastChild();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.w3c.dom.Node#getPreviousSibling()
|
||||
*/
|
||||
public Node getPreviousSibling() {
|
||||
return m_attributeNode.getPreviousSibling();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.w3c.dom.Node#getNextSibling()
|
||||
*/
|
||||
public Node getNextSibling() {
|
||||
return m_attributeNode.getNextSibling();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.w3c.dom.Node#getAttributes()
|
||||
*/
|
||||
public NamedNodeMap getAttributes() {
|
||||
return m_attributeNode.getAttributes();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.w3c.dom.Node#getOwnerDocument()
|
||||
*/
|
||||
public Document getOwnerDocument() {
|
||||
return m_attributeNode.getOwnerDocument();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.w3c.dom.Node#insertBefore(Node, Node)
|
||||
*/
|
||||
public Node insertBefore(Node arg0, Node arg1) throws DOMException {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.w3c.dom.Node#replaceChild(Node, Node)
|
||||
*/
|
||||
public Node replaceChild(Node arg0, Node arg1) throws DOMException {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.w3c.dom.Node#removeChild(Node)
|
||||
*/
|
||||
public Node removeChild(Node arg0) throws DOMException {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.w3c.dom.Node#appendChild(Node)
|
||||
*/
|
||||
public Node appendChild(Node arg0) throws DOMException {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.w3c.dom.Node#hasChildNodes()
|
||||
*/
|
||||
public boolean hasChildNodes() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.w3c.dom.Node#cloneNode(boolean)
|
||||
*/
|
||||
public Node cloneNode(boolean arg0) {
|
||||
throw new DOMException(DOMException.NOT_SUPPORTED_ERR,null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.w3c.dom.Node#normalize()
|
||||
*/
|
||||
public void normalize() {
|
||||
m_attributeNode.normalize();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.w3c.dom.Node#isSupported(String, String)
|
||||
*/
|
||||
public boolean isSupported(String arg0, String arg1) {
|
||||
return m_attributeNode.isSupported(arg0, arg1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.w3c.dom.Node#getNamespaceURI()
|
||||
*/
|
||||
public String getNamespaceURI() {
|
||||
|
||||
// For namespace node, the namespaceURI is the namespace URI
|
||||
// of the namespace represented by the node.
|
||||
return m_attributeNode.getNodeValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.w3c.dom.Node#getPrefix()
|
||||
*/
|
||||
public String getPrefix() {
|
||||
return m_attributeNode.getPrefix();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.w3c.dom.Node#setPrefix(String)
|
||||
*/
|
||||
public void setPrefix(String arg0) throws DOMException {
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.w3c.dom.Node#getLocalName()
|
||||
*/
|
||||
public String getLocalName() {
|
||||
|
||||
// For namespace node, the local name is the same as the prefix
|
||||
return m_attributeNode.getPrefix();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.w3c.dom.Node#hasAttributes()
|
||||
*/
|
||||
public boolean hasAttributes() {
|
||||
return m_attributeNode.hasAttributes();
|
||||
}
|
||||
|
||||
public String getBaseURI ( ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public short compareDocumentPosition(Node other) throws DOMException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
private String textContent;
|
||||
|
||||
public String getTextContent() throws DOMException {
|
||||
return textContent;
|
||||
}
|
||||
|
||||
public void setTextContent(String textContent) throws DOMException {
|
||||
this.textContent = textContent;
|
||||
}
|
||||
|
||||
public boolean isSameNode(Node other) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public String lookupPrefix(String namespaceURI) {
|
||||
return ""; //PENDING
|
||||
}
|
||||
|
||||
public boolean isDefaultNamespace(String namespaceURI) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public String lookupNamespaceURI(String prefix) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isEqualNode(Node arg) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public Object getFeature(String feature, String version) {
|
||||
return null; //PENDING
|
||||
}
|
||||
|
||||
public Object setUserData(String key,
|
||||
Object data,
|
||||
UserDataHandler handler) {
|
||||
return null; //PENDING
|
||||
}
|
||||
|
||||
public Object getUserData(String key) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,512 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* Copyright 2002-2005 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.
|
||||
*/
|
||||
/*
|
||||
* $Id: XPathResultImpl.java,v 1.2.4.1 2005/09/10 04:18:54 jeffsuttor Exp $
|
||||
*/
|
||||
|
||||
|
||||
package com.sun.org.apache.xpath.internal.domapi;
|
||||
|
||||
import javax.xml.transform.TransformerException;
|
||||
|
||||
import com.sun.org.apache.xpath.internal.XPath;
|
||||
import com.sun.org.apache.xpath.internal.objects.XObject;
|
||||
import com.sun.org.apache.xpath.internal.res.XPATHErrorResources;
|
||||
import com.sun.org.apache.xpath.internal.res.XPATHMessages;
|
||||
import org.w3c.dom.DOMException;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.w3c.dom.events.Event;
|
||||
import org.w3c.dom.events.EventListener;
|
||||
import org.w3c.dom.events.EventTarget;
|
||||
import org.w3c.dom.traversal.NodeIterator;
|
||||
import org.w3c.dom.xpath.XPathException;
|
||||
import org.w3c.dom.xpath.XPathResult;
|
||||
|
||||
/**
|
||||
*
|
||||
* The class provides an implementation XPathResult according
|
||||
* to the DOM L3 XPath Specification, Working Group Note 26 February 2004.
|
||||
*
|
||||
* <p>See also the <a href='http://www.w3.org/TR/2004/NOTE-DOM-Level-3-XPath-20040226'>Document Object Model (DOM) Level 3 XPath Specification</a>.</p>
|
||||
*
|
||||
* <p>The <code>XPathResult</code> interface represents the result of the
|
||||
* evaluation of an XPath expression within the context of a particular
|
||||
* node. Since evaluation of an XPath expression can result in various
|
||||
* result types, this object makes it possible to discover and manipulate
|
||||
* the type and value of the result.</p>
|
||||
*
|
||||
* <p>This implementation wraps an <code>XObject</code>.
|
||||
*
|
||||
* @see com.sun.org.apache.xpath.internal.objects.XObject
|
||||
* @see org.w3c.dom.xpath.XPathResult
|
||||
*
|
||||
* @xsl.usage internal
|
||||
*/
|
||||
class XPathResultImpl implements XPathResult, EventListener {
|
||||
|
||||
/**
|
||||
* The wrapped XObject
|
||||
*/
|
||||
final private XObject m_resultObj;
|
||||
|
||||
/**
|
||||
* The xpath object that wraps the expression used for this result.
|
||||
*/
|
||||
final private XPath m_xpath;
|
||||
|
||||
/**
|
||||
* This the type specified by the user during construction. Typically
|
||||
* the constructor will be called by com.sun.org.apache.xpath.internal.XPath.evaluate().
|
||||
*/
|
||||
final private short m_resultType;
|
||||
|
||||
private boolean m_isInvalidIteratorState = false;
|
||||
|
||||
/**
|
||||
* Only used to attach a mutation event handler when specified
|
||||
* type is an iterator type.
|
||||
*/
|
||||
final private Node m_contextNode;
|
||||
|
||||
/**
|
||||
* The iterator, if this is an iterator type.
|
||||
*/
|
||||
private NodeIterator m_iterator = null;;
|
||||
|
||||
/**
|
||||
* The list, if this is a snapshot type.
|
||||
*/
|
||||
private NodeList m_list = null;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor for XPathResultImpl.
|
||||
*
|
||||
* For internal use only.
|
||||
*/
|
||||
XPathResultImpl(short type, XObject result, Node contextNode, XPath xpath) {
|
||||
// Check that the type is valid
|
||||
if (!isValidType(type)) {
|
||||
String fmsg = XPATHMessages.createXPATHMessage(XPATHErrorResources.ER_INVALID_XPATH_TYPE, new Object[] {new Integer(type)});
|
||||
throw new XPathException(XPathException.TYPE_ERR,fmsg); // Invalid XPath type argument: {0}
|
||||
}
|
||||
|
||||
// Result object should never be null!
|
||||
if (null == result) {
|
||||
String fmsg = XPATHMessages.createXPATHMessage(XPATHErrorResources.ER_EMPTY_XPATH_RESULT, null);
|
||||
throw new XPathException(XPathException.INVALID_EXPRESSION_ERR,fmsg); // Empty XPath result object
|
||||
}
|
||||
|
||||
this.m_resultObj = result;
|
||||
this.m_contextNode = contextNode;
|
||||
this.m_xpath = xpath;
|
||||
|
||||
// If specified result was ANY_TYPE, determine XObject type
|
||||
if (type == ANY_TYPE) {
|
||||
this.m_resultType = getTypeFromXObject(result);
|
||||
} else {
|
||||
this.m_resultType = type;
|
||||
}
|
||||
|
||||
// If the context node supports DOM Events and the type is one of the iterator
|
||||
// types register this result as an event listener
|
||||
if (((m_resultType == XPathResult.ORDERED_NODE_ITERATOR_TYPE) ||
|
||||
(m_resultType == XPathResult.UNORDERED_NODE_ITERATOR_TYPE))) {
|
||||
addEventListener();
|
||||
|
||||
}// else can we handle iterator types if contextNode doesn't support EventTarget??
|
||||
|
||||
// If this is an iterator type get the iterator
|
||||
if ((m_resultType == ORDERED_NODE_ITERATOR_TYPE) ||
|
||||
(m_resultType == UNORDERED_NODE_ITERATOR_TYPE) ||
|
||||
(m_resultType == ANY_UNORDERED_NODE_TYPE) ||
|
||||
(m_resultType == FIRST_ORDERED_NODE_TYPE)) {
|
||||
|
||||
try {
|
||||
m_iterator = m_resultObj.nodeset();
|
||||
} catch (TransformerException te) {
|
||||
// probably not a node type
|
||||
String fmsg = XPATHMessages.createXPATHMessage(XPATHErrorResources.ER_INCOMPATIBLE_TYPES, new Object[] {m_xpath.getPatternString(), getTypeString(getTypeFromXObject(m_resultObj)),getTypeString(m_resultType)});
|
||||
throw new XPathException(XPathException.TYPE_ERR, fmsg); // "The XPathResult of XPath expression {0} has an XPathResultType of {1} which cannot be coerced into the specified XPathResultType of {2}."},
|
||||
}
|
||||
|
||||
// If user requested ordered nodeset and result is unordered
|
||||
// need to sort...TODO
|
||||
// if ((m_resultType == ORDERED_NODE_ITERATOR_TYPE) &&
|
||||
// (!(((DTMNodeIterator)m_iterator).getDTMIterator().isDocOrdered()))) {
|
||||
//
|
||||
// }
|
||||
|
||||
// If it's a snapshot type, get the nodelist
|
||||
} else if ((m_resultType == UNORDERED_NODE_SNAPSHOT_TYPE) ||
|
||||
(m_resultType == ORDERED_NODE_SNAPSHOT_TYPE)) {
|
||||
try {
|
||||
m_list = m_resultObj.nodelist();
|
||||
} catch (TransformerException te) {
|
||||
// probably not a node type
|
||||
String fmsg = XPATHMessages.createXPATHMessage(XPATHErrorResources.ER_INCOMPATIBLE_TYPES, new Object[] {m_xpath.getPatternString(), getTypeString(getTypeFromXObject(m_resultObj)),getTypeString(m_resultType)});
|
||||
throw new XPathException(XPathException.TYPE_ERR, fmsg); // "The XPathResult of XPath expression {0} has an XPathResultType of {1} which cannot be coerced into the specified XPathResultType of {2}."},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.w3c.dom.xpath.XPathResult#getResultType()
|
||||
*/
|
||||
public short getResultType() {
|
||||
return m_resultType;
|
||||
}
|
||||
|
||||
/**
|
||||
* The value of this number result.
|
||||
* @exception XPathException
|
||||
* TYPE_ERR: raised if <code>resultType</code> is not
|
||||
* <code>NUMBER_TYPE</code>.
|
||||
* @see org.w3c.dom.xpath.XPathResult#getNumberValue()
|
||||
*/
|
||||
public double getNumberValue() throws XPathException {
|
||||
if (getResultType() != NUMBER_TYPE) {
|
||||
String fmsg = XPATHMessages.createXPATHMessage(XPATHErrorResources.ER_CANT_CONVERT_XPATHRESULTTYPE_TO_NUMBER, new Object[] {m_xpath.getPatternString(), getTypeString(m_resultType)});
|
||||
throw new XPathException(XPathException.TYPE_ERR,fmsg);
|
||||
// "The XPathResult of XPath expression {0} has an XPathResultType of {1} which cannot be converted to a number"
|
||||
} else {
|
||||
try {
|
||||
return m_resultObj.num();
|
||||
} catch (Exception e) {
|
||||
// Type check above should prevent this exception from occurring.
|
||||
throw new XPathException(XPathException.TYPE_ERR,e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The value of this string result.
|
||||
* @exception XPathException
|
||||
* TYPE_ERR: raised if <code>resultType</code> is not
|
||||
* <code>STRING_TYPE</code>.
|
||||
*
|
||||
* @see org.w3c.dom.xpath.XPathResult#getStringValue()
|
||||
*/
|
||||
public String getStringValue() throws XPathException {
|
||||
if (getResultType() != STRING_TYPE) {
|
||||
String fmsg = XPATHMessages.createXPATHMessage(XPATHErrorResources.ER_CANT_CONVERT_TO_STRING, new Object[] {m_xpath.getPatternString(), m_resultObj.getTypeString()});
|
||||
throw new XPathException(XPathException.TYPE_ERR,fmsg);
|
||||
// "The XPathResult of XPath expression {0} has an XPathResultType of {1} which cannot be converted to a string."
|
||||
} else {
|
||||
try {
|
||||
return m_resultObj.str();
|
||||
} catch (Exception e) {
|
||||
// Type check above should prevent this exception from occurring.
|
||||
throw new XPathException(XPathException.TYPE_ERR,e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.w3c.dom.xpath.XPathResult#getBooleanValue()
|
||||
*/
|
||||
public boolean getBooleanValue() throws XPathException {
|
||||
if (getResultType() != BOOLEAN_TYPE) {
|
||||
String fmsg = XPATHMessages.createXPATHMessage(XPATHErrorResources.ER_CANT_CONVERT_TO_BOOLEAN, new Object[] {m_xpath.getPatternString(), getTypeString(m_resultType)});
|
||||
throw new XPathException(XPathException.TYPE_ERR,fmsg);
|
||||
// "The XPathResult of XPath expression {0} has an XPathResultType of {1} which cannot be converted to a boolean."
|
||||
} else {
|
||||
try {
|
||||
return m_resultObj.bool();
|
||||
} catch (TransformerException e) {
|
||||
// Type check above should prevent this exception from occurring.
|
||||
throw new XPathException(XPathException.TYPE_ERR,e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The value of this single node result, which may be <code>null</code>.
|
||||
* @exception XPathException
|
||||
* TYPE_ERR: raised if <code>resultType</code> is not
|
||||
* <code>ANY_UNORDERED_NODE_TYPE</code> or
|
||||
* <code>FIRST_ORDERED_NODE_TYPE</code>.
|
||||
*
|
||||
* @see org.w3c.dom.xpath.XPathResult#getSingleNodeValue()
|
||||
*/
|
||||
public Node getSingleNodeValue() throws XPathException {
|
||||
|
||||
if ((m_resultType != ANY_UNORDERED_NODE_TYPE) &&
|
||||
(m_resultType != FIRST_ORDERED_NODE_TYPE)) {
|
||||
String fmsg = XPATHMessages.createXPATHMessage(XPATHErrorResources.ER_CANT_CONVERT_TO_SINGLENODE, new Object[] {m_xpath.getPatternString(), getTypeString(m_resultType)});
|
||||
throw new XPathException(XPathException.TYPE_ERR,fmsg);
|
||||
// "The XPathResult of XPath expression {0} has an XPathResultType of {1} which cannot be converted to a single node.
|
||||
// This method applies only to types ANY_UNORDERED_NODE_TYPE and FIRST_ORDERED_NODE_TYPE."
|
||||
}
|
||||
|
||||
NodeIterator result = null;
|
||||
try {
|
||||
result = m_resultObj.nodeset();
|
||||
} catch (TransformerException te) {
|
||||
throw new XPathException(XPathException.TYPE_ERR,te.getMessage());
|
||||
}
|
||||
|
||||
if (null == result) return null;
|
||||
|
||||
Node node = result.nextNode();
|
||||
|
||||
// Wrap "namespace node" in an XPathNamespace
|
||||
if (isNamespaceNode(node)) {
|
||||
return new XPathNamespaceImpl(node);
|
||||
} else {
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.w3c.dom.xpath.XPathResult#getInvalidIteratorState()
|
||||
*/
|
||||
public boolean getInvalidIteratorState() {
|
||||
return m_isInvalidIteratorState;
|
||||
}
|
||||
|
||||
/**
|
||||
* The number of nodes in the result snapshot. Valid values for
|
||||
* snapshotItem indices are <code>0</code> to
|
||||
* <code>snapshotLength-1</code> inclusive.
|
||||
* @exception XPathException
|
||||
* TYPE_ERR: raised if <code>resultType</code> is not
|
||||
* <code>UNORDERED_NODE_SNAPSHOT_TYPE</code> or
|
||||
* <code>ORDERED_NODE_SNAPSHOT_TYPE</code>.
|
||||
*
|
||||
* @see org.w3c.dom.xpath.XPathResult#getSnapshotLength()
|
||||
*/
|
||||
public int getSnapshotLength() throws XPathException {
|
||||
|
||||
if ((m_resultType != UNORDERED_NODE_SNAPSHOT_TYPE) &&
|
||||
(m_resultType != ORDERED_NODE_SNAPSHOT_TYPE)) {
|
||||
String fmsg = XPATHMessages.createXPATHMessage(XPATHErrorResources.ER_CANT_GET_SNAPSHOT_LENGTH, new Object[] {m_xpath.getPatternString(), getTypeString(m_resultType)});
|
||||
throw new XPathException(XPathException.TYPE_ERR,fmsg);
|
||||
// "The method getSnapshotLength cannot be called on the XPathResult of XPath expression {0} because its XPathResultType is {1}.
|
||||
}
|
||||
|
||||
return m_list.getLength();
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterates and returns the next node from the node set or
|
||||
* <code>null</code>if there are no more nodes.
|
||||
* @return Returns the next node.
|
||||
* @exception XPathException
|
||||
* TYPE_ERR: raised if <code>resultType</code> is not
|
||||
* <code>UNORDERED_NODE_ITERATOR_TYPE</code> or
|
||||
* <code>ORDERED_NODE_ITERATOR_TYPE</code>.
|
||||
* @exception DOMException
|
||||
* INVALID_STATE_ERR: The document has been mutated since the result was
|
||||
* returned.
|
||||
* @see org.w3c.dom.xpath.XPathResult#iterateNext()
|
||||
*/
|
||||
public Node iterateNext() throws XPathException, DOMException {
|
||||
if ((m_resultType != UNORDERED_NODE_ITERATOR_TYPE) &&
|
||||
(m_resultType != ORDERED_NODE_ITERATOR_TYPE)) {
|
||||
String fmsg = XPATHMessages.createXPATHMessage(XPATHErrorResources.ER_NON_ITERATOR_TYPE, new Object[] {m_xpath.getPatternString(), getTypeString(m_resultType)});
|
||||
throw new XPathException(XPathException.TYPE_ERR, fmsg);
|
||||
// "The method iterateNext cannot be called on the XPathResult of XPath expression {0} because its XPathResultType is {1}.
|
||||
// This method applies only to types UNORDERED_NODE_ITERATOR_TYPE and ORDERED_NODE_ITERATOR_TYPE."},
|
||||
}
|
||||
|
||||
if (getInvalidIteratorState()) {
|
||||
String fmsg = XPATHMessages.createXPATHMessage(XPATHErrorResources.ER_DOC_MUTATED, null);
|
||||
throw new DOMException(DOMException.INVALID_STATE_ERR,fmsg); // Document mutated since result was returned. Iterator is invalid.
|
||||
}
|
||||
|
||||
Node node = m_iterator.nextNode();
|
||||
if(null == node)
|
||||
removeEventListener(); // JIRA 1673
|
||||
// Wrap "namespace node" in an XPathNamespace
|
||||
if (isNamespaceNode(node)) {
|
||||
return new XPathNamespaceImpl(node);
|
||||
} else {
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the <code>index</code>th item in the snapshot collection. If
|
||||
* <code>index</code> is greater than or equal to the number of nodes in
|
||||
* the list, this method returns <code>null</code>. Unlike the iterator
|
||||
* result, the snapshot does not become invalid, but may not correspond
|
||||
* to the current document if it is mutated.
|
||||
* @param index Index into the snapshot collection.
|
||||
* @return The node at the <code>index</code>th position in the
|
||||
* <code>NodeList</code>, or <code>null</code> if that is not a valid
|
||||
* index.
|
||||
* @exception XPathException
|
||||
* TYPE_ERR: raised if <code>resultType</code> is not
|
||||
* <code>UNORDERED_NODE_SNAPSHOT_TYPE</code> or
|
||||
* <code>ORDERED_NODE_SNAPSHOT_TYPE</code>.
|
||||
*
|
||||
* @see org.w3c.dom.xpath.XPathResult#snapshotItem(int)
|
||||
*/
|
||||
public Node snapshotItem(int index) throws XPathException {
|
||||
|
||||
if ((m_resultType != UNORDERED_NODE_SNAPSHOT_TYPE) &&
|
||||
(m_resultType != ORDERED_NODE_SNAPSHOT_TYPE)) {
|
||||
String fmsg = XPATHMessages.createXPATHMessage(XPATHErrorResources.ER_NON_SNAPSHOT_TYPE, new Object[] {m_xpath.getPatternString(), getTypeString(m_resultType)});
|
||||
throw new XPathException(XPathException.TYPE_ERR, fmsg);
|
||||
// "The method snapshotItem cannot be called on the XPathResult of XPath expression {0} because its XPathResultType is {1}.
|
||||
// This method applies only to types UNORDERED_NODE_SNAPSHOT_TYPE and ORDERED_NODE_SNAPSHOT_TYPE."},
|
||||
}
|
||||
|
||||
Node node = m_list.item(index);
|
||||
|
||||
// Wrap "namespace node" in an XPathNamespace
|
||||
if (isNamespaceNode(node)) {
|
||||
return new XPathNamespaceImpl(node);
|
||||
} else {
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if the specified type is one of the supported types.
|
||||
* @param type The specified type
|
||||
*
|
||||
* @return true If the specified type is supported; otherwise, returns false.
|
||||
*/
|
||||
static boolean isValidType( short type ) {
|
||||
switch (type) {
|
||||
case ANY_TYPE:
|
||||
case NUMBER_TYPE:
|
||||
case STRING_TYPE:
|
||||
case BOOLEAN_TYPE:
|
||||
case UNORDERED_NODE_ITERATOR_TYPE:
|
||||
case ORDERED_NODE_ITERATOR_TYPE:
|
||||
case UNORDERED_NODE_SNAPSHOT_TYPE:
|
||||
case ORDERED_NODE_SNAPSHOT_TYPE:
|
||||
case ANY_UNORDERED_NODE_TYPE:
|
||||
case FIRST_ORDERED_NODE_TYPE: return true;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.w3c.dom.events.EventListener#handleEvent(Event)
|
||||
*/
|
||||
public void handleEvent(Event event) {
|
||||
|
||||
if (event.getType().equals("DOMSubtreeModified")) {
|
||||
// invalidate the iterator
|
||||
m_isInvalidIteratorState = true;
|
||||
|
||||
// deregister as a listener to reduce computational load
|
||||
removeEventListener();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a request type, return the equivalent string.
|
||||
* For diagnostic purposes.
|
||||
*
|
||||
* @return type string
|
||||
*/
|
||||
private String getTypeString(int type)
|
||||
{
|
||||
switch (type) {
|
||||
case ANY_TYPE: return "ANY_TYPE";
|
||||
case ANY_UNORDERED_NODE_TYPE: return "ANY_UNORDERED_NODE_TYPE";
|
||||
case BOOLEAN_TYPE: return "BOOLEAN";
|
||||
case FIRST_ORDERED_NODE_TYPE: return "FIRST_ORDERED_NODE_TYPE";
|
||||
case NUMBER_TYPE: return "NUMBER_TYPE";
|
||||
case ORDERED_NODE_ITERATOR_TYPE: return "ORDERED_NODE_ITERATOR_TYPE";
|
||||
case ORDERED_NODE_SNAPSHOT_TYPE: return "ORDERED_NODE_SNAPSHOT_TYPE";
|
||||
case STRING_TYPE: return "STRING_TYPE";
|
||||
case UNORDERED_NODE_ITERATOR_TYPE: return "UNORDERED_NODE_ITERATOR_TYPE";
|
||||
case UNORDERED_NODE_SNAPSHOT_TYPE: return "UNORDERED_NODE_SNAPSHOT_TYPE";
|
||||
default: return "#UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an XObject, determine the corresponding DOM XPath type
|
||||
*
|
||||
* @return type string
|
||||
*/
|
||||
private short getTypeFromXObject(XObject object) {
|
||||
switch (object.getType()) {
|
||||
case XObject.CLASS_BOOLEAN: return BOOLEAN_TYPE;
|
||||
case XObject.CLASS_NODESET: return UNORDERED_NODE_ITERATOR_TYPE;
|
||||
case XObject.CLASS_NUMBER: return NUMBER_TYPE;
|
||||
case XObject.CLASS_STRING: return STRING_TYPE;
|
||||
// XPath 2.0 types
|
||||
// case XObject.CLASS_DATE:
|
||||
// case XObject.CLASS_DATETIME:
|
||||
// case XObject.CLASS_DTDURATION:
|
||||
// case XObject.CLASS_GDAY:
|
||||
// case XObject.CLASS_GMONTH:
|
||||
// case XObject.CLASS_GMONTHDAY:
|
||||
// case XObject.CLASS_GYEAR:
|
||||
// case XObject.CLASS_GYEARMONTH:
|
||||
// case XObject.CLASS_TIME:
|
||||
// case XObject.CLASS_YMDURATION: return STRING_TYPE; // treat all date types as strings?
|
||||
|
||||
case XObject.CLASS_RTREEFRAG: return UNORDERED_NODE_ITERATOR_TYPE;
|
||||
case XObject.CLASS_NULL: return ANY_TYPE; // throw exception ?
|
||||
default: return ANY_TYPE; // throw exception ?
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a node, determine if it is a namespace node.
|
||||
*
|
||||
* @param node
|
||||
*
|
||||
* @return boolean Returns true if this is a namespace node; otherwise, returns false.
|
||||
*/
|
||||
private boolean isNamespaceNode(Node node) {
|
||||
|
||||
if ((null != node) &&
|
||||
(node.getNodeType() == Node.ATTRIBUTE_NODE) &&
|
||||
(node.getNodeName().startsWith("xmlns:") || node.getNodeName().equals("xmlns"))) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add m_contextNode to Event Listner to listen for Mutations Events
|
||||
*
|
||||
*/
|
||||
private void addEventListener(){
|
||||
if(m_contextNode instanceof EventTarget)
|
||||
((EventTarget)m_contextNode).addEventListener("DOMSubtreeModified",this,true);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove m_contextNode to Event Listner to listen for Mutations Events
|
||||
*
|
||||
*/
|
||||
private void removeEventListener(){
|
||||
if(m_contextNode instanceof EventTarget)
|
||||
((EventTarget)m_contextNode).removeEventListener("DOMSubtreeModified",this,true);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file and, per its terms, should not be removed:
|
||||
*
|
||||
* Copyright (c) 2002 World Wide Web Consortium,
|
||||
* (Massachusetts Institute of Technology, Institut National de
|
||||
* Recherche en Informatique et en Automatique, Keio University). All
|
||||
* Rights Reserved. This program is distributed under the W3C's Software
|
||||
* Intellectual Property License. This program 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.
|
||||
* See W3C License http://www.w3.org/Consortium/Legal/ for more details.
|
||||
*/
|
||||
|
||||
package com.sun.org.apache.xpath.internal.domapi;
|
||||
|
||||
import javax.xml.transform.SourceLocator;
|
||||
import javax.xml.transform.TransformerException;
|
||||
|
||||
/**
|
||||
*
|
||||
* A new exception to add support for DOM Level 3 XPath API.
|
||||
* This class is needed to throw a org.w3c.dom.DOMException with proper error code in
|
||||
* createExpression method of XPathEvaluatorImpl (a DOM Level 3 class).
|
||||
*
|
||||
* This class extends TransformerException because the error message includes information
|
||||
* about where the XPath problem is in the stylesheet as well as the XPath expression itself.
|
||||
*
|
||||
* @xsl.usage internal
|
||||
*/
|
||||
final public class XPathStylesheetDOM3Exception extends TransformerException {
|
||||
public XPathStylesheetDOM3Exception(String msg, SourceLocator arg1)
|
||||
{
|
||||
super(msg, arg1);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.functions;
|
||||
|
||||
import com.sun.org.apache.xpath.internal.XPathContext;
|
||||
import com.sun.org.apache.xpath.internal.objects.XBoolean;
|
||||
import com.sun.org.apache.xpath.internal.objects.XObject;
|
||||
|
||||
/**
|
||||
* Execute the Boolean() function.
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public class FuncBoolean extends FunctionOneArg
|
||||
{
|
||||
static final long serialVersionUID = 4328660760070034592L;
|
||||
|
||||
/**
|
||||
* Execute the function. The function must return
|
||||
* a valid object.
|
||||
* @param xctxt The current execution context.
|
||||
* @return A valid XObject.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException
|
||||
{
|
||||
return m_arg0.execute(xctxt).bool() ? XBoolean.S_TRUE : XBoolean.S_FALSE;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.functions;
|
||||
|
||||
import com.sun.org.apache.xpath.internal.XPathContext;
|
||||
import com.sun.org.apache.xpath.internal.objects.XNumber;
|
||||
import com.sun.org.apache.xpath.internal.objects.XObject;
|
||||
|
||||
/**
|
||||
* Execute the Ceiling() function.
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public class FuncCeiling extends FunctionOneArg
|
||||
{
|
||||
static final long serialVersionUID = -1275988936390464739L;
|
||||
|
||||
/**
|
||||
* Execute the function. The function must return
|
||||
* a valid object.
|
||||
* @param xctxt The current execution context.
|
||||
* @return A valid XObject.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException
|
||||
{
|
||||
return new XNumber(Math.ceil(m_arg0.execute(xctxt).num()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.functions;
|
||||
|
||||
import com.sun.org.apache.xalan.internal.res.XSLMessages;
|
||||
import com.sun.org.apache.xpath.internal.XPathContext;
|
||||
import com.sun.org.apache.xpath.internal.objects.XObject;
|
||||
import com.sun.org.apache.xpath.internal.objects.XString;
|
||||
|
||||
/**
|
||||
* Execute the Concat() function.
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public class FuncConcat extends FunctionMultiArgs
|
||||
{
|
||||
static final long serialVersionUID = 1737228885202314413L;
|
||||
|
||||
/**
|
||||
* Execute the function. The function must return
|
||||
* a valid object.
|
||||
* @param xctxt The current execution context.
|
||||
* @return A valid XObject.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException
|
||||
{
|
||||
|
||||
StringBuffer sb = new StringBuffer();
|
||||
|
||||
// Compiler says we must have at least two arguments.
|
||||
sb.append(m_arg0.execute(xctxt).str());
|
||||
sb.append(m_arg1.execute(xctxt).str());
|
||||
|
||||
if (null != m_arg2)
|
||||
sb.append(m_arg2.execute(xctxt).str());
|
||||
|
||||
if (null != m_args)
|
||||
{
|
||||
for (int i = 0; i < m_args.length; i++)
|
||||
{
|
||||
sb.append(m_args[i].execute(xctxt).str());
|
||||
}
|
||||
}
|
||||
|
||||
return new XString(sb.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the number of arguments passed to this function is correct.
|
||||
*
|
||||
*
|
||||
* @param argNum The number of arguments that is being passed to the function.
|
||||
*
|
||||
* @throws WrongNumberArgsException
|
||||
*/
|
||||
public void checkNumberArgs(int argNum) throws WrongNumberArgsException
|
||||
{
|
||||
if (argNum < 2)
|
||||
reportWrongNumberArgs();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs and throws a WrongNumberArgException with the appropriate
|
||||
* message for this function object.
|
||||
*
|
||||
* @throws WrongNumberArgsException
|
||||
*/
|
||||
protected void reportWrongNumberArgs() throws WrongNumberArgsException {
|
||||
throw new WrongNumberArgsException(XSLMessages.createXPATHMessage("gtone", null));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.functions;
|
||||
|
||||
import com.sun.org.apache.xpath.internal.XPathContext;
|
||||
import com.sun.org.apache.xpath.internal.objects.XBoolean;
|
||||
import com.sun.org.apache.xpath.internal.objects.XObject;
|
||||
|
||||
/**
|
||||
* Execute the Contains() function.
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public class FuncContains extends Function2Args
|
||||
{
|
||||
static final long serialVersionUID = 5084753781887919723L;
|
||||
|
||||
/**
|
||||
* Execute the function. The function must return
|
||||
* a valid object.
|
||||
* @param xctxt The current execution context.
|
||||
* @return A valid XObject.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException
|
||||
{
|
||||
|
||||
String s1 = m_arg0.execute(xctxt).str();
|
||||
String s2 = m_arg1.execute(xctxt).str();
|
||||
|
||||
// Add this check for JDK consistency for empty strings.
|
||||
if (s1.length() == 0 && s2.length() == 0)
|
||||
return XBoolean.S_TRUE;
|
||||
|
||||
int index = s1.indexOf(s2);
|
||||
|
||||
return (index > -1) ? XBoolean.S_TRUE : XBoolean.S_FALSE;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.functions;
|
||||
|
||||
import com.sun.org.apache.xml.internal.dtm.DTMIterator;
|
||||
import com.sun.org.apache.xpath.internal.XPathContext;
|
||||
import com.sun.org.apache.xpath.internal.objects.XNumber;
|
||||
import com.sun.org.apache.xpath.internal.objects.XObject;
|
||||
|
||||
/**
|
||||
* Execute the Count() function.
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public class FuncCount extends FunctionOneArg
|
||||
{
|
||||
static final long serialVersionUID = -7116225100474153751L;
|
||||
|
||||
/**
|
||||
* Execute the function. The function must return
|
||||
* a valid object.
|
||||
* @param xctxt The current execution context.
|
||||
* @return A valid XObject.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException
|
||||
{
|
||||
|
||||
// DTMIterator nl = m_arg0.asIterator(xctxt, xctxt.getCurrentNode());
|
||||
|
||||
// // We should probably make a function on the iterator for this,
|
||||
// // as a given implementation could optimize.
|
||||
// int i = 0;
|
||||
//
|
||||
// while (DTM.NULL != nl.nextNode())
|
||||
// {
|
||||
// i++;
|
||||
// }
|
||||
// nl.detach();
|
||||
DTMIterator nl = m_arg0.asIterator(xctxt, xctxt.getCurrentNode());
|
||||
int i = nl.getLength();
|
||||
nl.detach();
|
||||
|
||||
return new XNumber((double) i);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.functions;
|
||||
|
||||
import com.sun.org.apache.xml.internal.dtm.DTM;
|
||||
import com.sun.org.apache.xml.internal.dtm.DTMIterator;
|
||||
import com.sun.org.apache.xpath.internal.XPathContext;
|
||||
import com.sun.org.apache.xpath.internal.axes.LocPathIterator;
|
||||
import com.sun.org.apache.xpath.internal.axes.PredicatedNodeTest;
|
||||
import com.sun.org.apache.xpath.internal.objects.XNodeSet;
|
||||
import com.sun.org.apache.xpath.internal.objects.XObject;
|
||||
import com.sun.org.apache.xpath.internal.axes.SubContextList;
|
||||
import com.sun.org.apache.xpath.internal.patterns.StepPattern;
|
||||
import com.sun.org.apache.xalan.internal.res.XSLMessages;
|
||||
import com.sun.org.apache.xalan.internal.res.XSLTErrorResources;
|
||||
|
||||
|
||||
/**
|
||||
* Execute the current() function.
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public class FuncCurrent extends Function
|
||||
{
|
||||
static final long serialVersionUID = 5715316804877715008L;
|
||||
|
||||
/**
|
||||
* Execute the function. The function must return
|
||||
* a valid object.
|
||||
* @param xctxt The current execution context.
|
||||
* @return A valid XObject.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException
|
||||
{
|
||||
|
||||
SubContextList subContextList = xctxt.getCurrentNodeList();
|
||||
int currentNode = DTM.NULL;
|
||||
|
||||
if (null != subContextList) {
|
||||
if (subContextList instanceof PredicatedNodeTest) {
|
||||
LocPathIterator iter = ((PredicatedNodeTest)subContextList)
|
||||
.getLocPathIterator();
|
||||
currentNode = iter.getCurrentContextNode();
|
||||
} else if(subContextList instanceof StepPattern) {
|
||||
throw new RuntimeException(XSLMessages.createMessage(
|
||||
XSLTErrorResources.ER_PROCESSOR_ERROR,null));
|
||||
}
|
||||
} else {
|
||||
// not predicate => ContextNode == CurrentNode
|
||||
currentNode = xctxt.getContextNode();
|
||||
}
|
||||
return new XNodeSet(currentNode, xctxt.getDTMManager());
|
||||
}
|
||||
|
||||
/**
|
||||
* No arguments to process, so this does nothing.
|
||||
*/
|
||||
public void fixupVariables(java.util.Vector vars, int globalsSize)
|
||||
{
|
||||
// no-op
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.functions;
|
||||
|
||||
import com.sun.org.apache.xml.internal.dtm.DTM;
|
||||
import com.sun.org.apache.xpath.internal.XPathContext;
|
||||
import com.sun.org.apache.xpath.internal.objects.XObject;
|
||||
import com.sun.org.apache.xpath.internal.objects.XString;
|
||||
|
||||
/**
|
||||
* Execute the proprietary document-location() function, which returns
|
||||
* a node set of documents.
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public class FuncDoclocation extends FunctionDef1Arg
|
||||
{
|
||||
static final long serialVersionUID = 7469213946343568769L;
|
||||
|
||||
/**
|
||||
* Execute the function. The function must return
|
||||
* a valid object.
|
||||
* @param xctxt The current execution context.
|
||||
* @return A valid XObject.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException
|
||||
{
|
||||
|
||||
int whereNode = getArg0AsNode(xctxt);
|
||||
String fileLocation = null;
|
||||
|
||||
if (DTM.NULL != whereNode)
|
||||
{
|
||||
DTM dtm = xctxt.getDTM(whereNode);
|
||||
|
||||
// %REVIEW%
|
||||
if (DTM.DOCUMENT_FRAGMENT_NODE == dtm.getNodeType(whereNode))
|
||||
{
|
||||
whereNode = dtm.getFirstChild(whereNode);
|
||||
}
|
||||
|
||||
if (DTM.NULL != whereNode)
|
||||
{
|
||||
fileLocation = dtm.getDocumentBaseURI();
|
||||
// int owner = dtm.getDocument();
|
||||
// fileLocation = xctxt.getSourceTreeManager().findURIFromDoc(owner);
|
||||
}
|
||||
}
|
||||
|
||||
return new XString((null != fileLocation) ? fileLocation : "");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.functions;
|
||||
|
||||
import com.sun.org.apache.xalan.internal.templates.Constants;
|
||||
// J2SE does not support Xalan interpretive
|
||||
/*
|
||||
import com.sun.org.apache.xalan.internal.transformer.TransformerImpl;
|
||||
*/
|
||||
import com.sun.org.apache.xml.internal.utils.QName;
|
||||
import com.sun.org.apache.xpath.internal.ExtensionsProvider;
|
||||
import com.sun.org.apache.xpath.internal.XPathContext;
|
||||
import com.sun.org.apache.xpath.internal.objects.XBoolean;
|
||||
import com.sun.org.apache.xpath.internal.objects.XObject;
|
||||
|
||||
/**
|
||||
* Execute the ExtElementAvailable() function.
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public class FuncExtElementAvailable extends FunctionOneArg
|
||||
{
|
||||
static final long serialVersionUID = -472533699257968546L;
|
||||
|
||||
/**
|
||||
* Execute the function. The function must return
|
||||
* a valid object.
|
||||
* @param xctxt The current execution context.
|
||||
* @return A valid XObject.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException
|
||||
{
|
||||
|
||||
String prefix;
|
||||
String namespace;
|
||||
String methName;
|
||||
|
||||
String fullName = m_arg0.execute(xctxt).str();
|
||||
int indexOfNSSep = fullName.indexOf(':');
|
||||
|
||||
if (indexOfNSSep < 0)
|
||||
{
|
||||
prefix = "";
|
||||
namespace = Constants.S_XSLNAMESPACEURL;
|
||||
methName = fullName;
|
||||
}
|
||||
else
|
||||
{
|
||||
prefix = fullName.substring(0, indexOfNSSep);
|
||||
namespace = xctxt.getNamespaceContext().getNamespaceForPrefix(prefix);
|
||||
if (null == namespace)
|
||||
return XBoolean.S_FALSE;
|
||||
methName= fullName.substring(indexOfNSSep + 1);
|
||||
}
|
||||
|
||||
if (namespace.equals(Constants.S_XSLNAMESPACEURL)
|
||||
|| namespace.equals(Constants.S_BUILTIN_EXTENSIONS_URL)) {
|
||||
|
||||
// J2SE does not support Xalan interpretive
|
||||
/*
|
||||
try {
|
||||
TransformerImpl transformer = (TransformerImpl) xctxt.getOwnerObject();
|
||||
return transformer.getStylesheet().getAvailableElements().containsKey(
|
||||
new QName(namespace, methName))
|
||||
? XBoolean.S_TRUE : XBoolean.S_FALSE;
|
||||
} catch (Exception e) {
|
||||
return XBoolean.S_FALSE;
|
||||
}
|
||||
*/
|
||||
return XBoolean.S_FALSE;
|
||||
} else {
|
||||
//dml
|
||||
ExtensionsProvider extProvider = (ExtensionsProvider)xctxt.getOwnerObject();
|
||||
return extProvider.elementAvailable(namespace, methName)
|
||||
? XBoolean.S_TRUE : XBoolean.S_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,341 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.functions;
|
||||
|
||||
import java.util.Vector;
|
||||
|
||||
import com.sun.org.apache.xalan.internal.res.XSLMessages;
|
||||
import com.sun.org.apache.xpath.internal.Expression;
|
||||
import com.sun.org.apache.xpath.internal.ExpressionNode;
|
||||
import com.sun.org.apache.xpath.internal.ExpressionOwner;
|
||||
import com.sun.org.apache.xpath.internal.ExtensionsProvider;
|
||||
import com.sun.org.apache.xpath.internal.XPathContext;
|
||||
import com.sun.org.apache.xpath.internal.XPathVisitor;
|
||||
import com.sun.org.apache.xpath.internal.objects.XNull;
|
||||
import com.sun.org.apache.xpath.internal.objects.XObject;
|
||||
import com.sun.org.apache.xpath.internal.res.XPATHErrorResources;
|
||||
import com.sun.org.apache.xpath.internal.res.XPATHMessages;
|
||||
|
||||
/**
|
||||
* An object of this class represents an extension call expression. When
|
||||
* the expression executes, it calls ExtensionsTable#extFunction, and then
|
||||
* converts the result to the appropriate XObject.
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public class FuncExtFunction extends Function
|
||||
{
|
||||
static final long serialVersionUID = 5196115554693708718L;
|
||||
|
||||
/**
|
||||
* The namespace for the extension function, which should not normally
|
||||
* be null or empty.
|
||||
* @serial
|
||||
*/
|
||||
String m_namespace;
|
||||
|
||||
/**
|
||||
* The local name of the extension.
|
||||
* @serial
|
||||
*/
|
||||
String m_extensionName;
|
||||
|
||||
/**
|
||||
* Unique method key, which is passed to ExtensionsTable#extFunction in
|
||||
* order to allow caching of the method.
|
||||
* @serial
|
||||
*/
|
||||
Object m_methodKey;
|
||||
|
||||
/**
|
||||
* Array of static expressions which represent the parameters to the
|
||||
* function.
|
||||
* @serial
|
||||
*/
|
||||
Vector m_argVec = new Vector();
|
||||
|
||||
/**
|
||||
* This function is used to fixup variables from QNames to stack frame
|
||||
* indexes at stylesheet build time.
|
||||
* @param vars List of QNames that correspond to variables. This list
|
||||
* should be searched backwards for the first qualified name that
|
||||
* corresponds to the variable reference qname. The position of the
|
||||
* QName in the vector from the start of the vector will be its position
|
||||
* in the stack frame (but variables above the globalsTop value will need
|
||||
* to be offset to the current stack frame).
|
||||
* NEEDSDOC @param globalsSize
|
||||
*/
|
||||
public void fixupVariables(java.util.Vector vars, int globalsSize)
|
||||
{
|
||||
|
||||
if (null != m_argVec)
|
||||
{
|
||||
int nArgs = m_argVec.size();
|
||||
|
||||
for (int i = 0; i < nArgs; i++)
|
||||
{
|
||||
Expression arg = (Expression) m_argVec.elementAt(i);
|
||||
|
||||
arg.fixupVariables(vars, globalsSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the namespace of the extension function.
|
||||
*
|
||||
* @return The namespace of the extension function.
|
||||
*/
|
||||
public String getNamespace()
|
||||
{
|
||||
return m_namespace;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of the extension function.
|
||||
*
|
||||
* @return The name of the extension function.
|
||||
*/
|
||||
public String getFunctionName()
|
||||
{
|
||||
return m_extensionName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the method key of the extension function.
|
||||
*
|
||||
* @return The method key of the extension function.
|
||||
*/
|
||||
public Object getMethodKey()
|
||||
{
|
||||
return m_methodKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the nth argument passed to the extension function.
|
||||
*
|
||||
* @param n The argument number index.
|
||||
* @return The Expression object at the given index.
|
||||
*/
|
||||
public Expression getArg(int n) {
|
||||
if (n >= 0 && n < m_argVec.size())
|
||||
return (Expression) m_argVec.elementAt(n);
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the number of arguments that were passed
|
||||
* into this extension function.
|
||||
*
|
||||
* @return The number of arguments.
|
||||
*/
|
||||
public int getArgCount() {
|
||||
return m_argVec.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new FuncExtFunction based on the qualified name of the extension,
|
||||
* and a unique method key.
|
||||
*
|
||||
* @param namespace The namespace for the extension function, which should
|
||||
* not normally be null or empty.
|
||||
* @param extensionName The local name of the extension.
|
||||
* @param methodKey Unique method key, which is passed to
|
||||
* ExtensionsTable#extFunction in order to allow caching
|
||||
* of the method.
|
||||
*/
|
||||
public FuncExtFunction(java.lang.String namespace,
|
||||
java.lang.String extensionName, Object methodKey)
|
||||
{
|
||||
//try{throw new Exception("FuncExtFunction() " + namespace + " " + extensionName);} catch (Exception e){e.printStackTrace();}
|
||||
m_namespace = namespace;
|
||||
m_extensionName = extensionName;
|
||||
m_methodKey = methodKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the function. The function must return
|
||||
* a valid object.
|
||||
* @param xctxt The current execution context.
|
||||
* @return A valid XObject.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
public XObject execute(XPathContext xctxt)
|
||||
throws javax.xml.transform.TransformerException
|
||||
{
|
||||
if (xctxt.isSecureProcessing())
|
||||
throw new javax.xml.transform.TransformerException(
|
||||
XPATHMessages.createXPATHMessage(
|
||||
XPATHErrorResources.ER_EXTENSION_FUNCTION_CANNOT_BE_INVOKED,
|
||||
new Object[] {toString()}));
|
||||
|
||||
XObject result;
|
||||
Vector argVec = new Vector();
|
||||
int nArgs = m_argVec.size();
|
||||
|
||||
for (int i = 0; i < nArgs; i++)
|
||||
{
|
||||
Expression arg = (Expression) m_argVec.elementAt(i);
|
||||
|
||||
XObject xobj = arg.execute(xctxt);
|
||||
/*
|
||||
* Should cache the arguments for func:function
|
||||
*/
|
||||
xobj.allowDetachToRelease(false);
|
||||
argVec.addElement(xobj);
|
||||
}
|
||||
//dml
|
||||
ExtensionsProvider extProvider = (ExtensionsProvider)xctxt.getOwnerObject();
|
||||
Object val = extProvider.extFunction(this, argVec);
|
||||
|
||||
if (null != val)
|
||||
{
|
||||
result = XObject.create(val, xctxt);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = new XNull();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an argument expression for a function. This method is called by the
|
||||
* XPath compiler.
|
||||
*
|
||||
* @param arg non-null expression that represents the argument.
|
||||
* @param argNum The argument number index.
|
||||
*
|
||||
* @throws WrongNumberArgsException If the argNum parameter is beyond what
|
||||
* is specified for this function.
|
||||
*/
|
||||
public void setArg(Expression arg, int argNum)
|
||||
throws WrongNumberArgsException
|
||||
{
|
||||
m_argVec.addElement(arg);
|
||||
arg.exprSetParent(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the number of arguments passed to this function is correct.
|
||||
*
|
||||
*
|
||||
* @param argNum The number of arguments that is being passed to the function.
|
||||
*
|
||||
* @throws WrongNumberArgsException
|
||||
*/
|
||||
public void checkNumberArgs(int argNum) throws WrongNumberArgsException{}
|
||||
|
||||
|
||||
class ArgExtOwner implements ExpressionOwner
|
||||
{
|
||||
|
||||
Expression m_exp;
|
||||
|
||||
ArgExtOwner(Expression exp)
|
||||
{
|
||||
m_exp = exp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ExpressionOwner#getExpression()
|
||||
*/
|
||||
public Expression getExpression()
|
||||
{
|
||||
return m_exp;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see ExpressionOwner#setExpression(Expression)
|
||||
*/
|
||||
public void setExpression(Expression exp)
|
||||
{
|
||||
exp.exprSetParent(FuncExtFunction.this);
|
||||
m_exp = exp;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Call the visitors for the function arguments.
|
||||
*/
|
||||
public void callArgVisitors(XPathVisitor visitor)
|
||||
{
|
||||
for (int i = 0; i < m_argVec.size(); i++)
|
||||
{
|
||||
Expression exp = (Expression)m_argVec.elementAt(i);
|
||||
exp.callVisitors(new ArgExtOwner(exp), visitor);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the parent node.
|
||||
* For an extension function, we also need to set the parent
|
||||
* node for all argument expressions.
|
||||
*
|
||||
* @param n The parent node
|
||||
*/
|
||||
public void exprSetParent(ExpressionNode n)
|
||||
{
|
||||
|
||||
super.exprSetParent(n);
|
||||
|
||||
int nArgs = m_argVec.size();
|
||||
|
||||
for (int i = 0; i < nArgs; i++)
|
||||
{
|
||||
Expression arg = (Expression) m_argVec.elementAt(i);
|
||||
|
||||
arg.exprSetParent(n);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs and throws a WrongNumberArgException with the appropriate
|
||||
* message for this function object. This class supports an arbitrary
|
||||
* number of arguments, so this method must never be called.
|
||||
*
|
||||
* @throws WrongNumberArgsException
|
||||
*/
|
||||
protected void reportWrongNumberArgs() throws WrongNumberArgsException {
|
||||
String fMsg = XSLMessages.createXPATHMessage(
|
||||
XPATHErrorResources.ER_INCORRECT_PROGRAMMER_ASSERTION,
|
||||
new Object[]{ "Programmer's assertion: the method FunctionMultiArgs.reportWrongNumberArgs() should never be called." });
|
||||
|
||||
throw new RuntimeException(fMsg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of the extesion function in string format
|
||||
*/
|
||||
public String toString()
|
||||
{
|
||||
if (m_namespace != null && m_namespace.length() > 0)
|
||||
return "{" + m_namespace + "}" + m_extensionName;
|
||||
else
|
||||
return m_extensionName;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.functions;
|
||||
|
||||
import com.sun.org.apache.xalan.internal.templates.Constants;
|
||||
import com.sun.org.apache.xpath.internal.ExtensionsProvider;
|
||||
import com.sun.org.apache.xpath.internal.XPathContext;
|
||||
import com.sun.org.apache.xpath.internal.compiler.FunctionTable;
|
||||
import com.sun.org.apache.xpath.internal.objects.XBoolean;
|
||||
import com.sun.org.apache.xpath.internal.objects.XObject;
|
||||
|
||||
/**
|
||||
* Execute the ExtFunctionAvailable() function.
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public class FuncExtFunctionAvailable extends FunctionOneArg
|
||||
{
|
||||
static final long serialVersionUID = 5118814314918592241L;
|
||||
|
||||
transient private FunctionTable m_functionTable = null;
|
||||
|
||||
/**
|
||||
* Execute the function. The function must return
|
||||
* a valid object.
|
||||
* @param xctxt The current execution context.
|
||||
* @return A valid XObject.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException
|
||||
{
|
||||
|
||||
String prefix;
|
||||
String namespace;
|
||||
String methName;
|
||||
|
||||
String fullName = m_arg0.execute(xctxt).str();
|
||||
int indexOfNSSep = fullName.indexOf(':');
|
||||
|
||||
if (indexOfNSSep < 0)
|
||||
{
|
||||
prefix = "";
|
||||
namespace = Constants.S_XSLNAMESPACEURL;
|
||||
methName = fullName;
|
||||
}
|
||||
else
|
||||
{
|
||||
prefix = fullName.substring(0, indexOfNSSep);
|
||||
namespace = xctxt.getNamespaceContext().getNamespaceForPrefix(prefix);
|
||||
if (null == namespace)
|
||||
return XBoolean.S_FALSE;
|
||||
methName = fullName.substring(indexOfNSSep + 1);
|
||||
}
|
||||
|
||||
if (namespace.equals(Constants.S_XSLNAMESPACEURL))
|
||||
{
|
||||
try
|
||||
{
|
||||
if (null == m_functionTable) m_functionTable = new FunctionTable();
|
||||
return m_functionTable.functionAvailable(methName) ? XBoolean.S_TRUE : XBoolean.S_FALSE;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return XBoolean.S_FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//dml
|
||||
ExtensionsProvider extProvider = (ExtensionsProvider)xctxt.getOwnerObject();
|
||||
return extProvider.functionAvailable(namespace, methName)
|
||||
? XBoolean.S_TRUE : XBoolean.S_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The function table is an instance field. In order to access this instance
|
||||
* field during evaluation, this method is called at compilation time to
|
||||
* insert function table information for later usage. It should only be used
|
||||
* during compiling of XPath expressions.
|
||||
* @param aTable an instance of the function table
|
||||
*/
|
||||
public void setFunctionTable(FunctionTable aTable){
|
||||
m_functionTable = aTable;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.functions;
|
||||
|
||||
import com.sun.org.apache.xpath.internal.XPathContext;
|
||||
import com.sun.org.apache.xpath.internal.objects.XBoolean;
|
||||
import com.sun.org.apache.xpath.internal.objects.XObject;
|
||||
|
||||
/**
|
||||
* Execute the False() function.
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public class FuncFalse extends Function
|
||||
{
|
||||
static final long serialVersionUID = 6150918062759769887L;
|
||||
|
||||
/**
|
||||
* Execute the function. The function must return
|
||||
* a valid object.
|
||||
* @param xctxt The current execution context.
|
||||
* @return A valid XObject.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException
|
||||
{
|
||||
return XBoolean.S_FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* No arguments to process, so this does nothing.
|
||||
*/
|
||||
public void fixupVariables(java.util.Vector vars, int globalsSize)
|
||||
{
|
||||
// no-op
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.functions;
|
||||
|
||||
import com.sun.org.apache.xpath.internal.XPathContext;
|
||||
import com.sun.org.apache.xpath.internal.objects.XNumber;
|
||||
import com.sun.org.apache.xpath.internal.objects.XObject;
|
||||
|
||||
/**
|
||||
* Execute the Floor() function.
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public class FuncFloor extends FunctionOneArg
|
||||
{
|
||||
static final long serialVersionUID = 2326752233236309265L;
|
||||
|
||||
/**
|
||||
* Execute the function. The function must return
|
||||
* a valid object.
|
||||
* @param xctxt The current execution context.
|
||||
* @return A valid XObject.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException
|
||||
{
|
||||
return new XNumber(java.lang.Math.floor(m_arg0.execute(xctxt).num()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.functions;
|
||||
|
||||
import com.sun.org.apache.xml.internal.dtm.DTM;
|
||||
import com.sun.org.apache.xpath.internal.XPathContext;
|
||||
import com.sun.org.apache.xpath.internal.objects.XObject;
|
||||
import com.sun.org.apache.xpath.internal.objects.XString;
|
||||
|
||||
/**
|
||||
* Execute the GenerateId() function.
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public class FuncGenerateId extends FunctionDef1Arg
|
||||
{
|
||||
static final long serialVersionUID = 973544842091724273L;
|
||||
|
||||
/**
|
||||
* Execute the function. The function must return
|
||||
* a valid object.
|
||||
* @param xctxt The current execution context.
|
||||
* @return A valid XObject.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException
|
||||
{
|
||||
|
||||
int which = getArg0AsNode(xctxt);
|
||||
|
||||
if (DTM.NULL != which)
|
||||
{
|
||||
// Note that this is a different value than in previous releases
|
||||
// of Xalan. It's sensitive to the exact encoding of the node
|
||||
// handle anyway, so fighting to maintain backward compatability
|
||||
// really didn't make sense; it may change again as we continue
|
||||
// to experiment with balancing document and node numbers within
|
||||
// that value.
|
||||
return new XString("N" + Integer.toHexString(which).toUpperCase());
|
||||
}
|
||||
else
|
||||
return XString.EMPTYSTRING;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
*/
|
||||
/**
|
||||
* 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 com.sun.org.apache.xpath.internal.functions;
|
||||
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Node;
|
||||
import com.sun.org.apache.xml.internal.dtm.DTM;
|
||||
import com.sun.org.apache.xpath.internal.NodeSetDTM;
|
||||
import com.sun.org.apache.xpath.internal.XPathContext;
|
||||
import com.sun.org.apache.xpath.internal.objects.XNodeSet;
|
||||
import com.sun.org.apache.xpath.internal.objects.XObject;
|
||||
import com.sun.org.apache.xpath.internal.res.XPATHErrorResources;
|
||||
|
||||
/**
|
||||
* Execute the XML Signature here() function.
|
||||
*/
|
||||
public final class FuncHere extends Function {
|
||||
|
||||
private static final long serialVersionUID = 4328660760070034592L;
|
||||
|
||||
@Override
|
||||
public XObject execute(XPathContext xctxt) throws TransformerException {
|
||||
Node xpathOwnerNode = (Node)xctxt.getOwnerObject();
|
||||
if (xpathOwnerNode == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
int xpathOwnerNodeDTM = xctxt.getDTMHandleFromNode(xpathOwnerNode);
|
||||
int currentNode = xctxt.getCurrentNode();
|
||||
DTM dtm = xctxt.getDTM(currentNode);
|
||||
int docContext = dtm.getDocument();
|
||||
|
||||
if (docContext == DTM.NULL) {
|
||||
error(xctxt, XPATHErrorResources.ER_CONTEXT_HAS_NO_OWNERDOC, null);
|
||||
}
|
||||
|
||||
// check whether currentNode and the node containing the XPath
|
||||
// expression are in the same document
|
||||
Document currentDoc = getOwnerDocument(dtm.getNode(currentNode));
|
||||
Document xpathOwnerDoc = getOwnerDocument(xpathOwnerNode);
|
||||
|
||||
if (currentDoc != xpathOwnerDoc) {
|
||||
throw new TransformerException("Owner documents differ");
|
||||
}
|
||||
|
||||
XNodeSet nodes = new XNodeSet(xctxt.getDTMManager());
|
||||
NodeSetDTM nodeSet = nodes.mutableNodeset();
|
||||
|
||||
int hereNode = DTM.NULL;
|
||||
|
||||
switch (dtm.getNodeType(xpathOwnerNodeDTM)) {
|
||||
|
||||
case Node.ATTRIBUTE_NODE:
|
||||
case Node.PROCESSING_INSTRUCTION_NODE: {
|
||||
// returns a node-set containing the attribute / processing
|
||||
// instruction node
|
||||
hereNode = xpathOwnerNodeDTM;
|
||||
nodeSet.addNode(hereNode);
|
||||
break;
|
||||
}
|
||||
case Node.TEXT_NODE : {
|
||||
// returns a node-set containing the parent element of the
|
||||
// text node that directly bears the XPath expression
|
||||
hereNode = dtm.getParent(xpathOwnerNodeDTM);
|
||||
nodeSet.addNode(hereNode);
|
||||
break;
|
||||
}
|
||||
default :
|
||||
break;
|
||||
}
|
||||
|
||||
/** $todo$ Do I have to do this detach() call? */
|
||||
nodeSet.detach();
|
||||
|
||||
return nodes;
|
||||
}
|
||||
|
||||
private static Document getOwnerDocument(Node node) {
|
||||
if (node.getNodeType() == Node.DOCUMENT_NODE) {
|
||||
return (Document)node;
|
||||
}
|
||||
return node.getOwnerDocument();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fixupVariables(java.util.Vector vars, int globalsSize) { }
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.functions;
|
||||
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import com.sun.org.apache.xml.internal.dtm.DTM;
|
||||
import com.sun.org.apache.xml.internal.dtm.DTMIterator;
|
||||
import com.sun.org.apache.xml.internal.utils.StringVector;
|
||||
import com.sun.org.apache.xpath.internal.NodeSetDTM;
|
||||
import com.sun.org.apache.xpath.internal.XPathContext;
|
||||
import com.sun.org.apache.xpath.internal.objects.XNodeSet;
|
||||
import com.sun.org.apache.xpath.internal.objects.XObject;
|
||||
import com.sun.org.apache.xpath.internal.res.XPATHErrorResources;
|
||||
|
||||
/**
|
||||
* Execute the Id() function.
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public class FuncId extends FunctionOneArg
|
||||
{
|
||||
static final long serialVersionUID = 8930573966143567310L;
|
||||
|
||||
/**
|
||||
* Fill in a list with nodes that match a space delimited list if ID
|
||||
* ID references.
|
||||
*
|
||||
* @param xctxt The runtime XPath context.
|
||||
* @param docContext The document where the nodes are being looked for.
|
||||
* @param refval A space delimited list of ID references.
|
||||
* @param usedrefs List of references for which nodes were found.
|
||||
* @param nodeSet Node set where the nodes will be added to.
|
||||
* @param mayBeMore true if there is another set of nodes to be looked for.
|
||||
*
|
||||
* @return The usedrefs value.
|
||||
*/
|
||||
private StringVector getNodesByID(XPathContext xctxt, int docContext,
|
||||
String refval, StringVector usedrefs,
|
||||
NodeSetDTM nodeSet, boolean mayBeMore)
|
||||
{
|
||||
|
||||
if (null != refval)
|
||||
{
|
||||
String ref = null;
|
||||
// DOMHelper dh = xctxt.getDOMHelper();
|
||||
StringTokenizer tokenizer = new StringTokenizer(refval);
|
||||
boolean hasMore = tokenizer.hasMoreTokens();
|
||||
DTM dtm = xctxt.getDTM(docContext);
|
||||
|
||||
while (hasMore)
|
||||
{
|
||||
ref = tokenizer.nextToken();
|
||||
hasMore = tokenizer.hasMoreTokens();
|
||||
|
||||
if ((null != usedrefs) && usedrefs.contains(ref))
|
||||
{
|
||||
ref = null;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
int node = dtm.getElementById(ref);
|
||||
|
||||
if (DTM.NULL != node)
|
||||
nodeSet.addNodeInDocOrder(node, xctxt);
|
||||
|
||||
if ((null != ref) && (hasMore || mayBeMore))
|
||||
{
|
||||
if (null == usedrefs)
|
||||
usedrefs = new StringVector();
|
||||
|
||||
usedrefs.addElement(ref);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return usedrefs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the function. The function must return
|
||||
* a valid object.
|
||||
* @param xctxt The current execution context.
|
||||
* @return A valid XObject.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException
|
||||
{
|
||||
|
||||
int context = xctxt.getCurrentNode();
|
||||
DTM dtm = xctxt.getDTM(context);
|
||||
int docContext = dtm.getDocument();
|
||||
|
||||
if (DTM.NULL == docContext)
|
||||
error(xctxt, XPATHErrorResources.ER_CONTEXT_HAS_NO_OWNERDOC, null);
|
||||
|
||||
XObject arg = m_arg0.execute(xctxt);
|
||||
int argType = arg.getType();
|
||||
XNodeSet nodes = new XNodeSet(xctxt.getDTMManager());
|
||||
NodeSetDTM nodeSet = nodes.mutableNodeset();
|
||||
|
||||
if (XObject.CLASS_NODESET == argType)
|
||||
{
|
||||
DTMIterator ni = arg.iter();
|
||||
StringVector usedrefs = null;
|
||||
int pos = ni.nextNode();
|
||||
|
||||
while (DTM.NULL != pos)
|
||||
{
|
||||
DTM ndtm = ni.getDTM(pos);
|
||||
String refval = ndtm.getStringValue(pos).toString();
|
||||
|
||||
pos = ni.nextNode();
|
||||
usedrefs = getNodesByID(xctxt, docContext, refval, usedrefs, nodeSet,
|
||||
DTM.NULL != pos);
|
||||
}
|
||||
// ni.detach();
|
||||
}
|
||||
else if (XObject.CLASS_NULL == argType)
|
||||
{
|
||||
return nodes;
|
||||
}
|
||||
else
|
||||
{
|
||||
String refval = arg.str();
|
||||
|
||||
getNodesByID(xctxt, docContext, refval, null, nodeSet, false);
|
||||
}
|
||||
|
||||
return nodes;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.functions;
|
||||
|
||||
import com.sun.org.apache.xml.internal.dtm.DTM;
|
||||
import com.sun.org.apache.xpath.internal.XPathContext;
|
||||
import com.sun.org.apache.xpath.internal.objects.XBoolean;
|
||||
import com.sun.org.apache.xpath.internal.objects.XObject;
|
||||
|
||||
/**
|
||||
* Execute the Lang() function.
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public class FuncLang extends FunctionOneArg
|
||||
{
|
||||
static final long serialVersionUID = -7868705139354872185L;
|
||||
|
||||
/**
|
||||
* Execute the function. The function must return
|
||||
* a valid object.
|
||||
* @param xctxt The current execution context.
|
||||
* @return A valid XObject.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException
|
||||
{
|
||||
|
||||
String lang = m_arg0.execute(xctxt).str();
|
||||
int parent = xctxt.getCurrentNode();
|
||||
boolean isLang = false;
|
||||
DTM dtm = xctxt.getDTM(parent);
|
||||
|
||||
while (DTM.NULL != parent)
|
||||
{
|
||||
if (DTM.ELEMENT_NODE == dtm.getNodeType(parent))
|
||||
{
|
||||
int langAttr = dtm.getAttributeNode(parent, "http://www.w3.org/XML/1998/namespace", "lang");
|
||||
|
||||
if (DTM.NULL != langAttr)
|
||||
{
|
||||
String langVal = dtm.getNodeValue(langAttr);
|
||||
// %OPT%
|
||||
if (langVal.toLowerCase().startsWith(lang.toLowerCase()))
|
||||
{
|
||||
int valLen = lang.length();
|
||||
|
||||
if ((langVal.length() == valLen)
|
||||
|| (langVal.charAt(valLen) == '-'))
|
||||
{
|
||||
isLang = true;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
parent = dtm.getParent(parent);
|
||||
}
|
||||
|
||||
return isLang ? XBoolean.S_TRUE : XBoolean.S_FALSE;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.functions;
|
||||
|
||||
import com.sun.org.apache.xml.internal.dtm.DTMIterator;
|
||||
import com.sun.org.apache.xpath.internal.XPathContext;
|
||||
import com.sun.org.apache.xpath.internal.axes.SubContextList;
|
||||
import com.sun.org.apache.xpath.internal.compiler.Compiler;
|
||||
import com.sun.org.apache.xpath.internal.objects.XNumber;
|
||||
import com.sun.org.apache.xpath.internal.objects.XObject;
|
||||
|
||||
|
||||
/**
|
||||
* Execute the Last() function.
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public class FuncLast extends Function
|
||||
{
|
||||
static final long serialVersionUID = 9205812403085432943L;
|
||||
|
||||
private boolean m_isTopLevel;
|
||||
|
||||
/**
|
||||
* Figure out if we're executing a toplevel expression.
|
||||
* If so, we can't be inside of a predicate.
|
||||
*/
|
||||
public void postCompileStep(Compiler compiler)
|
||||
{
|
||||
m_isTopLevel = compiler.getLocationPathDepth() == -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the position in the current context node list.
|
||||
*
|
||||
* @param xctxt non-null reference to XPath runtime context.
|
||||
*
|
||||
* @return The number of nodes in the list.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
public int getCountOfContextNodeList(XPathContext xctxt)
|
||||
throws javax.xml.transform.TransformerException
|
||||
{
|
||||
|
||||
// assert(null != m_contextNodeList, "m_contextNodeList must be non-null");
|
||||
// If we're in a predicate, then this will return non-null.
|
||||
SubContextList iter = m_isTopLevel ? null : xctxt.getSubContextList();
|
||||
|
||||
// System.out.println("iter: "+iter);
|
||||
if (null != iter)
|
||||
return iter.getLastPos(xctxt);
|
||||
|
||||
DTMIterator cnl = xctxt.getContextNodeList();
|
||||
int count;
|
||||
if(null != cnl)
|
||||
{
|
||||
count = cnl.getLength();
|
||||
// System.out.println("count: "+count);
|
||||
}
|
||||
else
|
||||
count = 0;
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the function. The function must return
|
||||
* a valid object.
|
||||
* @param xctxt The current execution context.
|
||||
* @return A valid XObject.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException
|
||||
{
|
||||
XNumber xnum = new XNumber((double) getCountOfContextNodeList(xctxt));
|
||||
// System.out.println("last: "+xnum.num());
|
||||
return xnum;
|
||||
}
|
||||
|
||||
/**
|
||||
* No arguments to process, so this does nothing.
|
||||
*/
|
||||
public void fixupVariables(java.util.Vector vars, int globalsSize)
|
||||
{
|
||||
// no-op
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.functions;
|
||||
|
||||
import com.sun.org.apache.xml.internal.dtm.DTM;
|
||||
import com.sun.org.apache.xpath.internal.XPathContext;
|
||||
import com.sun.org.apache.xpath.internal.objects.XObject;
|
||||
import com.sun.org.apache.xpath.internal.objects.XString;
|
||||
|
||||
/**
|
||||
* Execute the LocalPart() function.
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public class FuncLocalPart extends FunctionDef1Arg
|
||||
{
|
||||
static final long serialVersionUID = 7591798770325814746L;
|
||||
|
||||
/**
|
||||
* Execute the function. The function must return
|
||||
* a valid object.
|
||||
* @param xctxt The current execution context.
|
||||
* @return A valid XObject.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException
|
||||
{
|
||||
|
||||
int context = getArg0AsNode(xctxt);
|
||||
if(DTM.NULL == context)
|
||||
return XString.EMPTYSTRING;
|
||||
DTM dtm = xctxt.getDTM(context);
|
||||
String s = (context != DTM.NULL) ? dtm.getLocalName(context) : "";
|
||||
if(s.startsWith("#") || s.equals("xmlns"))
|
||||
return XString.EMPTYSTRING;
|
||||
|
||||
return new XString(s);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.functions;
|
||||
|
||||
import com.sun.org.apache.xml.internal.dtm.DTM;
|
||||
import com.sun.org.apache.xpath.internal.XPathContext;
|
||||
import com.sun.org.apache.xpath.internal.objects.XObject;
|
||||
import com.sun.org.apache.xpath.internal.objects.XString;
|
||||
|
||||
/**
|
||||
* Execute the Namespace() function.
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public class FuncNamespace extends FunctionDef1Arg
|
||||
{
|
||||
static final long serialVersionUID = -4695674566722321237L;
|
||||
|
||||
/**
|
||||
* Execute the function. The function must return
|
||||
* a valid object.
|
||||
* @param xctxt The current execution context.
|
||||
* @return A valid XObject.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException
|
||||
{
|
||||
|
||||
int context = getArg0AsNode(xctxt);
|
||||
|
||||
String s;
|
||||
if(context != DTM.NULL)
|
||||
{
|
||||
DTM dtm = xctxt.getDTM(context);
|
||||
int t = dtm.getNodeType(context);
|
||||
if(t == DTM.ELEMENT_NODE)
|
||||
{
|
||||
s = dtm.getNamespaceURI(context);
|
||||
}
|
||||
else if(t == DTM.ATTRIBUTE_NODE)
|
||||
{
|
||||
|
||||
// This function always returns an empty string for namespace nodes.
|
||||
// We check for those here. Fix inspired by Davanum Srinivas.
|
||||
|
||||
s = dtm.getNodeName(context);
|
||||
if(s.startsWith("xmlns:") || s.equals("xmlns"))
|
||||
return XString.EMPTYSTRING;
|
||||
|
||||
s = dtm.getNamespaceURI(context);
|
||||
}
|
||||
else
|
||||
return XString.EMPTYSTRING;
|
||||
}
|
||||
else
|
||||
return XString.EMPTYSTRING;
|
||||
|
||||
return ((null == s) ? XString.EMPTYSTRING : new XString(s));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.functions;
|
||||
|
||||
import com.sun.org.apache.xml.internal.dtm.DTM;
|
||||
import com.sun.org.apache.xml.internal.utils.XMLString;
|
||||
import com.sun.org.apache.xpath.internal.XPathContext;
|
||||
import com.sun.org.apache.xpath.internal.objects.XObject;
|
||||
import com.sun.org.apache.xpath.internal.objects.XString;
|
||||
import org.xml.sax.ContentHandler;
|
||||
|
||||
/**
|
||||
* Execute the normalize-space() function.
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public class FuncNormalizeSpace extends FunctionDef1Arg
|
||||
{
|
||||
static final long serialVersionUID = -3377956872032190880L;
|
||||
|
||||
/**
|
||||
* Execute the function. The function must return
|
||||
* a valid object.
|
||||
* @param xctxt The current execution context.
|
||||
* @return A valid XObject.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException
|
||||
{
|
||||
XMLString s1 = getArg0AsString(xctxt);
|
||||
|
||||
return (XString)s1.fixWhiteSpace(true, true, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute an expression in the XPath runtime context, and return the
|
||||
* result of the expression.
|
||||
*
|
||||
*
|
||||
* @param xctxt The XPath runtime context.
|
||||
*
|
||||
* @return The result of the expression in the form of a <code>XObject</code>.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException if a runtime exception
|
||||
* occurs.
|
||||
*/
|
||||
public void executeCharsToContentHandler(XPathContext xctxt,
|
||||
ContentHandler handler)
|
||||
throws javax.xml.transform.TransformerException,
|
||||
org.xml.sax.SAXException
|
||||
{
|
||||
if(Arg0IsNodesetExpr())
|
||||
{
|
||||
int node = getArg0AsNode(xctxt);
|
||||
if(DTM.NULL != node)
|
||||
{
|
||||
DTM dtm = xctxt.getDTM(node);
|
||||
dtm.dispatchCharactersEvents(node, handler, true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
XObject obj = execute(xctxt);
|
||||
obj.dispatchCharactersEvents(handler);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.functions;
|
||||
|
||||
import com.sun.org.apache.xpath.internal.XPathContext;
|
||||
import com.sun.org.apache.xpath.internal.objects.XBoolean;
|
||||
import com.sun.org.apache.xpath.internal.objects.XObject;
|
||||
|
||||
/**
|
||||
* Execute the Not() function.
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public class FuncNot extends FunctionOneArg
|
||||
{
|
||||
static final long serialVersionUID = 7299699961076329790L;
|
||||
|
||||
/**
|
||||
* Execute the function. The function must return
|
||||
* a valid object.
|
||||
* @param xctxt The current execution context.
|
||||
* @return A valid XObject.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException
|
||||
{
|
||||
return m_arg0.execute(xctxt).bool() ? XBoolean.S_FALSE : XBoolean.S_TRUE;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.functions;
|
||||
|
||||
import com.sun.org.apache.xpath.internal.XPathContext;
|
||||
import com.sun.org.apache.xpath.internal.objects.XNumber;
|
||||
import com.sun.org.apache.xpath.internal.objects.XObject;
|
||||
|
||||
/**
|
||||
* Execute the Number() function.
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public class FuncNumber extends FunctionDef1Arg
|
||||
{
|
||||
static final long serialVersionUID = 7266745342264153076L;
|
||||
|
||||
/**
|
||||
* Execute the function. The function must return
|
||||
* a valid object.
|
||||
* @param xctxt The current execution context.
|
||||
* @return A valid XObject.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException
|
||||
{
|
||||
return new XNumber(getArg0AsNumber(xctxt));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.functions;
|
||||
|
||||
import com.sun.org.apache.xml.internal.dtm.DTM;
|
||||
import com.sun.org.apache.xml.internal.dtm.DTMIterator;
|
||||
import com.sun.org.apache.xpath.internal.XPathContext;
|
||||
import com.sun.org.apache.xpath.internal.axes.SubContextList;
|
||||
import com.sun.org.apache.xpath.internal.compiler.Compiler;
|
||||
import com.sun.org.apache.xpath.internal.objects.XNumber;
|
||||
import com.sun.org.apache.xpath.internal.objects.XObject;
|
||||
|
||||
/**
|
||||
* Execute the Position() function.
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public class FuncPosition extends Function
|
||||
{
|
||||
static final long serialVersionUID = -9092846348197271582L;
|
||||
private boolean m_isTopLevel;
|
||||
|
||||
/**
|
||||
* Figure out if we're executing a toplevel expression.
|
||||
* If so, we can't be inside of a predicate.
|
||||
*/
|
||||
public void postCompileStep(Compiler compiler)
|
||||
{
|
||||
m_isTopLevel = compiler.getLocationPathDepth() == -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the position in the current context node list.
|
||||
*
|
||||
* @param xctxt Runtime XPath context.
|
||||
*
|
||||
* @return The current position of the itteration in the context node list,
|
||||
* or -1 if there is no active context node list.
|
||||
*/
|
||||
public int getPositionInContextNodeList(XPathContext xctxt)
|
||||
{
|
||||
|
||||
// System.out.println("FuncPosition- entry");
|
||||
// If we're in a predicate, then this will return non-null.
|
||||
SubContextList iter = m_isTopLevel ? null : xctxt.getSubContextList();
|
||||
|
||||
if (null != iter)
|
||||
{
|
||||
int prox = iter.getProximityPosition(xctxt);
|
||||
|
||||
// System.out.println("FuncPosition- prox: "+prox);
|
||||
return prox;
|
||||
}
|
||||
|
||||
DTMIterator cnl = xctxt.getContextNodeList();
|
||||
|
||||
if (null != cnl)
|
||||
{
|
||||
int n = cnl.getCurrentNode();
|
||||
if(n == DTM.NULL)
|
||||
{
|
||||
if(cnl.getCurrentPos() == 0)
|
||||
return 0;
|
||||
|
||||
// Then I think we're in a sort. See sort21.xsl. So the iterator has
|
||||
// already been spent, and is not on the node we're processing.
|
||||
// It's highly possible that this is an issue for other context-list
|
||||
// functions. Shouldn't be a problem for last(), and it shouldn't be
|
||||
// a problem for current().
|
||||
try
|
||||
{
|
||||
cnl = cnl.cloneWithReset();
|
||||
}
|
||||
catch(CloneNotSupportedException cnse)
|
||||
{
|
||||
throw new com.sun.org.apache.xml.internal.utils.WrappedRuntimeException(cnse);
|
||||
}
|
||||
int currentNode = xctxt.getContextNode();
|
||||
// System.out.println("currentNode: "+currentNode);
|
||||
while(DTM.NULL != (n = cnl.nextNode()))
|
||||
{
|
||||
if(n == currentNode)
|
||||
break;
|
||||
}
|
||||
}
|
||||
// System.out.println("n: "+n);
|
||||
// System.out.println("FuncPosition- cnl.getCurrentPos(): "+cnl.getCurrentPos());
|
||||
return cnl.getCurrentPos();
|
||||
}
|
||||
|
||||
// System.out.println("FuncPosition - out of guesses: -1");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the function. The function must return
|
||||
* a valid object.
|
||||
* @param xctxt The current execution context.
|
||||
* @return A valid XObject.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException
|
||||
{
|
||||
double pos = (double) getPositionInContextNodeList(xctxt);
|
||||
|
||||
return new XNumber(pos);
|
||||
}
|
||||
|
||||
/**
|
||||
* No arguments to process, so this does nothing.
|
||||
*/
|
||||
public void fixupVariables(java.util.Vector vars, int globalsSize)
|
||||
{
|
||||
// no-op
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.functions;
|
||||
|
||||
import com.sun.org.apache.xml.internal.dtm.DTM;
|
||||
import com.sun.org.apache.xpath.internal.XPathContext;
|
||||
import com.sun.org.apache.xpath.internal.objects.XObject;
|
||||
import com.sun.org.apache.xpath.internal.objects.XString;
|
||||
|
||||
/**
|
||||
* Execute the Qname() function.
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public class FuncQname extends FunctionDef1Arg
|
||||
{
|
||||
static final long serialVersionUID = -1532307875532617380L;
|
||||
|
||||
/**
|
||||
* Execute the function. The function must return
|
||||
* a valid object.
|
||||
* @param xctxt The current execution context.
|
||||
* @return A valid XObject.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException
|
||||
{
|
||||
|
||||
int context = getArg0AsNode(xctxt);
|
||||
XObject val;
|
||||
|
||||
if (DTM.NULL != context)
|
||||
{
|
||||
DTM dtm = xctxt.getDTM(context);
|
||||
String qname = dtm.getNodeNameX(context);
|
||||
val = (null == qname) ? XString.EMPTYSTRING : new XString(qname);
|
||||
}
|
||||
else
|
||||
{
|
||||
val = XString.EMPTYSTRING;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.functions;
|
||||
|
||||
import com.sun.org.apache.xpath.internal.XPathContext;
|
||||
import com.sun.org.apache.xpath.internal.objects.XNumber;
|
||||
import com.sun.org.apache.xpath.internal.objects.XObject;
|
||||
|
||||
/**
|
||||
* Execute the round() function.
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public class FuncRound extends FunctionOneArg
|
||||
{
|
||||
static final long serialVersionUID = -7970583902573826611L;
|
||||
|
||||
/**
|
||||
* Execute the function. The function must return
|
||||
* a valid object.
|
||||
* @param xctxt The current execution context.
|
||||
* @return A valid XObject.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException
|
||||
{
|
||||
final XObject obj = m_arg0.execute(xctxt);
|
||||
final double val= obj.num();
|
||||
if (val >= -0.5 && val < 0) return new XNumber(-0.0);
|
||||
if (val == 0.0) return new XNumber(val);
|
||||
return new XNumber(java.lang.Math.floor(val
|
||||
+ 0.5));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.functions;
|
||||
|
||||
import com.sun.org.apache.xpath.internal.XPathContext;
|
||||
import com.sun.org.apache.xpath.internal.objects.XBoolean;
|
||||
import com.sun.org.apache.xpath.internal.objects.XObject;
|
||||
|
||||
/**
|
||||
* Execute the StartsWith() function.
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public class FuncStartsWith extends Function2Args
|
||||
{
|
||||
static final long serialVersionUID = 2194585774699567928L;
|
||||
|
||||
/**
|
||||
* Execute the function. The function must return
|
||||
* a valid object.
|
||||
* @param xctxt The current execution context.
|
||||
* @return A valid XObject.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException
|
||||
{
|
||||
return m_arg0.execute(xctxt).xstr().startsWith(m_arg1.execute(xctxt).xstr())
|
||||
? XBoolean.S_TRUE : XBoolean.S_FALSE;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.functions;
|
||||
|
||||
import com.sun.org.apache.xpath.internal.XPathContext;
|
||||
import com.sun.org.apache.xpath.internal.objects.XObject;
|
||||
import com.sun.org.apache.xpath.internal.objects.XString;
|
||||
|
||||
/**
|
||||
* Execute the String() function.
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public class FuncString extends FunctionDef1Arg
|
||||
{
|
||||
static final long serialVersionUID = -2206677149497712883L;
|
||||
|
||||
/**
|
||||
* Execute the function. The function must return
|
||||
* a valid object.
|
||||
* @param xctxt The current execution context.
|
||||
* @return A valid XObject.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException
|
||||
{
|
||||
return (XString)getArg0AsString(xctxt);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.functions;
|
||||
|
||||
import com.sun.org.apache.xpath.internal.XPathContext;
|
||||
import com.sun.org.apache.xpath.internal.objects.XNumber;
|
||||
import com.sun.org.apache.xpath.internal.objects.XObject;
|
||||
|
||||
/**
|
||||
* Execute the StringLength() function.
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public class FuncStringLength extends FunctionDef1Arg
|
||||
{
|
||||
static final long serialVersionUID = -159616417996519839L;
|
||||
|
||||
/**
|
||||
* Execute the function. The function must return
|
||||
* a valid object.
|
||||
* @param xctxt The current execution context.
|
||||
* @return A valid XObject.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException
|
||||
{
|
||||
return new XNumber(getArg0AsString(xctxt).length());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.functions;
|
||||
|
||||
import com.sun.org.apache.xalan.internal.res.XSLMessages;
|
||||
import com.sun.org.apache.xml.internal.utils.XMLString;
|
||||
import com.sun.org.apache.xpath.internal.XPathContext;
|
||||
import com.sun.org.apache.xpath.internal.objects.XObject;
|
||||
import com.sun.org.apache.xpath.internal.objects.XString;
|
||||
import com.sun.org.apache.xpath.internal.res.XPATHErrorResources;
|
||||
|
||||
/**
|
||||
* Execute the Substring() function.
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public class FuncSubstring extends Function3Args
|
||||
{
|
||||
static final long serialVersionUID = -5996676095024715502L;
|
||||
|
||||
/**
|
||||
* Execute the function. The function must return
|
||||
* a valid object.
|
||||
* @param xctxt The current execution context.
|
||||
* @return A valid XObject.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException
|
||||
{
|
||||
|
||||
XMLString s1 = m_arg0.execute(xctxt).xstr();
|
||||
double start = m_arg1.execute(xctxt).num();
|
||||
int lenOfS1 = s1.length();
|
||||
XMLString substr;
|
||||
|
||||
if (lenOfS1 <= 0)
|
||||
return XString.EMPTYSTRING;
|
||||
else
|
||||
{
|
||||
int startIndex;
|
||||
|
||||
if (Double.isNaN(start))
|
||||
{
|
||||
|
||||
// Double.MIN_VALUE doesn't work with math below
|
||||
// so just use a big number and hope I never get caught.
|
||||
start = -1000000;
|
||||
startIndex = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
start = Math.round(start);
|
||||
startIndex = (start > 0) ? (int) start - 1 : 0;
|
||||
}
|
||||
|
||||
if (null != m_arg2)
|
||||
{
|
||||
double len = m_arg2.num(xctxt);
|
||||
int end = (int) (Math.round(len) + start) - 1;
|
||||
|
||||
// Normalize end index.
|
||||
if (end < 0)
|
||||
end = 0;
|
||||
else if (end > lenOfS1)
|
||||
end = lenOfS1;
|
||||
|
||||
if (startIndex > lenOfS1)
|
||||
startIndex = lenOfS1;
|
||||
|
||||
substr = s1.substring(startIndex, end);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (startIndex > lenOfS1)
|
||||
startIndex = lenOfS1;
|
||||
substr = s1.substring(startIndex);
|
||||
}
|
||||
}
|
||||
|
||||
return (XString)substr; // cast semi-safe
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the number of arguments passed to this function is correct.
|
||||
*
|
||||
*
|
||||
* @param argNum The number of arguments that is being passed to the function.
|
||||
*
|
||||
* @throws WrongNumberArgsException
|
||||
*/
|
||||
public void checkNumberArgs(int argNum) throws WrongNumberArgsException
|
||||
{
|
||||
if (argNum < 2)
|
||||
reportWrongNumberArgs();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs and throws a WrongNumberArgException with the appropriate
|
||||
* message for this function object.
|
||||
*
|
||||
* @throws WrongNumberArgsException
|
||||
*/
|
||||
protected void reportWrongNumberArgs() throws WrongNumberArgsException {
|
||||
throw new WrongNumberArgsException(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_TWO_OR_THREE, null)); //"2 or 3");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.functions;
|
||||
|
||||
import com.sun.org.apache.xml.internal.utils.XMLString;
|
||||
import com.sun.org.apache.xpath.internal.XPathContext;
|
||||
import com.sun.org.apache.xpath.internal.objects.XObject;
|
||||
import com.sun.org.apache.xpath.internal.objects.XString;
|
||||
|
||||
/**
|
||||
* Execute the SubstringAfter() function.
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public class FuncSubstringAfter extends Function2Args
|
||||
{
|
||||
static final long serialVersionUID = -8119731889862512194L;
|
||||
|
||||
/**
|
||||
* Execute the function. The function must return
|
||||
* a valid object.
|
||||
* @param xctxt The current execution context.
|
||||
* @return A valid XObject.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException
|
||||
{
|
||||
|
||||
XMLString s1 = m_arg0.execute(xctxt).xstr();
|
||||
XMLString s2 = m_arg1.execute(xctxt).xstr();
|
||||
int index = s1.indexOf(s2);
|
||||
|
||||
return (-1 == index)
|
||||
? XString.EMPTYSTRING
|
||||
: (XString)s1.substring(index + s2.length());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.functions;
|
||||
|
||||
import com.sun.org.apache.xpath.internal.XPathContext;
|
||||
import com.sun.org.apache.xpath.internal.objects.XObject;
|
||||
import com.sun.org.apache.xpath.internal.objects.XString;
|
||||
|
||||
/**
|
||||
* Execute the SubstringBefore() function.
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public class FuncSubstringBefore extends Function2Args
|
||||
{
|
||||
static final long serialVersionUID = 4110547161672431775L;
|
||||
|
||||
/**
|
||||
* Execute the function. The function must return
|
||||
* a valid object.
|
||||
* @param xctxt The current execution context.
|
||||
* @return A valid XObject.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException
|
||||
{
|
||||
|
||||
String s1 = m_arg0.execute(xctxt).str();
|
||||
String s2 = m_arg1.execute(xctxt).str();
|
||||
int index = s1.indexOf(s2);
|
||||
|
||||
return (-1 == index)
|
||||
? XString.EMPTYSTRING : new XString(s1.substring(0, index));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.functions;
|
||||
|
||||
import com.sun.org.apache.xml.internal.dtm.DTM;
|
||||
import com.sun.org.apache.xml.internal.dtm.DTMIterator;
|
||||
import com.sun.org.apache.xml.internal.utils.XMLString;
|
||||
import com.sun.org.apache.xpath.internal.XPathContext;
|
||||
import com.sun.org.apache.xpath.internal.objects.XNumber;
|
||||
import com.sun.org.apache.xpath.internal.objects.XObject;
|
||||
|
||||
/**
|
||||
* Execute the Sum() function.
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public class FuncSum extends FunctionOneArg
|
||||
{
|
||||
static final long serialVersionUID = -2719049259574677519L;
|
||||
|
||||
/**
|
||||
* Execute the function. The function must return
|
||||
* a valid object.
|
||||
* @param xctxt The current execution context.
|
||||
* @return A valid XObject.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException
|
||||
{
|
||||
|
||||
DTMIterator nodes = m_arg0.asIterator(xctxt, xctxt.getCurrentNode());
|
||||
double sum = 0.0;
|
||||
int pos;
|
||||
|
||||
while (DTM.NULL != (pos = nodes.nextNode()))
|
||||
{
|
||||
DTM dtm = nodes.getDTM(pos);
|
||||
XMLString s = dtm.getStringValue(pos);
|
||||
|
||||
if (null != s)
|
||||
sum += s.toDouble();
|
||||
}
|
||||
nodes.detach();
|
||||
|
||||
return new XNumber(sum);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* 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 com.sun.org.apache.xpath.internal.functions;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.util.Properties;
|
||||
|
||||
import com.sun.org.apache.xpath.internal.XPathContext;
|
||||
import com.sun.org.apache.xpath.internal.objects.XObject;
|
||||
import com.sun.org.apache.xpath.internal.objects.XString;
|
||||
import com.sun.org.apache.xpath.internal.res.XPATHErrorResources;
|
||||
import com.sun.org.apache.xalan.internal.utils.SecuritySupport;
|
||||
|
||||
/**
|
||||
* Execute the SystemProperty() function.
|
||||
* @xsl.usage advanced
|
||||
*/
|
||||
public class FuncSystemProperty extends FunctionOneArg
|
||||
{
|
||||
static final long serialVersionUID = 3694874980992204867L;
|
||||
/**
|
||||
* The path/filename of the property file: XSLTInfo.properties
|
||||
* Maintenance note: see also
|
||||
* com.sun.org.apache.xalan.internal.processor.TransformerFactoryImpl.XSLT_PROPERTIES
|
||||
*/
|
||||
static final String XSLT_PROPERTIES =
|
||||
"com/sun/org/apache/xalan/internal/res/XSLTInfo.properties";
|
||||
|
||||
/**
|
||||
* Execute the function. The function must return
|
||||
* a valid object.
|
||||
* @param xctxt The current execution context.
|
||||
* @return A valid XObject.
|
||||
*
|
||||
* @throws javax.xml.transform.TransformerException
|
||||
*/
|
||||
public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException
|
||||
{
|
||||
|
||||
String fullName = m_arg0.execute(xctxt).str();
|
||||
int indexOfNSSep = fullName.indexOf(':');
|
||||
String result;
|
||||
String propName = "";
|
||||
|
||||
// List of properties where the name of the
|
||||
// property argument is to be looked for.
|
||||
Properties xsltInfo = new Properties();
|
||||
|
||||
loadPropertyFile(xsltInfo);
|
||||
|
||||
if (indexOfNSSep > 0)
|
||||
{
|
||||
String prefix = (indexOfNSSep >= 0)
|
||||
? fullName.substring(0, indexOfNSSep) : "";
|
||||
String namespace;
|
||||
|
||||
namespace = xctxt.getNamespaceContext().getNamespaceForPrefix(prefix);
|
||||
propName = (indexOfNSSep < 0)
|
||||
? fullName : fullName.substring(indexOfNSSep + 1);
|
||||
|
||||
if (namespace.startsWith("http://www.w3.org/XSL/Transform")
|
||||
|| namespace.equals("http://www.w3.org/1999/XSL/Transform"))
|
||||
{
|
||||
result = xsltInfo.getProperty(propName);
|
||||
|
||||
if (null == result)
|
||||
{
|
||||
warn(xctxt, XPATHErrorResources.WG_PROPERTY_NOT_SUPPORTED,
|
||||
new Object[]{ fullName }); //"XSL Property not supported: "+fullName);
|
||||
|
||||
return XString.EMPTYSTRING;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
warn(xctxt, XPATHErrorResources.WG_DONT_DO_ANYTHING_WITH_NS,
|
||||
new Object[]{ namespace,
|
||||
fullName }); //"Don't currently do anything with namespace "+namespace+" in property: "+fullName);
|
||||
|
||||
try
|
||||
{
|
||||
result = SecuritySupport.getSystemProperty(propName);
|
||||
|
||||
if (null == result)
|
||||
{
|
||||
|
||||
// result = System.getenv(propName);
|
||||
return XString.EMPTYSTRING;
|
||||
}
|
||||
}
|
||||
catch (SecurityException se)
|
||||
{
|
||||
warn(xctxt, XPATHErrorResources.WG_SECURITY_EXCEPTION,
|
||||
new Object[]{ fullName }); //"SecurityException when trying to access XSL system property: "+fullName);
|
||||
|
||||
return XString.EMPTYSTRING;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
result = SecuritySupport.getSystemProperty(fullName);
|
||||
|
||||
if (null == result)
|
||||
{
|
||||
|
||||
// result = System.getenv(fullName);
|
||||
return XString.EMPTYSTRING;
|
||||
}
|
||||
}
|
||||
catch (SecurityException se)
|
||||
{
|
||||
warn(xctxt, XPATHErrorResources.WG_SECURITY_EXCEPTION,
|
||||
new Object[]{ fullName }); //"SecurityException when trying to access XSL system property: "+fullName);
|
||||
|
||||
return XString.EMPTYSTRING;
|
||||
}
|
||||
}
|
||||
|
||||
if (propName.equals("version") && result.length() > 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Needs to return the version number of the spec we conform to.
|
||||
return new XString("1.0");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new XString(result);
|
||||
}
|
||||
}
|
||||
else
|
||||
return new XString(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a property bundle from a XSLT_PROPERTIES
|
||||
*
|
||||
* @param target The target property bag the file will be placed into.
|
||||
*/
|
||||
private void loadPropertyFile(Properties target)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Use SecuritySupport class to provide privileged access to property file
|
||||
InputStream is = SecuritySupport.getResourceAsStream(XSLT_PROPERTIES);
|
||||
|
||||
// get a buffered version
|
||||
try (BufferedInputStream bis = new BufferedInputStream(is)) {
|
||||
target.load(bis); // and load up the property bag from this
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// ex.printStackTrace();
|
||||
throw new com.sun.org.apache.xml.internal.utils.WrappedRuntimeException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user