zongaro     2003/04/16 13:58:24

  Modified:    java/src/org/apache/xalan/xsltc/compiler DocumentCall.java
               java/src/org/apache/xalan/xsltc/dom LoadDocument.java
  Log:
  Applying patches from Igor Hersht ([EMAIL PROTECTED]) for bug 15200 and
  bug 18585.
  
  Fixed up code that processes the document function when it has two arguments,
  the second of which must be a node-set; the code didn't always resolve the
  value of the first argument against the first node in the second argument, as 
it
  should have.
  
  In addition, in order to simplify run-time processing, added a new
  LoadDocument.documentF method that is used when the second argument to the 
XSLT
  document function is present; if that argument is an empty node-set, the 
result
  of the document function should be an empty node-set, and that logic is much
  easier to code in the run-time than via generated code.
  
  Revision  Changes    Path
  1.17      +91 -107   
xml-xalan/java/src/org/apache/xalan/xsltc/compiler/DocumentCall.java
  
  Index: DocumentCall.java
  ===================================================================
  RCS file: 
/home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/compiler/DocumentCall.java,v
  retrieving revision 1.16
  retrieving revision 1.17
  diff -u -r1.16 -r1.17
  --- DocumentCall.java 1 Apr 2003 21:08:59 -0000       1.16
  +++ DocumentCall.java 16 Apr 2003 20:58:24 -0000      1.17
  @@ -79,15 +79,15 @@
   
   final class DocumentCall extends FunctionCall {
   
  -    private Expression _uri = null;
  -    private Expression _base = null;
  -    private Type       _uriType;
  +    private Expression _arg1 = null;
  +    private Expression _arg2 = null;
  +    private Type       _arg1Type;
   
       /**
        * Default function call constructor
        */
       public DocumentCall(QName fname, Vector arguments) {
  -     super(fname, arguments);
  +        super(fname, arguments);
       }
   
       /**
  @@ -96,115 +96,99 @@
        * URI of the document
        */
       public Type typeCheck(SymbolTable stable) throws TypeCheckError {
  -     // At least one argument - two at most
  -     final int ac = argumentCount();
  -     if ((ac < 1) || (ac > 2)) {
  -         ErrorMsg msg = new ErrorMsg(ErrorMsg.ILLEGAL_ARG_ERR, this);
  -         throw new TypeCheckError(msg);
  -     }
  -
  -     // Parse the first argument - the document URI
  -     _uri = argument(0);
  -     if (_uri instanceof LiteralExpr) {
  -         LiteralExpr expr = (LiteralExpr)_uri;
  -         if (expr.getValue().equals(EMPTYSTRING)) {
  -             Stylesheet stylesheet = getStylesheet();
  -             if (stylesheet == null) {
  -                 ErrorMsg msg = new ErrorMsg(ErrorMsg.ILLEGAL_ARG_ERR, this);
  -                 throw new TypeCheckError(msg);
  -             }
  -             _uri = new LiteralExpr(stylesheet.getSystemId(), EMPTYSTRING);
  -         }
  -     }
  -
  -     _uriType = _uri.typeCheck(stable);
  -     if ((_uriType != Type.NodeSet) && (_uriType != Type.String)) {
  -         _uri = new CastExpr(_uri, Type.String);
  -     }
  -
  -     // Parse the second argument - the document URI base
  -     if (ac == 2) {
  -         _base = argument(1);
  -         final Type baseType = _base.typeCheck(stable);
  -         
  -         if (baseType.identicalTo(Type.Node)) {
  -             _base = new CastExpr(_base, Type.NodeSet);
  -         }
  -         else if (baseType.identicalTo(Type.NodeSet)) {
  -             // falls through
  -         }
  -         else {
  -             ErrorMsg msg = new ErrorMsg(ErrorMsg.DOCUMENT_ARG_ERR, this);
  -             throw new TypeCheckError(msg);
  -         }
  -     }
  +        // At least one argument - two at most
  +        final int ac = argumentCount();
  +        if ((ac < 1) || (ac > 2)) {
  +            ErrorMsg msg = new ErrorMsg(ErrorMsg.ILLEGAL_ARG_ERR, this);
  +            throw new TypeCheckError(msg);
  +        }
  +        if (getStylesheet() == null) {
  +            ErrorMsg msg = new ErrorMsg(ErrorMsg.ILLEGAL_ARG_ERR, this);
  +            throw new TypeCheckError(msg);
  +        }
  +
  +        // Parse the first argument 
  +        _arg1 = argument(0);
  +
  +        if (_arg1 == null) {// should not happened 
  +            ErrorMsg msg = new ErrorMsg(ErrorMsg.DOCUMENT_ARG_ERR, this);
  +            throw new TypeCheckError(msg);
  +        }
  +
  +        _arg1Type = _arg1.typeCheck(stable);
  +        if ((_arg1Type != Type.NodeSet) && (_arg1Type != Type.String)) {
  +            _arg1 = new CastExpr(_arg1, Type.String);
  +        }
  +
  +        // Parse the second argument 
  +        if (ac == 2) {
  +            _arg2 = argument(1);
  +
  +            if (_arg2 == null) {// should not happened 
  +                ErrorMsg msg = new ErrorMsg(ErrorMsg.DOCUMENT_ARG_ERR, this);
  +                throw new TypeCheckError(msg);
  +            }
  +
  +            final Type arg2Type = _arg2.typeCheck(stable);
  +
  +            if (arg2Type.identicalTo(Type.Node)) {
  +                _arg2 = new CastExpr(_arg2, Type.NodeSet);
  +            } else if (arg2Type.identicalTo(Type.NodeSet)) {
  +                // falls through
  +            } else {
  +                ErrorMsg msg = new ErrorMsg(ErrorMsg.DOCUMENT_ARG_ERR, this);
  +                throw new TypeCheckError(msg);
  +            }
  +        }
   
  -     return _type = Type.NodeSet;
  +        return _type = Type.NodeSet;
       }
  -     
  +    
       /**
        * Translates the document() function call to a call to LoadDocument()'s
        * static method document().
        */
       public void translate(ClassGenerator classGen, MethodGenerator 
methodGen) {
  -     final ConstantPoolGen cpg = classGen.getConstantPool();
  -     final InstructionList il = methodGen.getInstructionList();
  -
  -     final int domField = cpg.addFieldref(classGen.getClassName(),
  -                                          DOM_FIELD,
  -                                          DOM_INTF_SIG);
  -     final String docParamList =
  -         "("+OBJECT_SIG+STRING_SIG+STRING_SIG+TRANSLET_SIG+DOM_INTF_SIG+")"+
  -         NODE_ITERATOR_SIG;
  -     final int docIdx = cpg.addMethodref(LOAD_DOCUMENT_CLASS,
  -                                         "document", docParamList);
  -
  -     final int uriIdx = cpg.addInterfaceMethodref(DOM_INTF,
  -                                                  "getDocumentURI",
  -                                                  "(I)"+STRING_SIG);
  -
  -     final int nextIdx = cpg.addInterfaceMethodref(NODE_ITERATOR,
  -                                                   NEXT, NEXT_SIG);
  -
  -     // The URI can be either a node-set or something else cast to a string
  -     _uri.translate(classGen, methodGen);
  -     if (_uriType == Type.NodeSet)
  -         _uri.startResetIterator(classGen, methodGen);
  -
  -     // The base of the URI may be given as a second argument (a node-set)
  -     //il.append(methodGen.loadDOM());
  -     if (_base != null) {
  -             il.append(methodGen.loadDOM());
  -         _base.translate(classGen, methodGen);
  -         il.append(new INVOKEINTERFACE(nextIdx, 1));
  -         il.append(new INVOKEINTERFACE(uriIdx, 2));
  -     }
  -     else {
  -             //TODO: (MM) Need someone to double check me on this
  -             // but I think this code was wrong because it would
  -             // resolve document() relative to the input xml
  -             // rather than relative to the input xsl when there
  -             // is no second argument!!!
  -             // The context node here would be at runtime in the xml
  -             // I think the reason this worked was because if the
  -             // xml fails, then the xsl is tried in the current code. 
  -          //il.append(methodGen.loadContextNode());
  -          // Instead just pass in the current stylesheet
  -          // I think this get the stylesheet associated with the
  -          // context node, but...
  -          if (_uriType == Type.NodeSet)
  -          il.append(new PUSH(cpg,""));
  -          else
  -          il.append(new PUSH(cpg, getStylesheet().getSystemId()));        
  -     }
  -     //il.append(new INVOKEINTERFACE(uriIdx, 2));
  -     il.append(new PUSH(cpg, getStylesheet().getSystemId()));
  -
  -     // Feck the rest of the parameters on the stack
  -     il.append(classGen.loadTranslet());
  -     il.append(DUP);
  -     il.append(new GETFIELD(domField));
  -     il.append(new INVOKESTATIC(docIdx));
  +        final ConstantPoolGen cpg = classGen.getConstantPool();
  +        final InstructionList il = methodGen.getInstructionList();
  +        final int ac = argumentCount();
  +
  +        final int domField = cpg.addFieldref(classGen.getClassName(),
  +                                             DOM_FIELD,
  +                                             DOM_INTF_SIG);
  +          
  +        String docParamList = null;
  +        if (ac == 1) {
  +           // documentF(Object,String,AbstractTranslet,DOM)
  +           docParamList = "("+OBJECT_SIG+STRING_SIG+TRANSLET_SIG+DOM_INTF_SIG
  +                         +")"+NODE_ITERATOR_SIG;
  +        } else { //ac == 2; ac < 1 or as >2  was tested in typeChec()
  +           // documentF(Object,DTMAxisIterator,String,AbstractTranslet,DOM)
  +           docParamList = "("+OBJECT_SIG+NODE_ITERATOR_SIG+STRING_SIG
  +                         +TRANSLET_SIG+DOM_INTF_SIG+")"+NODE_ITERATOR_SIG;  
  +        }
  +        final int docIdx = cpg.addMethodref(LOAD_DOCUMENT_CLASS, "documentF",
  +                                            docParamList);
  +
  +
  +        // The URI can be either a node-set or something else cast to a 
string
  +        _arg1.translate(classGen, methodGen);
  +        if (_arg1Type == Type.NodeSet) {
  +            _arg1.startResetIterator(classGen, methodGen);
  +        }
  +
  +        if (ac == 2) {
  +            //_arg2 == null was tested in typeChec()
  +            _arg2.translate(classGen, methodGen);
  +            _arg2.startResetIterator(classGen, methodGen);       
  +        }
  +    
  +        // Feck the rest of the parameters on the stack
  +        il.append(new PUSH(cpg, getStylesheet().getSystemId()));
  +        il.append(classGen.loadTranslet());
  +        il.append(DUP);
  +        il.append(new GETFIELD(domField));
  +        il.append(new INVOKESTATIC(docIdx));
       }
   
   }
  
  
  
  1.16      +104 -102  
