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: TraceManager.java 468644 2006-10-28 06:56:42Z minchau $
020 */
021 package org.apache.xalan.trace;
022
023 import java.lang.reflect.Method;
024 import java.util.TooManyListenersException;
025 import java.util.Vector;
026
027 import org.apache.xalan.templates.ElemTemplateElement;
028 import org.apache.xalan.transformer.TransformerImpl;
029 import org.apache.xpath.XPath;
030 import org.apache.xpath.objects.XObject;
031 import org.w3c.dom.Node;
032
033 /**
034 * This class manages trace listeners, and acts as an
035 * interface for the tracing functionality in Xalan.
036 */
037 public class TraceManager
038 {
039
040 /** A transformer instance */
041 private TransformerImpl m_transformer;
042
043 /**
044 * Constructor for the trace manager.
045 *
046 * @param transformer a non-null instance of a transformer
047 */
048 public TraceManager(TransformerImpl transformer)
049 {
050 m_transformer = transformer;
051 }
052
053 /**
054 * List of listeners who are interested in tracing what's
055 * being generated.
056 */
057 private Vector m_traceListeners = null;
058
059 /**
060 * Add a trace listener for the purposes of debugging and diagnosis.
061 * @param tl Trace listener to be added.
062 *
063 * @throws TooManyListenersException
064 */
065 public void addTraceListener(TraceListener tl)
066 throws TooManyListenersException
067 {
068
069 m_transformer.setDebug(true);
070
071 if (null == m_traceListeners)
072 m_traceListeners = new Vector();
073
074 m_traceListeners.addElement(tl);
075 }
076
077 /**
078 * Remove a trace listener.
079 * @param tl Trace listener to be removed.
080 */
081 public void removeTraceListener(TraceListener tl)
082 {
083
084 if (null != m_traceListeners)
085 {
086 m_traceListeners.removeElement(tl);
087
088 // The following line added to fix the bug#5140: hasTraceListeners() returns true
089 // after adding and removing a listener.
090 // Check: if m_traceListeners is empty, then set it to NULL.
091 if (0 == m_traceListeners.size()) m_traceListeners = null;
092 }
093 }
094
095 /**
096 * Fire a generate event.
097 *
098 * @param te Generate Event to fire
099 */
100 public void fireGenerateEvent(GenerateEvent te)
101 {
102
103 if (null != m_traceListeners)
104 {
105 int nListeners = m_traceListeners.size();
106
107 for (int i = 0; i < nListeners; i++)
108 {
109 TraceListener tl = (TraceListener) m_traceListeners.elementAt(i);
110
111 tl.generated(te);
112 }
113 }
114 }
115
116 /**
117 * Tell if trace listeners are present.
118 *
119 * @return True if there are trace listeners
120 */
121 public boolean hasTraceListeners()
122 {
123 return (null != m_traceListeners);
124 }
125
126 /**
127 * Fire a trace event.
128 *
129 * @param styleNode Stylesheet template node
130 */
131 public void fireTraceEvent(ElemTemplateElement styleNode)
132 {
133
134 if (hasTraceListeners())
135 {
136 int sourceNode = m_transformer.getXPathContext().getCurrentNode();
137 Node source = getDOMNodeFromDTM(sourceNode);
138
139 fireTraceEvent(new TracerEvent(m_transformer, source,
140 m_transformer.getMode(), /*sourceNode, mode,*/
141 styleNode));
142 }
143 }
144
145 /**
146 * Fire a end trace event, after all children of an element have been
147 * executed.
148 *
149 * @param styleNode Stylesheet template node
150 */
151 public void fireTraceEndEvent(ElemTemplateElement styleNode)
152 {
153
154 if (hasTraceListeners())
155 {
156 int sourceNode = m_transformer.getXPathContext().getCurrentNode();
157 Node source = getDOMNodeFromDTM(sourceNode);
158
159 fireTraceEndEvent(new TracerEvent(m_transformer, source,
160 m_transformer.getMode(), /*sourceNode, mode,*/
161 styleNode));
162 }
163 }
164
165 /**
166 * Fire a trace event.
167 *
168 * @param te Trace event to fire
169 */
170 public void fireTraceEndEvent(TracerEvent te)
171 {
172
173 if (hasTraceListeners())
174 {
175 int nListeners = m_traceListeners.size();
176
177 for (int i = 0; i < nListeners; i++)
178 {
179 TraceListener tl = (TraceListener) m_traceListeners.elementAt(i);
180 if(tl instanceof TraceListenerEx2)
181 {
182 ((TraceListenerEx2)tl).traceEnd(te);
183 }
184 }
185 }
186 }
187
188
189
190 /**
191 * Fire a trace event.
192 *
193 * @param te Trace event to fire
194 */
195 public void fireTraceEvent(TracerEvent te)
196 {
197
198 if (hasTraceListeners())
199 {
200 int nListeners = m_traceListeners.size();
201
202 for (int i = 0; i < nListeners; i++)
203 {
204 TraceListener tl = (TraceListener) m_traceListeners.elementAt(i);
205
206 tl.trace(te);
207 }
208 }
209 }
210
211 /**
212 * Fire a selection event.
213 *
214 * @param sourceNode Current source node
215 * @param styleNode node in the style tree reference for the event.
216 * @param attributeName The attribute name from which the selection is made.
217 * @param xpath The XPath that executed the selection.
218 * @param selection The result of the selection.
219 *
220 * @throws javax.xml.transform.TransformerException
221 */
222 public void fireSelectedEvent(
223 int sourceNode, ElemTemplateElement styleNode, String attributeName,
224 XPath xpath, XObject selection)
225 throws javax.xml.transform.TransformerException
226 {
227
228 if (hasTraceListeners())
229 {
230 Node source = getDOMNodeFromDTM(sourceNode);
231
232 fireSelectedEvent(new SelectionEvent(m_transformer, source, styleNode,
233 attributeName, xpath, selection));
234 }
235 }
236
237 /**
238 * Fire a selection event.
239 *
240 * @param sourceNode Current source node
241 * @param styleNode node in the style tree reference for the event.
242 * @param attributeName The attribute name from which the selection is made.
243 * @param xpath The XPath that executed the selection.
244 * @param selection The result of the selection.
245 *
246 * @throws javax.xml.transform.TransformerException
247 */
248 public void fireSelectedEndEvent(
249 int sourceNode, ElemTemplateElement styleNode, String attributeName,
250 XPath xpath, XObject selection)
251 throws javax.xml.transform.TransformerException
252 {
253
254 if (hasTraceListeners())
255 {
256 Node source = getDOMNodeFromDTM(sourceNode);
257
258 fireSelectedEndEvent(new EndSelectionEvent(m_transformer, source, styleNode,
259 attributeName, xpath, selection));
260 }
261 }
262
263 /**
264 * Fire a selection event.
265 *
266 * @param se Selection event to fire
267 *
268 * @throws javax.xml.transform.TransformerException
269 */
270 public void fireSelectedEndEvent(EndSelectionEvent se)
271 throws javax.xml.transform.TransformerException
272 {
273
274 if (hasTraceListeners())
275 {
276 int nListeners = m_traceListeners.size();
277
278 for (int i = 0; i < nListeners; i++)
279 {
280 TraceListener tl = (TraceListener) m_traceListeners.elementAt(i);
281
282 if(tl instanceof TraceListenerEx)
283 ((TraceListenerEx)tl).selectEnd(se);
284 }
285 }
286 }
287
288 /**
289 * Fire a selection event.
290 *
291 * @param se Selection event to fire
292 *
293 * @throws javax.xml.transform.TransformerException
294 */
295 public void fireSelectedEvent(SelectionEvent se)
296 throws javax.xml.transform.TransformerException
297 {
298
299 if (hasTraceListeners())
300 {
301 int nListeners = m_traceListeners.size();
302
303 for (int i = 0; i < nListeners; i++)
304 {
305 TraceListener tl = (TraceListener) m_traceListeners.elementAt(i);
306
307 tl.selected(se);
308 }
309 }
310 }
311
312
313 /**
314 * Fire an end extension event.
315 *
316 * @see java.lang.reflect.Method#invoke
317 *
318 * @param method The java method about to be executed
319 * @param instance The instance the method will be executed on
320 * @param arguments Parameters passed to the method.
321 */
322 public void fireExtensionEndEvent(Method method, Object instance, Object[] arguments)
323 {
324 ExtensionEvent ee = new ExtensionEvent(m_transformer, method, instance, arguments);
325
326 if (hasTraceListeners())
327 {
328 int nListeners = m_traceListeners.size();
329
330 for (int i = 0; i < nListeners; i++)
331 {
332 TraceListener tl = (TraceListener) m_traceListeners.elementAt(i);
333 if(tl instanceof TraceListenerEx3)
334 {
335 ((TraceListenerEx3)tl).extensionEnd(ee);
336 }
337 }
338 }
339 }
340
341 /**
342 * Fire an end extension event.
343 *
344 * @see java.lang.reflect.Method#invoke
345 *
346 * @param method The java method about to be executed
347 * @param instance The instance the method will be executed on
348 * @param arguments Parameters passed to the method.
349 */
350 public void fireExtensionEvent(Method method, Object instance, Object[] arguments)
351 {
352 ExtensionEvent ee = new ExtensionEvent(m_transformer, method, instance, arguments);
353
354 if (hasTraceListeners())
355 {
356 int nListeners = m_traceListeners.size();
357
358 for (int i = 0; i < nListeners; i++)
359 {
360 TraceListener tl = (TraceListener) m_traceListeners.elementAt(i);
361 if(tl instanceof TraceListenerEx3)
362 {
363 ((TraceListenerEx3)tl).extension(ee);
364 }
365 }
366 }
367 }
368
369 /**
370 * Fire an end extension event.
371 *
372 * @see java.lang.reflect.Method#invoke
373 *
374 * @param ee the ExtensionEvent to fire
375 */
376 public void fireExtensionEndEvent(ExtensionEvent ee)
377 {
378 if (hasTraceListeners())
379 {
380 int nListeners = m_traceListeners.size();
381
382 for (int i = 0; i < nListeners; i++)
383 {
384 TraceListener tl = (TraceListener) m_traceListeners.elementAt(i);
385 if(tl instanceof TraceListenerEx3)
386 {
387 ((TraceListenerEx3)tl).extensionEnd(ee);
388 }
389 }
390 }
391 }
392
393 /**
394 * Fire an end extension event.
395 *
396 * @see java.lang.reflect.Method#invoke
397 *
398 * @param ee the ExtensionEvent to fire
399 */
400 public void fireExtensionEvent(ExtensionEvent ee)
401 {
402
403 if (hasTraceListeners())
404 {
405 int nListeners = m_traceListeners.size();
406
407 for (int i = 0; i < nListeners; i++)
408 {
409 TraceListener tl = (TraceListener) m_traceListeners.elementAt(i);
410 if(tl instanceof TraceListenerEx3)
411 {
412 ((TraceListenerEx3)tl).extension(ee);
413 }
414 }
415 }
416 }
417
418 /**
419 * Get the DOM Node of the current XPath context, which is possibly null.
420 * @param sourceNode the handle on the node used by a DTM.
421 */
422 private Node getDOMNodeFromDTM(int sourceNode) {
423 org.apache.xml.dtm.DTM dtm = m_transformer.getXPathContext().getDTM(sourceNode);
424 final Node source = (dtm == null) ? null : dtm.getNode(sourceNode);
425 return source;
426 }
427 }