sboag 00/10/04 00:50:07
Modified: java/src/org/apache/xalan/extensions
ExtensionFunctionHandler.java ExtensionsTable.java
MethodResolver.java
java/src/org/apache/xalan/templates ElemExtensionDecl.java
java/src/org/apache/xpath/axes LocPathIterator.java
java/src/org/apache/xpath/objects XRTreeFrag.java
Log:
The extension mechanism should be working relativly OK now. Also provide
NodeSet conversion for iterators and RTFs.
Revision Changes Path
1.9 +116 -57
xml-xalan/java/src/org/apache/xalan/extensions/ExtensionFunctionHandler.java
Index: ExtensionFunctionHandler.java
===================================================================
RCS file:
/home/cvs/xml-xalan/java/src/org/apache/xalan/extensions/ExtensionFunctionHandler.java,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- ExtensionFunctionHandler.java 2000/09/28 15:56:25 1.8
+++ ExtensionFunctionHandler.java 2000/10/04 07:49:51 1.9
@@ -161,13 +161,53 @@
functions.put (tok, junk); // just stick it in there basically
}
}
+
+ /**
+ * Set function local parts of extension NS.
+ *
+ * @param functions whitespace separated list of function names defined
+ * by this extension namespace.
+ */
+ public void setFunctions (org.apache.xalan.utils.StringVector funcNames)
+ {
+ if (funcNames == null)
+ return;
+ Object junk = new Object ();
+ int n = funcNames.size();
+ for(int i = 0; i < n; i++)
+ {
+ String tok = funcNames.elementAt(i);
+ functions.put (tok, junk); // just stick it in there basically
+ }
+ }
+
/**
* Set element local parts of extension NS.
*
* @param elements whitespace separated list of element names defined
* by this extension namespace.
*/
+ public void setElements (org.apache.xalan.utils.StringVector funcNames)
+ {
+ if (funcNames == null)
+ return;
+
+ Object junk = new Object ();
+ int n = funcNames.size();
+ for(int i = 0; i < n; i++)
+ {
+ String tok = funcNames.elementAt(i);
+ elements.put (tok, junk); // just stick it in there basically
+ }
+ }
+
+ /**
+ * Set element local parts of extension NS.
+ *
+ * @param elements whitespace separated list of element names defined
+ * by this extension namespace.
+ */
public void setElements (String elemNames)
{
if (elemNames == null)
@@ -254,14 +294,36 @@
if (dotPos == -1)
{
methodArgs = args;
- object = args[0];
- if (args.length > 1)
+
+ // If we don't have an object yet, and we have a script/class
+ // URL, and the class object hasn't been found yet, then assume
+ // this is a static call, and set the object to the class.
+ if((null == object) && (null != scriptSrcURL) &&
+ (scriptSrcURL.lastIndexOf (":") == -1) && (classObject == null))
{
- methodArgs = new Object[args.length-1];
- System.arraycopy (args, 1, methodArgs, 0, args.length - 1);
+ try
+ {
+ object = Class.forName (scriptSrcURL);
+ }
+ catch (ClassNotFoundException e)
+ {
+ // Try for an object.
+ }
}
- else
- methodArgs = null;
+ // If we don't have an object yet, assume the first
+ // argument is the object for the method.
+ if(null == object)
+ {
+ methodArgs = args;
+ object = args[0];
+ if (args.length > 1)
+ {
+ methodArgs = new Object[args.length-1];
+ System.arraycopy (args, 1, methodArgs, 0, args.length - 1);
+ }
+ else
+ methodArgs = null;
+ }
}
else
{
@@ -319,6 +381,8 @@
}
else
{
+ if(object == null)
+ return null;
Class cl = (object instanceof Class) ? ((Class)object) :
object.getClass();
Method m = MethodResolver.getMethod(cl, method,
methodArgs,
@@ -335,22 +399,14 @@
}
catch (NoSuchMethodException nsme)
{
- throw new SAXException(nsme);
- // throw new BSFException (BSFException.REASON_OTHER_ERROR,
- // "NoSuchMethodException: " + nsme);
+ // Error handling here is in need of dire help.
+ System.out.println("Extension method not found: "+nsme);
+ return null;
}
catch (Exception e)
{
- e.printStackTrace();
+ // e.printStackTrace();
throw new SAXException(e);
- /*
- Throwable t = (e instanceof InvocationTargetException) ?
- ((InvocationTargetException)e).getTargetException () :
- null;
- throw new BSFException (BSFException.REASON_OTHER_ERROR,
- "method call/new failed: " + e +
- ((t==null)?"":(" target exception: "+t)), t);
- */
}
// should not get here
// return null;
@@ -438,14 +494,12 @@
javaObject = this.classObject;
}
- argArray = new Object[args.size () + 1];
+ argArray = new Object[args.size ()];
- argArray[0] = javaObject;
-
for (int i = 0; i < args.size(); i++)
{
Object o = args.elementAt (i);
- argArray[i+1] = o;
+ argArray[i] = o;
}
}
else
@@ -465,7 +519,7 @@
{
argArray = new Object[1];
Object o = args.elementAt (0);
- argArray[0] = (o instanceof XObject) ? ((XObject)o).object ()
: o;
+ argArray[0] = o;
}
}
}
@@ -481,7 +535,6 @@
Object o = args.elementAt (i);
argArray[i] = (o instanceof XObject) ? ((XObject)o).object () : o;
}
-
return e.call (null, funcName, argArray);
}
@@ -555,45 +608,50 @@
}
else // classObj = null
{
- if(null == scriptSrcURL)
- scriptSrcURL = namespaceUri; // Use the namespace URL
-
- if (scriptLang.equals ("javaclass") && (scriptSrcURL != null))
+ if (scriptLang.equals ("javaclass"))
{
- try
+ if(null == scriptSrcURL)
+ scriptSrcURL = namespaceUri; // Use the namespace URL
+
+ if(null != scriptSrcURL)
{
- String cname = scriptSrcURL;
- boolean isClass = false;
- if (scriptSrcURL.startsWith ("class:"))
- {
- cname = scriptSrcURL.substring (6);
- isClass = true;
- }
- else
- {
- // ?? -sb
- cname = scriptSrcURL;
- // isClass = true;
- }
- classObject = Class.forName (cname);
- // System.out.println("classObject: "+classObject);
-
- if (isClass)
+ try
{
- javaObject = classObject;
+ String cname = scriptSrcURL;
+ boolean isClass = false;
+ if (scriptSrcURL.startsWith ("class:"))
+ {
+ cname = scriptSrcURL.substring (6);
+ isClass = true;
+ }
+ else
+ {
+ // ?? -sb
+ cname = scriptSrcURL;
+ // isClass = true;
+ }
+ classObject = Class.forName (cname);
+ // System.out.println("classObject: "+classObject);
+
+ if (isClass)
+ {
+ javaObject = classObject;
+ }
+ else
+ {
+ // We'll only do this if they haven't called a ctor.
+ // javaObject = classObject.newInstance ();
+ }
+ componentStarted = true;
+ return;
}
- else
+ catch (Exception e)
{
- // We'll only do this if they haven't called a ctor.
- // javaObject = classObject.newInstance ();
+ // Should be diagnostics.
+ System.out.println("Extension error: "+e.getMessage ());
+ return;
+ // throw new SAXException (e.getMessage (), e);
}
- componentStarted = true;
- return;
- }
- catch (Exception e)
- {
- // System.out.println("Extension error: "+e.getMessage ());
- throw new SAXException (e.getMessage (), e);
}
}
}
@@ -602,6 +660,7 @@
if ((scriptSrcURL != null) && !(scriptLang.equals ("javaclass")
|| scriptLang.equals
("xslt-javaclass")))
{
+ System.out.println("scriptSrcURL: "+scriptSrcURL);
throw new SAXException ("src attr not supported (yet) for:
"+scriptLang);
}
1.6 +2 -2
xml-xalan/java/src/org/apache/xalan/extensions/ExtensionsTable.java
Index: ExtensionsTable.java
===================================================================
RCS file:
/home/cvs/xml-xalan/java/src/org/apache/xalan/extensions/ExtensionsTable.java,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- ExtensionsTable.java 2000/07/31 22:11:31 1.5
+++ ExtensionsTable.java 2000/10/04 07:49:52 1.6
@@ -245,9 +245,9 @@
{
msg = msg.substring("Stopping after fatal error:".length());
}
- System.out.println("Call to extension function failed: "+msg);
+ // System.out.println("Call to extension function failed: "+msg);
result = new XNull();
- throw new org.xml.sax.SAXException(e);
+ // throw new org.xml.sax.SAXException(e);
}
}
}
1.9 +27 -23
xml-xalan/java/src/org/apache/xalan/extensions/MethodResolver.java
Index: MethodResolver.java
===================================================================
RCS file:
/home/cvs/xml-xalan/java/src/org/apache/xalan/extensions/MethodResolver.java,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- MethodResolver.java 2000/08/09 04:01:15 1.8
+++ MethodResolver.java 2000/10/04 07:49:53 1.9
@@ -4,6 +4,7 @@
import java.lang.reflect.Constructor;
import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
import org.w3c.dom.traversal.NodeIterator;
import org.apache.xpath.objects.XObject;
@@ -243,15 +244,15 @@
* (i.e. some unknown Java object) to allowed Java types.
*/
static ConversionInfo[] m_javaObjConversions = {
- new ConversionInfo(java.lang.Object.class, 0),
- new ConversionInfo(Double.TYPE, 1),
- new ConversionInfo(Float.TYPE, 2),
- new ConversionInfo(Long.TYPE, 3),
- new ConversionInfo(Integer.TYPE, 4),
- new ConversionInfo(Short.TYPE, 5),
- new ConversionInfo(Character.TYPE, 6),
- new ConversionInfo(Byte.TYPE, 7),
- new ConversionInfo(java.lang.String.class, 8)
+ new ConversionInfo(Double.TYPE, 0),
+ new ConversionInfo(Float.TYPE, 1),
+ new ConversionInfo(Long.TYPE, 2),
+ new ConversionInfo(Integer.TYPE, 3),
+ new ConversionInfo(Short.TYPE, 4),
+ new ConversionInfo(Character.TYPE, 5),
+ new ConversionInfo(Byte.TYPE, 6),
+ new ConversionInfo(java.lang.String.class, 7),
+ new ConversionInfo(java.lang.Object.class, 8)
};
/**
@@ -327,18 +328,19 @@
*/
static ConversionInfo[] m_nodesetConversions = {
new ConversionInfo(org.w3c.dom.traversal.NodeIterator.class, 0),
- new ConversionInfo(org.w3c.dom.Node.class, 1),
- new ConversionInfo(java.lang.String.class, 2),
- new ConversionInfo(Boolean.TYPE, 3),
- new ConversionInfo(java.lang.Object.class, 4),
- new ConversionInfo(Character.TYPE, 5),
- new ConversionInfo(Double.TYPE, 6),
- new ConversionInfo(Float.TYPE, 6),
- new ConversionInfo(Long.TYPE, 6),
- new ConversionInfo(Integer.TYPE, 6),
- new ConversionInfo(Short.TYPE, 6),
- new ConversionInfo(Byte.TYPE, 6),
- new ConversionInfo(Boolean.TYPE, 7)
+ new ConversionInfo(org.w3c.dom.NodeList.class, 1),
+ new ConversionInfo(org.w3c.dom.Node.class, 2),
+ new ConversionInfo(java.lang.String.class, 3),
+ new ConversionInfo(Boolean.TYPE, 4),
+ new ConversionInfo(java.lang.Object.class, 5),
+ new ConversionInfo(Character.TYPE, 6),
+ new ConversionInfo(Double.TYPE, 7),
+ new ConversionInfo(Float.TYPE, 7),
+ new ConversionInfo(Long.TYPE, 7),
+ new ConversionInfo(Integer.TYPE, 7),
+ new ConversionInfo(Short.TYPE, 7),
+ new ConversionInfo(Byte.TYPE, 7),
+ new ConversionInfo(Boolean.TYPE, 8)
};
/**
@@ -521,8 +523,10 @@
if((NodeIterator.class.isAssignableFrom(javaClass)) ||
(javaClass == java.lang.Object.class))
{
- // This will fail in Xalan right now, since RTFs aren't
- // convertable to node-sets.
+ return xobj.nodeset();
+ }
+ else if(NodeList.class.isAssignableFrom(javaClass))
+ {
return xobj.nodeset();
}
else if(Node.class.isAssignableFrom(javaClass))
1.3 +6 -0
xml-xalan/java/src/org/apache/xalan/templates/ElemExtensionDecl.java
Index: ElemExtensionDecl.java
===================================================================
RCS file:
/home/cvs/xml-xalan/java/src/org/apache/xalan/templates/ElemExtensionDecl.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- ElemExtensionDecl.java 2000/10/03 19:38:02 1.2
+++ ElemExtensionDecl.java 2000/10/04 07:49:59 1.3
@@ -123,10 +123,14 @@
ElemTextLiteral tl = (ElemTextLiteral)childOfSDecl;
char[] chars = tl.getChars();
scriptSrc = new String(chars);
+ if(scriptSrc.trim().length() == 0)
+ scriptSrc = null;
}
}
}
}
+ if(null == lang)
+ lang = "javaclass";
XPathContext liaison = ((XPathContext)transformer.getXPathContext());
ExtensionsTable etable = liaison.getExtensionsTable();
ExtensionNSHandler nsh = etable.get(declNamespace);
@@ -138,6 +142,8 @@
// declNamespace+", lang = "+lang+", srcURL = "+
// srcURL+", scriptSrc="+scriptSrc);
nsh.setScript (lang, srcURL, scriptSrc);
+ nsh.setElements(this.m_elements);
+ nsh.setFunctions(this.m_functions);
etable.addExtensionElementNamespace(declNamespace, nsh);
}
}
1.3 +41 -1
xml-xalan/java/src/org/apache/xpath/axes/LocPathIterator.java
Index: LocPathIterator.java
===================================================================
RCS file:
/home/cvs/xml-xalan/java/src/org/apache/xpath/axes/LocPathIterator.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- LocPathIterator.java 2000/10/02 15:34:06 1.2
+++ LocPathIterator.java 2000/10/04 07:50:02 1.3
@@ -67,6 +67,7 @@
import org.w3c.dom.Node;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.DOMException;
+import org.w3c.dom.NodeList;
// Xalan imports
import org.apache.xpath.res.XPATHErrorResources;
@@ -100,7 +101,7 @@
* in which case the UnionPathIterator will cache the nodes.</p>
*/
public class LocPathIterator extends Expression
- implements Cloneable, NodeIterator, ContextNodeList
+ implements Cloneable, NodeIterator, ContextNodeList, NodeList
{
/**
* Create a LocPathIterator object.
@@ -221,6 +222,45 @@
return 0;
return m_cachedNodes.size();
}
+
+ /**
+ * Returns the <code>index</code> th item in the collection. If
+ * <code>index</code> is greater than or equal to the number of nodes in
+ * the list, this returns <code>null</code> .
+ * @param index Index into the 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.
+ */
+ public Node item(int index)
+ {
+ resetToCachedList();
+ return m_cachedNodes.item(index);
+ }
+
+ /**
+ * The number of nodes in the list. The range of valid child node indices
+ * is 0 to <code>length-1</code> inclusive.
+ */
+ public int getLength()
+ {
+ resetToCachedList();
+ return m_cachedNodes.getLength();
+ }
+
+ /**
+ * In order to implement NodeList (for extensions), try to reset
+ * to a cached list for random access.
+ */
+ private void resetToCachedList()
+ {
+ int pos = this.getCurrentPos();
+ if((null == m_cachedNodes) || (pos != 0))
+ this.setShouldCacheNodes(true);
+ runTo(-1);
+ this.setCurrentPos(pos);
+ }
+
/**
* Tells if this NodeSet is "fresh", in other words, if
1.3 +149 -0
xml-xalan/java/src/org/apache/xpath/objects/XRTreeFrag.java
Index: XRTreeFrag.java
===================================================================
RCS file:
/home/cvs/xml-xalan/java/src/org/apache/xpath/objects/XRTreeFrag.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- XRTreeFrag.java 2000/09/26 14:57:28 1.2
+++ XRTreeFrag.java 2000/10/04 07:50:06 1.3
@@ -57,6 +57,8 @@
package org.apache.xpath.objects;
import org.w3c.dom.*;
+import org.w3c.dom.traversal.NodeIterator;
+import org.w3c.dom.traversal.NodeFilter;
import org.apache.xpath.DOMHelper;
/**
@@ -163,6 +165,18 @@
}
/**
+ * Cast result object to a nodelist.
+ */
+ public NodeIterator nodeset()
+ {
+ System.out.println("**m_obj: "+((Object)m_obj).getClass().getName());
+ if(m_obj instanceof NodeIterator)
+ return (NodeIterator)m_obj;
+ else
+ return new NodeIteratorWrapper(rtree());
+ }
+
+ /**
* Cast result object to a nodelist. (special function).
*/
public NodeList convertToNodeset()
@@ -207,6 +221,141 @@
else
{
return super.equals(obj2);
+ }
+ }
+
+ class NodeIteratorWrapper implements NodeIterator, NodeList
+ {
+ int m_pos = -1;
+ DocumentFragment m_docFrag;
+ NodeList m_nl;
+
+ NodeIteratorWrapper(DocumentFragment df)
+ {
+ m_docFrag = df;
+ m_nl = df.getChildNodes();
+ }
+
+ /**
+ * Returns the <code>index</code> th item in the collection. If
+ * <code>index</code> is greater than or equal to the number of nodes in
+ * the list, this returns <code>null</code> .
+ * @param index Index into the 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.
+ */
+ public Node item(int index)
+ {
+ return m_nl.item(index);
+ }
+
+ /**
+ * The number of nodes in the list. The range of valid child node
indices
+ * is 0 to <code>length-1</code> inclusive.
+ */
+ public int getLength()
+ {
+ return m_nl.getLength();
+ }
+
+ /**
+ * The root node of the Iterator, as specified when it was created.
+ */
+ public Node getRoot()
+ {
+ return null;
+ }
+
+ /**
+ * This attribute determines which node types are presented via the
+ * iterator. The available set of constants is defined in the
+ * <code>NodeFilter</code> interface.
+ */
+ public int getWhatToShow()
+ {
+ return NodeFilter.SHOW_ALL;
+ }
+
+ /**
+ * The filter used to screen nodes.
+ */
+ public NodeFilter getFilter()
+ {
+ return null;
+ }
+
+ /**
+ * The value of this flag determines whether the children of entity
+ * reference nodes are visible to the iterator. If false, they will be
+ * skipped over.
+ * <br> To produce a view of the document that has entity references
+ * expanded and does not expose the entity reference node itself, use
the
+ * whatToShow flags to hide the entity reference node and set
+ * expandEntityReferences to true when creating the iterator. To produce
+ * a view of the document that has entity reference nodes but no entity
+ * expansion, use the whatToShow flags to show the entity reference node
+ * and set expandEntityReferences to false.
+ */
+ public boolean getExpandEntityReferences()
+ {
+ return true;
+ }
+
+ /**
+ * 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.
+ * @exception DOMException
+ * INVALID_STATE_ERR: Raised if this method is called after the
+ * <code>detach</code> method was invoked.
+ */
+ public Node nextNode()
+ throws DOMException
+ {
+ int next = m_pos+1;
+ if((next >= 0) && (next < m_nl.getLength()))
+ {
+ m_pos++;
+ return m_nl.item(next);
+ }
+ else
+ return null;
+ }
+
+ /**
+ * Returns the previous node in the set and moves the position of the
+ * iterator backwards in the set.
+ * @return The previous <code>Node</code> in the set being iterated
over,
+ * or<code>null</code> if there are no more members in that set.
+ * @exception DOMException
+ * INVALID_STATE_ERR: Raised if this method is called after the
+ * <code>detach</code> method was invoked.
+ */
+ public Node previousNode()
+ throws DOMException
+ {
+ int prev = m_pos-1;
+ if((prev >= 0) && (prev < m_nl.getLength()))
+ {
+ m_pos--;
+ return m_nl.item(prev);
+ }
+ else
+ return null;
+ }
+
+ /**
+ * 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()
+ {
}
}