xml-xalan/java/src/org/apache/xalan/xsltc/dom/LoadDocument.java
  
  Index: LoadDocument.java
  ===================================================================
  RCS file: 
/home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/dom/LoadDocument.java,v
  retrieving revision 1.15
  retrieving revision 1.16
  diff -u -r1.15 -r1.16
  --- LoadDocument.java 7 Apr 2003 19:23:15 -0000       1.15
  +++ LoadDocument.java 16 Apr 2003 20:58:24 -0000      1.16
  @@ -76,6 +76,7 @@
   import org.apache.xml.dtm.DTM;
   import org.apache.xml.dtm.DTMAxisIterator;
   import org.apache.xml.dtm.ref.DTMDefaultBase;
  +import org.apache.xml.dtm.ref.EmptyIterator;
   
   import org.xml.sax.InputSource;
   import org.xml.sax.XMLReader;
  @@ -83,15 +84,80 @@
   public final class LoadDocument {
   
       private static final String NAMESPACE_FEATURE =
  -     "http://xml.org/sax/features/namespaces";;
  +       "http://xml.org/sax/features/namespaces";;
   
       /**
  -     * Returns an iterator containing a set of nodes from an XML document
  -     * loaded by the document() function.
  +     * Interprets the arguments passed from the document() function (see
  +     * org/apache/xalan/xsltc/compiler/DocumentCall.java) and returns an
  +     * iterator containing the requested nodes. Builds a union-iterator if
  +     * several documents are requested.
  +     * 2 arguments arg1 and arg2.  document(Obj, node-set) call 
        */
  -    public static DTMAxisIterator document(String uri, String base,
  -                                     AbstractTranslet translet, DOM dom)
  -     throws Exception 
  +    public static DTMAxisIterator documentF(Object arg1, DTMAxisIterator 
arg2,
  +                            String xslURI, AbstractTranslet translet, DOM 
dom)
  +    throws TransletException {
  +        String baseURI = null;
  +        final int arg2FirstNode = arg2.next();
  +        if (arg2FirstNode == DTMAxisIterator.END) {
  +            //  the second argument node-set is empty
  +            return EmptyIterator.getInstance();
  +        } else {
  +            //System.err.println("arg2FirstNode name: "
  +            //                   + dom.getNodeName(arg2FirstNode )+"["
  +            //                   +Integer.toHexString(arg2FirstNode )+"]");
  +            baseURI = getBaseFromURI(dom.getDocumentURI(arg2FirstNode)); 
  +        }
  +      
  +        try {
  +            if (arg1 instanceof String) {
  +                if (((String)arg1).length() == 0) {
  +                    return document(xslURI, "", translet, dom);
  +                } else {
  +                    return document((String)arg1, baseURI, translet, dom);
  +                }
  +            } else if (arg1 instanceof DTMAxisIterator) {
  +                return document((DTMAxisIterator)arg1, baseURI, translet, 
dom);
  +            } else {
  +                final String err = "document("+arg1.toString()+")";
  +                throw new IllegalArgumentException(err);
  +            }      
  +        } catch (Exception e) {
  +            throw new TransletException(e);
  +        }
  +    }
  +    /**
  +     * Interprets the arguments passed from the document() function (see
  +     * org/apache/xalan/xsltc/compiler/DocumentCall.java) and returns an
  +     * iterator containing the requested nodes. Builds a union-iterator if
  +     * several documents are requested.
  +     * 1 arguments arg.  document(Obj) call
  +     */
  +    public static DTMAxisIterator documentF(Object arg, String xslURI,
  +                    AbstractTranslet translet, DOM dom)
  +    throws TransletException {
  +        try {
  +            if (arg instanceof String) {
  +                if (((String)arg).length() == 0) {
  +                    return document(xslURI, "", translet, dom);
  +                } else {
  +                    return document((String)arg, getBaseFromURI(xslURI),
  +                                    translet, dom);
  +                }
  +            } else if (arg instanceof DTMAxisIterator) {
  +                return document((DTMAxisIterator)arg, null, translet, dom);
  +            } else {
  +                final String err = "document("+arg.toString()+")";
  +                throw new IllegalArgumentException(err);
  +            }      
  +        } catch (Exception e) {
  +            throw new TransletException(e);
  +        }
  +    }
  + 
  + 
  +    private static DTMAxisIterator document(String uri, String base,
  +                    AbstractTranslet translet, DOM dom)
  +    throws Exception 
       {
           final String originalUri = uri;
           MultiDOM multiplexer = (MultiDOM)dom;
  @@ -99,7 +165,7 @@
           // Return an empty iterator if the URI is clearly invalid
           // (to prevent some unncessary MalformedURL exceptions).
           if (uri == null || uri.equals("")) {
  -            return(new SingletonIterator(DTM.NULL,true));
  +            return(EmptyIterator.getInstance());
           }
   
           // Prepend URI base to URI (from context)
  @@ -117,7 +183,7 @@
           if (file.exists()) {
               uri = file.toURL().toExternalForm();
           }
  -     
  +    
           // Check if this DOM has already been added to the multiplexer
           int mask = multiplexer.getDocumentMask(uri);
           if (mask != -1) {
  @@ -160,8 +226,8 @@
                           ((DTMDefaultBase)((DOMAdapter)multiplexer.getMain())
                                                  .getDOMImpl()).m_mgr;
               newdom = (SAXImpl)dtmManager.getDTM(
  -                                 new SAXSource(reader, new InputSource(uri)),
  -                                 false, null, true, false, 
translet.hasIdCall());
  +                                new SAXSource(reader, new InputSource(uri)),
  +                                false, null, true, false, 
translet.hasIdCall());
   
               translet.prepassDocument(newdom);
   
  @@ -173,102 +239,38 @@
           multiplexer.addDOMAdapter(domAdapter);
   
           // Create index for any key elements
  -        translet.buildKeys(domAdapter, null, null, 
((SAXImpl)newdom).getDocument());
  +        translet.buildKeys(domAdapter, null, null,
  +                           ((SAXImpl)newdom).getDocument());
   
           // Return a singleton iterator containing the root node
           return new SingletonIterator(((SAXImpl)newdom).getDocument(), true);
       }
   
  -    /**
  -     * Interprets the arguments passed from the document() function (see
  -     * org/apache/xalan/xsltc/compiler/DocumentCall.java) and returns an
  -     * iterator containing the requested nodes. Builds a union-iterator if
  -     * several documents are requested.
  -     */
  -    public static DTMAxisIterator document(Object arg,String xmlURI,String 
xslURI,
  -                                     AbstractTranslet translet, DOM dom)
  -     throws TransletException {
  -     try {
  -
  -         // Get the base of the current DOM's URI
  -         if (xmlURI != null) {
  -             int sep = xmlURI.lastIndexOf('\\') + 1;
  -             if (sep <= 0) {
  -                 sep = xmlURI.lastIndexOf('/') + 1;
  -             }
  -             xmlURI = xmlURI.substring(0, sep); // could be empty string
  -         }
  -         else {
  -             xmlURI = "";
  -         }
  -
  -         // Get the base of the current stylesheet's URI
  -         if (xslURI != null) {
  -             int sep = xslURI.lastIndexOf('\\') + 1;
  -             if (sep <= 0) {
  -                 sep = xslURI.lastIndexOf('/') + 1;
  -             }
  -             xslURI = xslURI.substring(0, sep); // could be empty string
  -         }
  -         else {
  -             xslURI = "";
  -         }
  -
  -         // If the argument is just a single string (an URI) we just return
  -         // the nodes from the one document this URI points to.
  -         if (arg instanceof String) {
  -             // First try to load doc relative to current DOM
  -             try {
  -                 return document((String)arg, xmlURI, translet, dom);
  -             }
  -             // Then try to load doc relative to original stylesheet
  -             catch (java.io.FileNotFoundException e) {
  -                 return document((String)arg, xslURI, translet, dom);
  -             }
  -             catch (org.xml.sax.SAXParseException e) {
  -                 return document((String)arg, xslURI, translet, dom);
  -             }
  -         }
  -         // Otherwise we must create a union iterator, add the nodes from
  -         // all the DOMs to this iterator, and return the union in the end.
  -         else if (arg instanceof DTMAxisIterator) {
  -             UnionIterator union = new UnionIterator(dom);
  -             DTMAxisIterator iterator = (DTMAxisIterator)arg;
  -             int node;
  -
  -             while ((node = iterator.next()) != DTM.NULL) {
  -                 String uri = dom.getStringValueX(node);
  -                 // Get the URI from this node if no xml URI base is set
  -                 if ((xmlURI == null) || xmlURI.equals("")) {
  -                     xmlURI = dom.getDocumentURI(node);
  -                     int sep = xmlURI.lastIndexOf('\\') + 1;
  -                     if (sep <= 0) {
  -                         sep = xmlURI.lastIndexOf('/') + 1;
  -                     }
  -                     xmlURI = xmlURI.substring(0, sep);
  -                 }
  -                 // First try to load doc relative to current DOM
  -                 try {
  -                     union.addIterator(document(uri, xmlURI, translet, dom));
  -                 }
  -                 // Then try to load doc relative to original stylesheet
  -                 catch (java.io.FileNotFoundException e) {
  -                     union.addIterator(document(uri, xslURI, translet, dom));
  -                 }
  -             }
  -             return(union);
  -         }
  -         else {
  -             final String err = "document("+arg.toString()+")";
  -             throw new IllegalArgumentException(err);
  -         }
  -     }
  -     catch (TransletException e) {
  -         throw e;
  -     }
  -     catch (Exception e) {
  -         throw new TransletException(e);
  -     }
  +
  +    private static DTMAxisIterator document(DTMAxisIterator arg1,
  +                                            String baseURI,
  +                                            AbstractTranslet translet, DOM 
dom)
  +    throws Exception
  +    {
  +        UnionIterator union = new UnionIterator(dom);
  +        int node = DTM.NULL;
  +
  +        while ((node = arg1.next()) != DTM.NULL) {
  +            String uri = dom.getStringValueX(node);
  +            //document(node-set) if true;  document(node-set,node-set) if 
false
  +            if (baseURI  == null) {
  +                baseURI = getBaseFromURI(dom.getDocumentURI(node));
  +            }
  +            union.addIterator(document(uri, baseURI, translet, dom));
  +        }
  +        return(union);
  +    }
  + 
  +    private static String getBaseFromURI( String uri){
  +        final int backwardSep = uri.lastIndexOf('\\') + 1;
  +        final int forwardSep = uri.lastIndexOf('/') + 1;
  +
  +        return uri.substring(0, Math.max(backwardSep, forwardSep));
       }
   
   }
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to