001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the "License"); 007 * you may not use this file except in compliance with the License. 008 * You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 /* 019 * $Id: PrintTraceListener.java 468644 2006-10-28 06:56:42Z minchau $ 020 */ 021 package org.apache.xalan.trace; 022 023 import java.lang.reflect.Constructor; 024 import java.lang.reflect.Method; 025 026 import javax.xml.transform.SourceLocator; 027 028 import org.apache.xalan.templates.Constants; 029 import org.apache.xalan.templates.ElemTemplate; 030 import org.apache.xalan.templates.ElemTemplateElement; 031 import org.apache.xalan.templates.ElemTextLiteral; 032 import org.apache.xml.dtm.DTM; 033 import org.apache.xml.dtm.ref.DTMNodeProxy; 034 import org.apache.xml.serializer.SerializerTrace; 035 036 import org.w3c.dom.Node; 037 038 /** 039 * Implementation of the TraceListener interface that 040 * prints each event to standard out as it occurs. 041 * 042 * @see org.apache.xalan.trace.TracerEvent 043 * @xsl.usage advanced 044 */ 045 public class PrintTraceListener implements TraceListenerEx3 046 { 047 048 /** 049 * Construct a trace listener. 050 * 051 * @param pw PrintWriter to use for tracing events 052 */ 053 public PrintTraceListener(java.io.PrintWriter pw) 054 { 055 m_pw = pw; 056 } 057 058 /** 059 * The print writer where the events should be written. 060 */ 061 java.io.PrintWriter m_pw; 062 063 /** 064 * This needs to be set to true if the listener is to print an event whenever a template is invoked. 065 */ 066 public boolean m_traceTemplates = false; 067 068 /** 069 * Set to true if the listener is to print events that occur as each node is 'executed' in the stylesheet. 070 */ 071 public boolean m_traceElements = false; 072 073 /** 074 * Set to true if the listener is to print information after each result-tree generation event. 075 */ 076 public boolean m_traceGeneration = false; 077 078 /** 079 * Set to true if the listener is to print information after each selection event. 080 */ 081 public boolean m_traceSelection = false; 082 083 /** 084 * Set to true if the listener is to print information after each extension event. 085 */ 086 public boolean m_traceExtension = false; 087 088 /** 089 * Print information about a TracerEvent. 090 * 091 * @param ev the trace event. 092 */ 093 public void _trace(TracerEvent ev) 094 { 095 096 switch (ev.m_styleNode.getXSLToken()) 097 { 098 case Constants.ELEMNAME_TEXTLITERALRESULT : 099 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 396 public void extensionEnd(ExtensionEvent ev) { 397 // do nothing 398 } 399 400 }