• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the  "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 /*
19  * $Id$
20  */
21 package org.apache.xalan.trace;
22 
23 import java.lang.reflect.Constructor;
24 import java.lang.reflect.Method;
25 
26 import javax.xml.transform.SourceLocator;
27 
28 import org.apache.xalan.templates.Constants;
29 import org.apache.xalan.templates.ElemTemplate;
30 import org.apache.xalan.templates.ElemTemplateElement;
31 import org.apache.xalan.templates.ElemTextLiteral;
32 import org.apache.xml.dtm.DTM;
33 import org.apache.xml.dtm.ref.DTMNodeProxy;
34 import org.apache.xml.serializer.SerializerTrace;
35 
36 import org.w3c.dom.Node;
37 
38 /**
39  * Implementation of the TraceListener interface that
40  * prints each event to standard out as it occurs.
41  *
42  * @see org.apache.xalan.trace.TracerEvent
43  * @xsl.usage advanced
44  */
45 public class PrintTraceListener implements TraceListenerEx3
46 {
47 
48   /**
49    * Construct a trace listener.
50    *
51    * @param pw PrintWriter to use for tracing events
52    */
PrintTraceListener(java.io.PrintWriter pw)53   public PrintTraceListener(java.io.PrintWriter pw)
54   {
55     m_pw = pw;
56   }
57 
58   /**
59    * The print writer where the events should be written.
60    */
61   java.io.PrintWriter m_pw;
62 
63   /**
64    * This needs to be set to true if the listener is to print an event whenever a template is invoked.
65    */
66   public boolean m_traceTemplates = false;
67 
68   /**
69    * Set to true if the listener is to print events that occur as each node is 'executed' in the stylesheet.
70    */
71   public boolean m_traceElements = false;
72 
73   /**
74    * Set to true if the listener is to print information after each result-tree generation event.
75    */
76   public boolean m_traceGeneration = false;
77 
78   /**
79    * Set to true if the listener is to print information after each selection event.
80    */
81   public boolean m_traceSelection = false;
82 
83   /**
84    * Set to true if the listener is to print information after each extension event.
85    */
86   public boolean m_traceExtension = false;
87 
88   /**
89    * Print information about a TracerEvent.
90    *
91    * @param ev the trace event.
92    */
_trace(TracerEvent ev)93   public void _trace(TracerEvent ev)
94   {
95 
96     switch (ev.m_styleNode.getXSLToken())
97     {
98     case Constants.ELEMNAME_TEXTLITERALRESULT :
99       if (m_traceElements)
100       {
101         m_pw.print(ev.m_styleNode.getSystemId()+ " Line #" + ev.m_styleNode.getLineNumber() + ", "
102                    + "Column #" + ev.m_styleNode.getColumnNumber() + " -- "
103                    + ev.m_styleNode.getNodeName() + ": ");
104 
105         ElemTextLiteral etl = (ElemTextLiteral) ev.m_styleNode;
106         String chars = new String(etl.getChars(), 0, etl.getChars().length);
107 
108         m_pw.println("    " + chars.trim());
109       }
110       break;
111     case Constants.ELEMNAME_TEMPLATE :
112       if (m_traceTemplates || m_traceElements)
113       {
114         ElemTemplate et = (ElemTemplate) ev.m_styleNode;
115 
116         m_pw.print(et.getSystemId()+ " Line #" + et.getLineNumber() + ", " + "Column #"
117                    + et.getColumnNumber() + ": " + et.getNodeName() + " ");
118 
119         if (null != et.getMatch())
120         {
121           m_pw.print("match='" + et.getMatch().getPatternString() + "' ");
122         }
123 
124         if (null != et.getName())
125         {
126           m_pw.print("name='" + et.getName() + "' ");
127         }
128 
129         m_pw.println();
130       }
131       break;
132     default :
133       if (m_traceElements)
134       {
135         m_pw.println(ev.m_styleNode.getSystemId()+ " Line #" + ev.m_styleNode.getLineNumber() + ", "
136                      + "Column #" + ev.m_styleNode.getColumnNumber() + ": "
137                      + ev.m_styleNode.getNodeName());
138       }
139     }
140   }
141 
142   int m_indent = 0;
143 
144   /**
145    * Print information about a TracerEvent.
146    *
147    * @param ev the trace event.
148    */
trace(TracerEvent ev)149   public void trace(TracerEvent ev)
150   {
151 //  	m_traceElements = true;
152 //  	m_traceTemplates = true;
153 //
154 //  	for(int i = 0; i < m_indent; i++)
155 //  		m_pw.print(" ");
156 //    m_indent = m_indent+2;
157 //  	m_pw.print("trace: ");
158 	_trace(ev);
159   }
160 
161   /**
162    * Method that is called when the end of a trace event occurs.
163    * The method is blocking.  It must return before processing continues.
164    *
165    * @param ev the trace event.
166    */
traceEnd(TracerEvent ev)167   public void traceEnd(TracerEvent ev)
168   {
169 //  	m_traceElements = true;
170 //  	m_traceTemplates = true;
171 //
172 //  	m_indent = m_indent-2;
173 //  	for(int i = 0; i < m_indent; i++)
174 //  		m_pw.print(" ");
175 //  	m_pw.print("etrac: ");
176 //	_trace(ev);
177   }
178 
179 
180   /**
181    * Method that is called just after a select attribute has been evaluated.
182    *
183    * @param ev the generate event.
184    *
185    * @throws javax.xml.transform.TransformerException
186    */
selected(SelectionEvent ev)187 public void selected(SelectionEvent ev)
188     throws javax.xml.transform.TransformerException {
189 
190     if (m_traceSelection) {
191         ElemTemplateElement ete = (ElemTemplateElement) ev.m_styleNode;
192         Node sourceNode = ev.m_sourceNode;
193 
194         SourceLocator locator = null;
195         if (sourceNode instanceof DTMNodeProxy) {
196             int nodeHandler = ((DTMNodeProxy) sourceNode).getDTMNodeNumber();
197             locator =
198                 ((DTMNodeProxy) sourceNode).getDTM().getSourceLocatorFor(
199                     nodeHandler);
200         }
201 
202         if (locator != null)
203             m_pw.println(
204                 "Selected source node '"
205                     + sourceNode.getNodeName()
206                     + "', at "
207                     + locator);
208         else
209             m_pw.println(
210                 "Selected source node '" + sourceNode.getNodeName() + "'");
211 
212         if (ev.m_styleNode.getLineNumber() == 0) {
213 
214             // You may not have line numbers if the selection is occuring from a
215             // default template.
216             ElemTemplateElement parent =
217                 (ElemTemplateElement) ete.getParentElem();
218 
219             if (parent == ete.getStylesheetRoot().getDefaultRootRule()) {
220                 m_pw.print("(default root rule) ");
221             } else if (
222                 parent == ete.getStylesheetRoot().getDefaultTextRule()) {
223                 m_pw.print("(default text rule) ");
224             } else if (parent == ete.getStylesheetRoot().getDefaultRule()) {
225                 m_pw.print("(default rule) ");
226             }
227 
228             m_pw.print(
229                 ete.getNodeName()
230                     + ", "
231                     + ev.m_attributeName
232                     + "='"
233                     + ev.m_xpath.getPatternString()
234                     + "': ");
235         } else {
236             m_pw.print(
237                 ev.m_styleNode.getSystemId()
238                     + " Line #"
239                     + ev.m_styleNode.getLineNumber()
240                     + ", "
241                     + "Column #"
242                     + ev.m_styleNode.getColumnNumber()
243                     + ": "
244                     + ete.getNodeName()
245                     + ", "
246                     + ev.m_attributeName
247                     + "='"
248                     + ev.m_xpath.getPatternString()
249                     + "': ");
250         }
251 
252         if (ev.m_selection.getType() == ev.m_selection.CLASS_NODESET) {
253             m_pw.println();
254 
255             org.apache.xml.dtm.DTMIterator nl = ev.m_selection.iter();
256 
257             // The following lines are added to fix bug#16222.
258             // The main cause is that the following loop change the state of iterator, which is shared
259             // with the transformer. The fix is that we record the initial state before looping, then
260             // restore the state when we finish it, which is done in the following lines added.
261             int currentPos = DTM.NULL;
262             currentPos = nl.getCurrentPos();
263             nl.setShouldCacheNodes(true); // This MUST be done before we clone the iterator!
264             org.apache.xml.dtm.DTMIterator clone = null;
265             // End of block
266 
267             try {
268                 clone = nl.cloneWithReset();
269             } catch (CloneNotSupportedException cnse) {
270                 m_pw.println(
271                     "     [Can't trace nodelist because it it threw a CloneNotSupportedException]");
272                 return;
273             }
274             int pos = clone.nextNode();
275 
276             if (DTM.NULL == pos) {
277                 m_pw.println("     [empty node list]");
278             } else {
279                 while (DTM.NULL != pos) {
280                     // m_pw.println("     " + ev.m_processor.getXPathContext().getDTM(pos).getNode(pos));
281                     DTM dtm = ev.m_processor.getXPathContext().getDTM(pos);
282                     m_pw.print("     ");
283                     m_pw.print(Integer.toHexString(pos));
284                     m_pw.print(": ");
285                     m_pw.println(dtm.getNodeName(pos));
286                     pos = clone.nextNode();
287                 }
288             }
289 
290             // Restore the initial state of the iterator, part of fix for bug#16222.
291             nl.runTo(-1);
292             nl.setCurrentPos(currentPos);
293         	// End of fix for bug#16222
294 
295         } else {
296             m_pw.println(ev.m_selection.str());
297         }
298     }
299 }
300   /**
301    * Method that is called after an xsl:apply-templates or xsl:for-each
302    * selection occurs.
303    *
304    * @param ev the generate event.
305    *
306    * @throws javax.xml.transform.TransformerException
307    */
selectEnd(EndSelectionEvent ev)308   public void selectEnd(EndSelectionEvent ev)
309      throws javax.xml.transform.TransformerException
310   {
311   	// Nothing for right now.
312   }
313 
314 
315   /**
316    * Print information about a Generate event.
317    *
318    * @param ev the trace event.
319    */
generated(GenerateEvent ev)320   public void generated(GenerateEvent ev)
321   {
322 
323     if (m_traceGeneration)
324     {
325       switch (ev.m_eventtype)
326       {
327       case SerializerTrace.EVENTTYPE_STARTDOCUMENT :
328         m_pw.println("STARTDOCUMENT");
329         break;
330       case SerializerTrace.EVENTTYPE_ENDDOCUMENT :
331         m_pw.println("ENDDOCUMENT");
332         break;
333       case SerializerTrace.EVENTTYPE_STARTELEMENT :
334         m_pw.println("STARTELEMENT: " + ev.m_name);
335         break;
336       case SerializerTrace.EVENTTYPE_ENDELEMENT :
337         m_pw.println("ENDELEMENT: " + ev.m_name);
338         break;
339       case SerializerTrace.EVENTTYPE_CHARACTERS :
340       {
341         String chars = new String(ev.m_characters, ev.m_start, ev.m_length);
342 
343         m_pw.println("CHARACTERS: " + chars);
344       }
345       break;
346       case SerializerTrace.EVENTTYPE_CDATA :
347       {
348         String chars = new String(ev.m_characters, ev.m_start, ev.m_length);
349 
350         m_pw.println("CDATA: " + chars);
351       }
352       break;
353       case SerializerTrace.EVENTTYPE_COMMENT :
354         m_pw.println("COMMENT: " + ev.m_data);
355         break;
356       case SerializerTrace.EVENTTYPE_PI :
357         m_pw.println("PI: " + ev.m_name + ", " + ev.m_data);
358         break;
359       case SerializerTrace.EVENTTYPE_ENTITYREF :
360         m_pw.println("ENTITYREF: " + ev.m_name);
361         break;
362       case SerializerTrace.EVENTTYPE_IGNORABLEWHITESPACE :
363         m_pw.println("IGNORABLEWHITESPACE");
364         break;
365       }
366     }
367   }
368 
369   /**
370    * Print information about an extension event.
371    *
372    * @param ev the extension event to print information about
373    */
extension(ExtensionEvent ev)374   public void extension(ExtensionEvent ev) {
375     if (m_traceExtension) {
376       switch (ev.m_callType) {
377         case ExtensionEvent.DEFAULT_CONSTRUCTOR:
378           m_pw.println("EXTENSION: " + ((Class)ev.m_method).getName() + "#<init>");
379           break;
380         case ExtensionEvent.METHOD:
381           m_pw.println("EXTENSION: " + ((Method)ev.m_method).getDeclaringClass().getName() + "#" + ((Method)ev.m_method).getName());
382           break;
383         case ExtensionEvent.CONSTRUCTOR:
384           m_pw.println("EXTENSION: " + ((Constructor)ev.m_method).getDeclaringClass().getName() + "#<init>");
385           break;
386       }
387     }
388   }
389 
390 
391   /**
392    * Print information about an extension event.
393    *
394    * @param ev the extension event to print information about
395    */
extensionEnd(ExtensionEvent ev)396   public void extensionEnd(ExtensionEvent ev) {
397     // do nothing
398   }
399 
400 }
401