feat(jdk8): move files to new folder to avoid resources compiled.

This commit is contained in:
2025-09-07 15:25:52 +08:00
parent 3f0047bf6f
commit 8c35cfb1c0
17415 changed files with 217 additions and 213 deletions

View 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;
}
}

View File

@@ -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);
}
}

View 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();
}
}

View File

@@ -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();
}

View File

@@ -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);
}

View File

@@ -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;
}

View File

@@ -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(){}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -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;
}

View File

@@ -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);
}
}
}

View 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

View File

@@ -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();
}

View 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;
}

View 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);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -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;
}
}

View File

@@ -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);
}

View File

@@ -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);
}
}

View File

@@ -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);
}

View 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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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();
}
}
}

View File

@@ -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);
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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

View File

@@ -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();
}
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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();
}

View File

@@ -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;
}
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}

View File

@@ -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;
}
}

View File

@@ -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);
}

View File

@@ -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;
}
}

View File

@@ -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

View File

@@ -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;
}
}

View File

@@ -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));
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -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());
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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 = "*";
}

View File

@@ -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
}
}

View File

@@ -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

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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()));
}
}

View File

@@ -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));
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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
}
}

View File

@@ -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 : "");
}
}

View File

@@ -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;
}
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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
}
}

View File

@@ -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()));
}
}

View File

@@ -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;
}
}

View File

@@ -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) { }
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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
}
}

View File

@@ -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);
}
}

View File

@@ -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));
}
}

View File

@@ -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);
}
}
}

View File

@@ -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;
}
}

View File

@@ -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));
}
}

View File

@@ -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
}
}

View File

@@ -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;
}
}

View File

@@ -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));
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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());
}
}

View File

@@ -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");
}
}

View File

@@ -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());
}
}

View File

@@ -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));
}
}

View File

@@ -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);
}
}

View File

@@ -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