You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xalan.apache.org by jk...@apache.org on 2002/03/04 19:21:32 UTC

cvs commit: xml-xalan/java/src/org/apache/xpath VariableStack.java XPathContext.java

jkesselm    02/03/04 10:21:32

  Modified:    java/src/org/apache/xalan/processor StylesheetHandler.java
               java/src/org/apache/xalan/templates ElemVariable.java
               java/src/org/apache/xalan/transformer TransformerImpl.java
               java/src/org/apache/xml/dtm/ref DTMManagerDefault.java
               java/src/org/apache/xpath VariableStack.java
                        XPathContext.java
  Log:
  Variable64-66 and a number of variable-related Bugzilla reports: Global
  variables may have their resolution deferred. This was causing their
  content to be placed on the normal variable stack, where it could be
  popped off (arggh) and later overwritten (double arggh). This change
  gives them an independent storage space which is not subject to
  those risks.
  
  While I was at it, I've also made the VariableStack class a trifle more
  self-documenting by giving some of the fields more meaningful names.
  
  Revision  Changes    Path
  1.48      +1 -0      xml-xalan/java/src/org/apache/xalan/processor/StylesheetHandler.java
  
  Index: StylesheetHandler.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/processor/StylesheetHandler.java,v
  retrieving revision 1.47
  retrieving revision 1.48
  diff -u -r1.47 -r1.48
  --- StylesheetHandler.java	10 Oct 2001 18:42:07 -0000	1.47
  +++ StylesheetHandler.java	4 Mar 2002 18:21:31 -0000	1.48
  @@ -725,6 +725,7 @@
       {
   
         // If it's whitespace, just ignore it, otherwise flag an error.
  +      // %ISSUE% What about whitesace within scope of xsl:space="preserve"?
         if (!XMLCharacterRecognizer.isWhiteSpace(ch, start, length))
           error(
             "Non-whitespace text is not allowed in this position in the stylesheet!",
  
  
  
  1.14      +10 -2     xml-xalan/java/src/org/apache/xalan/templates/ElemVariable.java
  
  Index: ElemVariable.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/templates/ElemVariable.java,v
  retrieving revision 1.13
  retrieving revision 1.14
  diff -u -r1.13 -r1.14
  --- ElemVariable.java	11 Jul 2001 09:54:21 -0000	1.13
  +++ ElemVariable.java	4 Mar 2002 18:21:31 -0000	1.14
  @@ -323,8 +323,16 @@
         else
         {
   
  -        // Use result tree fragment
  -        int df = transformer.transformToRTF(this);
  +        // Use result tree fragment.
  +        // Global variables may be deferred (see XUnresolvedVariable) and hence
  +        // need to be assigned to a different set of DTMs than local variables
  +        // so they aren't popped off the stack on return from a template.
  +        int df;
  +
  +	    if(m_parentNode instanceof Stylesheet) // Global variable
  +	        df = transformer.transformToGlobalRTF(this);
  +	    else        
  +	        df = transformer.transformToRTF(this);
   
           var = new XRTreeFrag(df, xctxt);
         }
  
  
  
  1.125     +45 -7     xml-xalan/java/src/org/apache/xalan/transformer/TransformerImpl.java
  
  Index: TransformerImpl.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/transformer/TransformerImpl.java,v
  retrieving revision 1.124
  retrieving revision 1.125
  diff -u -r1.124 -r1.125
  --- TransformerImpl.java	8 Feb 2002 23:33:49 -0000	1.124
  +++ TransformerImpl.java	4 Mar 2002 18:21:31 -0000	1.125
  @@ -1724,23 +1724,61 @@
     /**
      * <meta name="usage" content="advanced"/>
      * Given a stylesheet element, create a result tree fragment from it's
  -   * contents.
  +   * contents. The fragment will be built within the shared RTF DTM system
  +   * used as a variable stack.
      * @param templateParent The template element that holds the fragment.
  -   * @param sourceNode The current source context node.
  -   * @param mode The mode under which the template is operating.
  -   * @return An object that represents the result tree fragment.
  +   * @return the NodeHandle for the root node of the resulting RTF.
      *
      * @throws TransformerException
      */
     public int transformToRTF(ElemTemplateElement templateParent)
             throws TransformerException
     {
  +    // Retrieve a DTM to contain the RTF. At this writing, this may be a
  +    // multi-document DTM (SAX2RTFDTM).
  +    DTM dtmFrag = m_xcontext.getRTFDTM();
  +    return transformToRTF(templateParent,dtmFrag);
  +  }
  +  
  +  /**
  +   * <meta name="usage" content="advanced"/>
  +   * Given a stylesheet element, create a result tree fragment from it's
  +   * contents. The fragment will also use the shared DTM system, but will
  +   * obtain its space from the global variable pool rather than the dynamic
  +   * variable stack. This allows late binding of XUnresolvedVariables without
  +   * the risk that their content will be discarded when the variable stack
  +   * is popped.
  +   * 
  +   * @param templateParent The template element that holds the fragment.
  +   * @return the NodeHandle for the root node of the resulting RTF.
  +   *
  +   * @throws TransformerException
  +   */
  +  public int transformToGlobalRTF(ElemTemplateElement templateParent)
  +          throws TransformerException
  +  {
  +    // Retrieve a DTM to contain the RTF. At this writing, this may be a
  +    // multi-document DTM (SAX2RTFDTM).
  +    DTM dtmFrag = m_xcontext.getGlobalRTFDTM();
  +    return transformToRTF(templateParent,dtmFrag);
  +  }
  +  
  +  /**
  +   * <meta name="usage" content="advanced"/>
  +   * Given a stylesheet element, create a result tree fragment from it's
  +   * contents.
  +   * @param templateParent The template element that holds the fragment.
  +   * @param dtmFrag The DTM to write the RTF into
  +   * @return the NodeHandle for the root node of the resulting RTF.
  +   *
  +   * @throws TransformerException
  +   */
  +  private int transformToRTF(ElemTemplateElement templateParent,DTM dtmFrag)
  +          throws TransformerException
  +  {
   
       XPathContext xctxt = m_xcontext;
       
  -    // Retrieve a DTM to contain the RTF. At this writing, this may be a
  -    // multi-document DTM (SAX2RTFDTM).
  -    DTM dtmFrag = xctxt.getRTFDTM();
       ContentHandler rtfHandler = dtmFrag.getContentHandler();
   
       // Obtain the ResultTreeFrag's root node.
  
  
  
  1.37      +6 -3      xml-xalan/java/src/org/apache/xml/dtm/ref/DTMManagerDefault.java
  
  Index: DTMManagerDefault.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xml/dtm/ref/DTMManagerDefault.java,v
  retrieving revision 1.36
  retrieving revision 1.37
  diff -u -r1.36 -r1.37
  --- DTMManagerDefault.java	22 Feb 2002 15:32:22 -0000	1.36
  +++ DTMManagerDefault.java	4 Mar 2002 18:21:31 -0000	1.37
  @@ -351,11 +351,14 @@
   		{
   		  dtm = new SAX2DTM(this, source, documentID, whiteSpaceFilter,
   				    xstringFactory, doIndexing);
  -		}
  +
  +       	}
   
           // Go ahead and add the DTM to the lookup table.  This needs to be
  -        // done before any parsing occurs.
  -        addDTM(dtm, dtmPos, 0);
  +        // done before any parsing occurs. Note offset 0, since we've just
  +        // created a new DTM.
  + 	    addDTM(dtm, dtmPos, 0);
  +
   
           boolean haveXercesParser =
             (null != reader)
  
  
  
  1.39      +36 -36    xml-xalan/java/src/org/apache/xpath/VariableStack.java
  
  Index: VariableStack.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/VariableStack.java,v
  retrieving revision 1.38
  retrieving revision 1.39
  diff -u -r1.38 -r1.39
  --- VariableStack.java	1 Feb 2002 21:10:25 -0000	1.38
  +++ VariableStack.java	4 Mar 2002 18:21:32 -0000	1.39
  @@ -97,7 +97,7 @@
       VariableStack vs = (VariableStack) super.clone();
   
       // I *think* I can get away with a shallow clone here?
  -    vs._sf = (XObject[]) _sf.clone();
  +    vs._stackFrames = (XObject[]) _stackFrames.clone();
       vs._links = (int[]) _links.clone();
   
       return vs;
  @@ -107,19 +107,19 @@
      * The stack frame where all variables and params will be kept.
      * @serial
      */
  -  XObject[] _sf = new XObject[XPathContext.RECURSIONLIMIT * 2];
  +  XObject[] _stackFrames = new XObject[XPathContext.RECURSIONLIMIT * 2];
   
     /**
  -   * The top of the stack frame (<code>_sf</code>).
  +   * The top of the stack frame (<code>_stackFrames</code>).
      * @serial
      */
  -  int _top;
  +  int _frameTop;
   
     /**
  -   * The bottom index of the current frame (relative to <code>_sf</code>).
  +   * The bottom index of the current frame (relative to <code>_stackFrames</code>).
      * @serial
      */
  -  private int _cfb;
  +  private int _currentFrameBottom;
   
     /**
      * The stack of frame positions.  I call 'em links because of distant
  @@ -143,7 +143,7 @@
      */
     public XObject elementAt(final int i)
     {
  -    return _sf[i];
  +    return _stackFrames[i];
     }
   
     /**
  @@ -153,7 +153,7 @@
      */
     public int size()
     {
  -    return _top;
  +    return _frameTop;
     }
   
     /**
  @@ -164,14 +164,14 @@
     public void reset()
     {
   
  -    _top = 0;
  +    _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;
  -    _sf = new XObject[_sf.length]; 
  +    _stackFrames = new XObject[_stackFrames.length]; 
     }
   
     /**
  @@ -181,7 +181,7 @@
      */
     public void setStackFrame(int sf)
     {
  -    _cfb = sf;
  +    _currentFrameBottom = sf;
     }
   
     /**
  @@ -193,7 +193,7 @@
      */
     public int getStackFrame()
     {
  -    return _cfb;
  +    return _currentFrameBottom;
     }
   
     /**
  @@ -214,16 +214,16 @@
     public int link(final int size)
     {
   
  -    _cfb = _top;
  -    _top += size;
  +    _currentFrameBottom = _frameTop;
  +    _frameTop += size;
   
  -    if (_top >= _sf.length)
  +    if (_frameTop >= _stackFrames.length)
       {
  -      XObject newsf[] = new XObject[_sf.length + (1024 * 4) + size];
  +      XObject newsf[] = new XObject[_stackFrames.length + (1024 * 4) + size];
   
  -      System.arraycopy(_sf, 0, newsf, 0, _sf.length);
  +      System.arraycopy(_stackFrames, 0, newsf, 0, _stackFrames.length);
   
  -      _sf = newsf;
  +      _stackFrames = newsf;
       }
   
       if (_linksTop + 1 >= _links.length)
  @@ -235,9 +235,9 @@
         _links = newlinks;
       }
   
  -    _links[_linksTop++] = _cfb;
  +    _links[_linksTop++] = _currentFrameBottom;
   
  -    return _cfb;
  +    return _currentFrameBottom;
     }
   
     /**
  @@ -246,8 +246,8 @@
      */
     public  void unlink()
     {
  -    _top = _links[--_linksTop];
  -    _cfb = _links[_linksTop - 1];
  +    _frameTop = _links[--_linksTop];
  +    _currentFrameBottom = _links[_linksTop - 1];
     }
     
     /**
  @@ -258,8 +258,8 @@
      */
     public  void unlink(int currentFrame)
     {
  -    _top = _links[--_linksTop];
  -    _cfb = currentFrame; 
  +    _frameTop = _links[--_linksTop];
  +    _currentFrameBottom = currentFrame; 
     }
   
     /**
  @@ -273,7 +273,7 @@
      */
     public void setLocalVariable(int index, XObject val)
     {
  -    _sf[index + _cfb] = val;
  +    _stackFrames[index + _currentFrameBottom] = val;
     }
   
     /**
  @@ -288,7 +288,7 @@
      */
     public void setLocalVariable(int index, XObject val, int stackFrame)
     {
  -    _sf[index + stackFrame] = val;
  +    _stackFrames[index + stackFrame] = val;
     }
   
     /**
  @@ -309,16 +309,16 @@
             throws TransformerException
     {
   
  -    index += _cfb;
  +    index += _currentFrameBottom;
   
  -    XObject val = _sf[index];
  +    XObject val = _stackFrames[index];
       
       if(null == val)
         throw new TransformerException("Variable accessed before it is bound!", xctxt.getSAXLocator());
   
       // Lazy execution of variables.
       if (val.getType() == XObject.CLASS_UNRESOLVEDVARIABLE)
  -      return (_sf[index] = val.execute(xctxt));
  +      return (_stackFrames[index] = val.execute(xctxt));
   
       return val;
     }
  @@ -341,7 +341,7 @@
   
       index += frame;
   
  -    XObject val = _sf[index];
  +    XObject val = _stackFrames[index];
   
       return val;
     }
  @@ -358,7 +358,7 @@
      */
     public boolean isLocalSet(int index) throws TransformerException
     {
  -    return (_sf[index + _cfb] != null);
  +    return (_stackFrames[index + _currentFrameBottom] != null);
     }
   
     /** NEEDSDOC Field m_nulls          */
  @@ -376,9 +376,9 @@
     public void clearLocalSlots(int start, int len)
     {
   
  -    start += _cfb;
  +    start += _currentFrameBottom;
   
  -    System.arraycopy(m_nulls, 0, _sf, start, len);
  +    System.arraycopy(m_nulls, 0, _stackFrames, start, len);
     }
   
     /**
  @@ -392,7 +392,7 @@
      */
     public void setGlobalVariable(final int index, final XObject val)
     {
  -    _sf[index] = val;
  +    _stackFrames[index] = val;
     }
   
     /**
  @@ -413,11 +413,11 @@
             throws TransformerException
     {
   
  -    XObject val = _sf[index];
  +    XObject val = _stackFrames[index];
   
       // Lazy execution of variables.
       if (val.getType() == XObject.CLASS_UNRESOLVEDVARIABLE)
  -      return (_sf[index] = val.execute(xctxt));
  +      return (_stackFrames[index] = val.execute(xctxt));
   
       return val;
     }
  
  
  
  1.35      +48 -1     xml-xalan/java/src/org/apache/xpath/XPathContext.java
  
  Index: XPathContext.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/XPathContext.java,v
  retrieving revision 1.34
  retrieving revision 1.35
  diff -u -r1.34 -r1.35
  --- XPathContext.java	22 Feb 2002 16:26:20 -0000	1.34
  +++ XPathContext.java	4 Mar 2002 18:21:32 -0000	1.35
  @@ -138,6 +138,12 @@
     /** Index of currently active RTF DTM in m_rtfdtm_stack */
     private int m_which_rtfdtm=-1;
     
  + /**
  +   * Most recent "reusable" DTM for Global Result Tree Fragments. No stack is
  +   * required since we're never going to pop these.
  +   */
  +  private SAX2RTFDTM m_global_rtfdtm=null;
  +  
   	
     /**
      * Though XPathContext context extends 
  @@ -1185,8 +1191,49 @@
   
     }
   
  + /**
  +   * Get a DTM to be used as a container for a global Result Tree
  +   * Fragment. This will always be an instance of (derived from? equivalent to?) 
  +   * SAX2DTM, since each RTF is constructed by temporarily redirecting our SAX 
  +   * output to it. It may be a single DTM containing for multiple fragments, 
  +   * if the implementation supports that.
  +   * 
  +   * Note: The distinction between this method and getRTFDTM() is that the latter
  +   * allocates space from the dynamic variable stack (m_rtfdtm_stack), which may
  +   * be pruned away again as the templates which defined those variables are exited.
  +   * Global variables may be bound late (see XUnresolvedVariable), and never want to
  +   * be discarded, hence we need to allocate them separately and don't actually need
  +   * a stack to track them.
  +   * 
  +   * @return a non-null DTM reference.
  +   */
  +  public DTM getGlobalRTFDTM()
  +  {
  +  	// We probably should _NOT_ be applying whitespace filtering at this stage!
  +  	//
  +  	// Some magic has been applied in DTMManagerDefault to recognize this set of options
  +  	// and generate an instance of DTM which can contain multiple documents
  +  	// (SAX2RTFDTM). Perhaps not the optimal way of achieving that result, but
  +  	// I didn't want to change the manager API at this time, or expose 
  +  	// too many dependencies on its internals. (Ideally, I'd like to move
  +  	// isTreeIncomplete all the way up to DTM, so we wouldn't need to explicitly
  +  	// specify the subclass here.)
  +
  +	// If it doesn't exist, or if the one already existing is in the middle of
  +	// being constructed, we need to obtain a new DTM to write into. I'm not sure
  +	// the latter will ever arise, but I'd rather be just a bit paranoid..
  +	if( m_global_rtfdtm==null || m_global_rtfdtm.isTreeIncomplete() )
  +	{
  +  		m_global_rtfdtm=(SAX2RTFDTM)m_dtmManager.getDTM(null,true,null,false,false);
  +	}
  +    return m_global_rtfdtm;
  +  }
  +  
  +
  +
  +
     /**
  -   * Get a DTM to be used as a container for a Result Tree
  +   * Get a DTM to be used as a container for a dynamic Result Tree
      * Fragment. This will always be an instance of (derived from? equivalent to?) 
      * SAX2DTM, since each RTF is constructed by temporarily redirecting our SAX 
      * output to it. It may be a single DTM containing for multiple fragments, 
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: xalan-cvs-unsubscribe@xml.apache.org
For additional commands, e-mail: xalan-cvs-help@xml.apache.org