KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > xalan > transformer > StackGuard


1 /*
2  * Copyright 1999-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 /*
17  * $Id: StackGuard.java,v 1.12 2004/02/16 20:41:29 minchau Exp $
18  */

19 package org.apache.xalan.transformer;
20
21 import javax.xml.transform.TransformerException JavaDoc;
22
23 import org.apache.xalan.res.XSLMessages;
24 import org.apache.xalan.templates.Constants;
25 import org.apache.xalan.templates.ElemTemplate;
26 import org.apache.xalan.templates.ElemTemplateElement;
27 import org.apache.xml.utils.ObjectStack;
28
29 /**
30  * Class to guard against recursion getting too deep.
31  */

32 public class StackGuard
33 {
34
35   /**
36    * Used for infinite loop check. If the value is -1, do not
37    * check for infinite loops. Anyone who wants to enable that
38    * check should change the value of this variable to be the
39    * level of recursion that they want to check. Be careful setting
40    * this variable, if the number is too low, it may report an
41    * infinite loop situation, when there is none.
42    * Post version 1.0.0, we'll make this a runtime feature.
43    */

44   public static int m_recursionLimit = -1;
45   
46   TransformerImpl m_transformer;
47
48   /**
49    * Get the recursion limit.
50    * Used for infinite loop check. If the value is -1, do not
51    * check for infinite loops. Anyone who wants to enable that
52    * check should change the value of this variable to be the
53    * level of recursion that they want to check. Be careful setting
54    * this variable, if the number is too low, it may report an
55    * infinite loop situation, when there is none.
56    * Post version 1.0.0, we'll make this a runtime feature.
57    *
58    * @return The recursion limit.
59    */

60   public int getRecursionLimit()
61   {
62     return m_recursionLimit;
63   }
64
65   /**
66    * Set the recursion limit.
67    * Used for infinite loop check. If the value is -1, do not
68    * check for infinite loops. Anyone who wants to enable that
69    * check should change the value of this variable to be the
70    * level of recursion that they want to check. Be careful setting
71    * this variable, if the number is too low, it may report an
72    * infinite loop situation, when there is none.
73    * Post version 1.0.0, we'll make this a runtime feature.
74    *
75    * @param limit The recursion limit.
76    */

77   public void setRecursionLimit(int limit)
78   {
79     m_recursionLimit = limit;
80   }
81
82   /**
83    * Constructor StackGuard
84    *
85    *
86    * @param xslTemplate Current template node
87    * @param sourceXML Source Node
88    */

89   public StackGuard(TransformerImpl transformerImpl)
90   {
91     m_transformer = transformerImpl;
92   }
93
94   /**
95    * Overide equal method for StackGuard objects
96    *
97    *
98    * @param obj StackGuard object to compare
99    *
100    * @return True if the given object matches this StackGuard object
101    */

102   public int countLikeTemplates(ElemTemplate templ, int pos)
103   {
104     ObjectStack elems = m_transformer.getCurrentTemplateElements();
105     int count = 1;
106     for (int i = pos-1; i >= 0; i--)
107     {
108         if((ElemTemplateElement)elems.elementAt(i) == templ)
109             count++;
110     }
111     
112     return count;
113   }
114
115   
116   /**
117    * Get the next named or match template down from and including
118    * the given position.
119    * @param pos the current index position in the stack.
120    * @return null if no matched or named template found, otherwise
121    * the next named or matched template at or below the position.
122    */

123   private ElemTemplate getNextMatchOrNamedTemplate(int pos)
124   {
125     ObjectStack elems = m_transformer.getCurrentTemplateElements();
126     for (int i = pos; i >= 0; i--)
127     {
128         ElemTemplateElement elem = (ElemTemplateElement) elems.elementAt(i);
129         if(null != elem)
130         {
131             if(elem.getXSLToken() == Constants.ELEMNAME_TEMPLATE)
132             {
133                 return (ElemTemplate)elem;
134             }
135         }
136     }
137     return null;
138   }
139
140   /**
141    * Check if we are in an infinite loop
142    *
143    *
144    * @param guard Current StackGuard object (matching current template)
145    *
146    * @throws TransformerException
147    */

148   public void checkForInfinateLoop() throws TransformerException JavaDoc
149   {
150     int nTemplates = m_transformer.getCurrentTemplateElementsCount();
151     if(nTemplates < m_recursionLimit)
152         return;
153         
154     if(m_recursionLimit <= 0)
155         return; // Safety check.
156

157     // loop from the top index down to the recursion limit (I don't think
158
// there's any need to go below that).
159
for (int i = (nTemplates - 1); i >= m_recursionLimit; i--)
160     {
161         ElemTemplate template = getNextMatchOrNamedTemplate(i);
162         
163         if(null == template)
164             break;
165             
166         int loopCount = countLikeTemplates(template, i);
167         
168         if (loopCount >= m_recursionLimit)
169         {
170             // throw new TransformerException("Template nesting too deep. nesting = "+loopCount+
171
// ", template "+((null == template.getName()) ? "name = " : "match = ")+
172
// ((null != template.getName()) ? template.getName().toString()
173
// : template.getMatch().getPatternString()));
174

175             String JavaDoc idIs = XSLMessages.createMessage(((null != template.getName()) ? "nameIs" : "matchPatternIs"), null);
176             Object JavaDoc[] msgArgs = new Object JavaDoc[]{ new Integer JavaDoc(loopCount), idIs,
177                      ((null != template.getName()) ? template.getName().toString()
178                : template.getMatch().getPatternString()) };
179             String JavaDoc msg = XSLMessages.createMessage("recursionTooDeep", msgArgs);
180
181             throw new TransformerException JavaDoc(msg);
182         }
183     }
184   }
185
186 }
187
Popular Tags