001: /*
002: * Copyright 1999-2004 The Apache Software Foundation.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: /*
017: * $Id: PrintTraceListener.java,v 1.21 2004/02/16 23:00:27 minchau Exp $
018: */
019: package org.apache.xalan.trace;
020:
021: import java.lang.reflect.Constructor;
022: import java.lang.reflect.Method;
023:
024: import javax.xml.transform.SourceLocator;
025:
026: import org.apache.xalan.templates.Constants;
027: import org.apache.xalan.templates.ElemTemplate;
028: import org.apache.xalan.templates.ElemTemplateElement;
029: import org.apache.xalan.templates.ElemTextLiteral;
030: import org.apache.xml.dtm.DTM;
031: import org.apache.xml.dtm.ref.DTMNodeProxy;
032: import org.apache.xml.serializer.SerializerTrace;
033:
034: import org.w3c.dom.Node;
035:
036: /**
037: * Implementation of the TraceListener interface that
038: * prints each event to standard out as it occurs.
039: *
040: * @see org.apache.xalan.trace.TracerEvent
041: * @xsl.usage advanced
042: */
043: public class PrintTraceListener implements TraceListenerEx3 {
044:
045: /**
046: * Construct a trace listener.
047: *
048: * @param pw PrintWriter to use for tracing events
049: */
050: public PrintTraceListener(java.io.PrintWriter pw) {
051: m_pw = pw;
052: }
053:
054: /**
055: * The print writer where the events should be written.
056: */
057: java.io.PrintWriter m_pw;
058:
059: /**
060: * This needs to be set to true if the listener is to print an event whenever a template is invoked.
061: */
062: public boolean m_traceTemplates = false;
063:
064: /**
065: * Set to true if the listener is to print events that occur as each node is 'executed' in the stylesheet.
066: */
067: public boolean m_traceElements = false;
068:
069: /**
070: * Set to true if the listener is to print information after each result-tree generation event.
071: */
072: public boolean m_traceGeneration = false;
073:
074: /**
075: * Set to true if the listener is to print information after each selection event.
076: */
077: public boolean m_traceSelection = false;
078:
079: /**
080: * Set to true if the listener is to print information after each extension event.
081: */
082: public boolean m_traceExtension = false;
083:
084: /**
085: * Print information about a TracerEvent.
086: *
087: * @param ev the trace event.
088: */
089: public void _trace(TracerEvent ev) {
090:
091: switch (ev.m_styleNode.getXSLToken()) {
092: case Constants.ELEMNAME_TEXTLITERALRESULT:
093: if (m_traceElements) {
094: m_pw.print(ev.m_styleNode.getSystemId() + " Line #"
095: + ev.m_styleNode.getLineNumber() + ", "
096: + "Column #" + ev.m_styleNode.getColumnNumber()
097: + " -- " + ev.m_styleNode.getNodeName() + ": ");
098:
099: ElemTextLiteral etl = (ElemTextLiteral) ev.m_styleNode;
100: String chars = new String(etl.getChars(), 0, etl
101: .getChars().length);
102:
103: m_pw.println(" " + chars.trim());
104: }
105: break;
106: case Constants.ELEMNAME_TEMPLATE:
107: if (m_traceTemplates || m_traceElements) {
108: ElemTemplate et = (ElemTemplate) ev.m_styleNode;
109:
110: m_pw.print(et.getSystemId() + " Line #"
111: + et.getLineNumber() + ", " + "Column #"
112: + et.getColumnNumber() + ": "
113: + et.getNodeName() + " ");
114:
115: if (null != et.getMatch()) {
116: m_pw.print("match='"
117: + et.getMatch().getPatternString() + "' ");
118: }
119:
120: if (null != et.getName()) {
121: m_pw.print("name='" + et.getName() + "' ");
122: }
123:
124: m_pw.println();
125: }
126: break;
127: default:
128: if (m_traceElements) {
129: m_pw.println(ev.m_styleNode.getSystemId() + " Line #"
130: + ev.m_styleNode.getLineNumber() + ", "
131: + "Column #" + ev.m_styleNode.getColumnNumber()
132: + ": " + ev.m_styleNode.getNodeName());
133: }
134: }
135: }
136:
137: int m_indent = 0;
138:
139: /**
140: * Print information about a TracerEvent.
141: *
142: * @param ev the trace event.
143: */
144: public void trace(TracerEvent ev) {
145: // m_traceElements = true;
146: // m_traceTemplates = true;
147: //
148: // for(int i = 0; i < m_indent; i++)
149: // m_pw.print(" ");
150: // m_indent = m_indent+2;
151: // m_pw.print("trace: ");
152: _trace(ev);
153: }
154:
155: /**
156: * Method that is called when the end of a trace event occurs.
157: * The method is blocking. It must return before processing continues.
158: *
159: * @param ev the trace event.
160: */
161: public void traceEnd(TracerEvent ev) {
162: // m_traceElements = true;
163: // m_traceTemplates = true;
164: //
165: // m_indent = m_indent-2;
166: // for(int i = 0; i < m_indent; i++)
167: // m_pw.print(" ");
168: // m_pw.print("etrac: ");
169: // _trace(ev);
170: }
171:
172: /**
173: * Method that is called just after a select attribute has been evaluated.
174: *
175: * @param ev the generate event.
176: *
177: * @throws javax.xml.transform.TransformerException
178: */
179: public void selected(SelectionEvent ev)
180: throws javax.xml.transform.TransformerException {
181:
182: if (m_traceSelection) {
183: ElemTemplateElement ete = (ElemTemplateElement) ev.m_styleNode;
184: Node sourceNode = ev.m_sourceNode;
185:
186: SourceLocator locator = null;
187: if (sourceNode instanceof DTMNodeProxy) {
188: int nodeHandler = ((DTMNodeProxy) sourceNode)
189: .getDTMNodeNumber();
190: locator = ((DTMNodeProxy) sourceNode).getDTM()
191: .getSourceLocatorFor(nodeHandler);
192: }
193:
194: if (locator != null)
195: m_pw
196: .println("Selected source node '"
197: + sourceNode.getNodeName() + "', at "
198: + locator);
199: else
200: m_pw.println("Selected source node '"
201: + sourceNode.getNodeName() + "'");
202:
203: if (ev.m_styleNode.getLineNumber() == 0) {
204:
205: // You may not have line numbers if the selection is occuring from a
206: // default template.
207: ElemTemplateElement parent = (ElemTemplateElement) ete
208: .getParentElem();
209:
210: if (parent == ete.getStylesheetRoot()
211: .getDefaultRootRule()) {
212: m_pw.print("(default root rule) ");
213: } else if (parent == ete.getStylesheetRoot()
214: .getDefaultTextRule()) {
215: m_pw.print("(default text rule) ");
216: } else if (parent == ete.getStylesheetRoot()
217: .getDefaultRule()) {
218: m_pw.print("(default rule) ");
219: }
220:
221: m_pw.print(ete.getNodeName() + ", "
222: + ev.m_attributeName + "='"
223: + ev.m_xpath.getPatternString() + "': ");
224: } else {
225: m_pw.print(ev.m_styleNode.getSystemId() + " Line #"
226: + ev.m_styleNode.getLineNumber() + ", "
227: + "Column #" + ev.m_styleNode.getColumnNumber()
228: + ": " + ete.getNodeName() + ", "
229: + ev.m_attributeName + "='"
230: + ev.m_xpath.getPatternString() + "': ");
231: }
232:
233: if (ev.m_selection.getType() == ev.m_selection.CLASS_NODESET) {
234: m_pw.println();
235:
236: org.apache.xml.dtm.DTMIterator nl = ev.m_selection
237: .iter();
238:
239: // The following lines are added to fix bug#16222.
240: // The main cause is that the following loop change the state of iterator, which is shared
241: // with the transformer. The fix is that we record the initial state before looping, then
242: // restore the state when we finish it, which is done in the following lines added.
243: int currentPos = DTM.NULL;
244: currentPos = nl.getCurrentPos();
245: nl.setShouldCacheNodes(true); // This MUST be done before we clone the iterator!
246: org.apache.xml.dtm.DTMIterator clone = null;
247: // End of block
248:
249: try {
250: clone = nl.cloneWithReset();
251: } catch (CloneNotSupportedException cnse) {
252: m_pw
253: .println(" [Can't trace nodelist because it it threw a CloneNotSupportedException]");
254: return;
255: }
256: int pos = clone.nextNode();
257:
258: if (DTM.NULL == pos) {
259: m_pw.println(" [empty node list]");
260: } else {
261: while (DTM.NULL != pos) {
262: // m_pw.println(" " + ev.m_processor.getXPathContext().getDTM(pos).getNode(pos));
263: DTM dtm = ev.m_processor.getXPathContext()
264: .getDTM(pos);
265: m_pw.print(" ");
266: m_pw.print(Integer.toHexString(pos));
267: m_pw.print(": ");
268: m_pw.println(dtm.getNodeName(pos));
269: pos = clone.nextNode();
270: }
271: }
272:
273: // Restore the initial state of the iterator, part of fix for bug#16222.
274: nl.runTo(-1);
275: nl.setCurrentPos(currentPos);
276: // End of fix for bug#16222
277:
278: } else {
279: m_pw.println(ev.m_selection.str());
280: }
281: }
282: }
283:
284: /**
285: * Method that is called after an xsl:apply-templates or xsl:for-each
286: * selection occurs.
287: *
288: * @param ev the generate event.
289: *
290: * @throws javax.xml.transform.TransformerException
291: */
292: public void selectEnd(EndSelectionEvent ev)
293: throws javax.xml.transform.TransformerException {
294: // Nothing for right now.
295: }
296:
297: /**
298: * Print information about a Generate event.
299: *
300: * @param ev the trace event.
301: */
302: public void generated(GenerateEvent ev) {
303:
304: if (m_traceGeneration) {
305: switch (ev.m_eventtype) {
306: case SerializerTrace.EVENTTYPE_STARTDOCUMENT:
307: m_pw.println("STARTDOCUMENT");
308: break;
309: case SerializerTrace.EVENTTYPE_ENDDOCUMENT:
310: m_pw.println("ENDDOCUMENT");
311: break;
312: case SerializerTrace.EVENTTYPE_STARTELEMENT:
313: m_pw.println("STARTELEMENT: " + ev.m_name);
314: break;
315: case SerializerTrace.EVENTTYPE_ENDELEMENT:
316: m_pw.println("ENDELEMENT: " + ev.m_name);
317: break;
318: case SerializerTrace.EVENTTYPE_CHARACTERS: {
319: String chars = new String(ev.m_characters, ev.m_start,
320: ev.m_length);
321:
322: m_pw.println("CHARACTERS: " + chars);
323: }
324: break;
325: case SerializerTrace.EVENTTYPE_CDATA: {
326: String chars = new String(ev.m_characters, ev.m_start,
327: ev.m_length);
328:
329: m_pw.println("CDATA: " + chars);
330: }
331: break;
332: case SerializerTrace.EVENTTYPE_COMMENT:
333: m_pw.println("COMMENT: " + ev.m_data);
334: break;
335: case SerializerTrace.EVENTTYPE_PI:
336: m_pw.println("PI: " + ev.m_name + ", " + ev.m_data);
337: break;
338: case SerializerTrace.EVENTTYPE_ENTITYREF:
339: m_pw.println("ENTITYREF: " + ev.m_name);
340: break;
341: case SerializerTrace.EVENTTYPE_IGNORABLEWHITESPACE:
342: m_pw.println("IGNORABLEWHITESPACE");
343: break;
344: }
345: }
346: }
347:
348: /**
349: * Print information about an extension event.
350: *
351: * @param ev the extension event to print information about
352: */
353: public void extension(ExtensionEvent ev) {
354: if (m_traceExtension) {
355: switch (ev.m_callType) {
356: case ExtensionEvent.DEFAULT_CONSTRUCTOR:
357: m_pw.println("EXTENSION: "
358: + ((Class) ev.m_method).getName() + "#<init>");
359: break;
360: case ExtensionEvent.METHOD:
361: m_pw.println("EXTENSION: "
362: + ((Method) ev.m_method).getDeclaringClass()
363: .getName() + "#"
364: + ((Method) ev.m_method).getName());
365: break;
366: case ExtensionEvent.CONSTRUCTOR:
367: m_pw.println("EXTENSION: "
368: + ((Constructor) ev.m_method)
369: .getDeclaringClass().getName()
370: + "#<init>");
371: break;
372: }
373: }
374: }
375:
376: /**
377: * Print information about an extension event.
378: *
379: * @param ev the extension event to print information about
380: */
381: public void extensionEnd(ExtensionEvent ev) {
382: // do nothing
383: }
384:
385: }
|