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

Reply via email to