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.Method; 24 import java.util.TooManyListenersException; 25 import java.util.Vector; 26 27 import org.apache.xalan.templates.ElemTemplateElement; 28 import org.apache.xalan.transformer.TransformerImpl; 29 import org.apache.xpath.XPath; 30 import org.apache.xpath.objects.XObject; 31 import org.w3c.dom.Node; 32 33 /** 34 * This class manages trace listeners, and acts as an 35 * interface for the tracing functionality in Xalan. 36 */ 37 public class TraceManager 38 { 39 40 /** A transformer instance */ 41 private TransformerImpl m_transformer; 42 43 /** 44 * Constructor for the trace manager. 45 * 46 * @param transformer a non-null instance of a transformer 47 */ TraceManager(TransformerImpl transformer)48 public TraceManager(TransformerImpl transformer) 49 { 50 m_transformer = transformer; 51 } 52 53 /** 54 * List of listeners who are interested in tracing what's 55 * being generated. 56 */ 57 private Vector m_traceListeners = null; 58 59 /** 60 * Add a trace listener for the purposes of debugging and diagnosis. 61 * @param tl Trace listener to be added. 62 * 63 * @throws TooManyListenersException 64 */ addTraceListener(TraceListener tl)65 public void addTraceListener(TraceListener tl) 66 throws TooManyListenersException 67 { 68 69 // Android-changed: TransformerImpl in 2.7.1 doesn't have setDebug() method. 70 // m_transformer.setDebug(true); 71 72 if (null == m_traceListeners) 73 m_traceListeners = new Vector(); 74 75 m_traceListeners.addElement(tl); 76 } 77 78 /** 79 * Remove a trace listener. 80 * @param tl Trace listener to be removed. 81 */ removeTraceListener(TraceListener tl)82 public void removeTraceListener(TraceListener tl) 83 { 84 85 if (null != m_traceListeners) 86 { 87 m_traceListeners.removeElement(tl); 88 89 // The following line added to fix the bug#5140: hasTraceListeners() returns true 90 // after adding and removing a listener. 91 // Check: if m_traceListeners is empty, then set it to NULL. 92 if (0 == m_traceListeners.size()) m_traceListeners = null; 93 } 94 } 95 96 /** 97 * Fire a generate event. 98 * 99 * @param te Generate Event to fire 100 */ fireGenerateEvent(GenerateEvent te)101 public void fireGenerateEvent(GenerateEvent te) 102 { 103 104 if (null != m_traceListeners) 105 { 106 int nListeners = m_traceListeners.size(); 107 108 for (int i = 0; i < nListeners; i++) 109 { 110 TraceListener tl = (TraceListener) m_traceListeners.elementAt(i); 111 112 tl.generated(te); 113 } 114 } 115 } 116 117 /** 118 * Tell if trace listeners are present. 119 * 120 * @return True if there are trace listeners 121 */ hasTraceListeners()122 public boolean hasTraceListeners() 123 { 124 return (null != m_traceListeners); 125 } 126 127 /** 128 * Fire a trace event. 129 * 130 * @param styleNode Stylesheet template node 131 */ fireTraceEvent(ElemTemplateElement styleNode)132 public void fireTraceEvent(ElemTemplateElement styleNode) 133 { 134 135 if (hasTraceListeners()) 136 { 137 int sourceNode = m_transformer.getXPathContext().getCurrentNode(); 138 Node source = getDOMNodeFromDTM(sourceNode); 139 140 fireTraceEvent(new TracerEvent(m_transformer, source, 141 m_transformer.getMode(), /*sourceNode, mode,*/ 142 styleNode)); 143 } 144 } 145 146 /** 147 * Fire a end trace event, after all children of an element have been 148 * executed. 149 * 150 * @param styleNode Stylesheet template node 151 */ fireTraceEndEvent(ElemTemplateElement styleNode)152 public void fireTraceEndEvent(ElemTemplateElement styleNode) 153 { 154 155 if (hasTraceListeners()) 156 { 157 int sourceNode = m_transformer.getXPathContext().getCurrentNode(); 158 Node source = getDOMNodeFromDTM(sourceNode); 159 160 fireTraceEndEvent(new TracerEvent(m_transformer, source, 161 m_transformer.getMode(), /*sourceNode, mode,*/ 162 styleNode)); 163 } 164 } 165 166 /** 167 * Fire a trace event. 168 * 169 * @param te Trace event to fire 170 */ fireTraceEndEvent(TracerEvent te)171 public void fireTraceEndEvent(TracerEvent te) 172 { 173 174 if (hasTraceListeners()) 175 { 176 int nListeners = m_traceListeners.size(); 177 178 for (int i = 0; i < nListeners; i++) 179 { 180 TraceListener tl = (TraceListener) m_traceListeners.elementAt(i); 181 if(tl instanceof TraceListenerEx2) 182 { 183 ((TraceListenerEx2)tl).traceEnd(te); 184 } 185 } 186 } 187 } 188 189 190 191 /** 192 * Fire a trace event. 193 * 194 * @param te Trace event to fire 195 */ fireTraceEvent(TracerEvent te)196 public void fireTraceEvent(TracerEvent te) 197 { 198 199 if (hasTraceListeners()) 200 { 201 int nListeners = m_traceListeners.size(); 202 203 for (int i = 0; i < nListeners; i++) 204 { 205 TraceListener tl = (TraceListener) m_traceListeners.elementAt(i); 206 207 tl.trace(te); 208 } 209 } 210 } 211 212 /** 213 * Fire a selection event. 214 * 215 * @param sourceNode Current source node 216 * @param styleNode node in the style tree reference for the event. 217 * @param attributeName The attribute name from which the selection is made. 218 * @param xpath The XPath that executed the selection. 219 * @param selection The result of the selection. 220 * 221 * @throws javax.xml.transform.TransformerException 222 */ fireSelectedEvent( int sourceNode, ElemTemplateElement styleNode, String attributeName, XPath xpath, XObject selection)223 public void fireSelectedEvent( 224 int sourceNode, ElemTemplateElement styleNode, String attributeName, 225 XPath xpath, XObject selection) 226 throws javax.xml.transform.TransformerException 227 { 228 229 if (hasTraceListeners()) 230 { 231 Node source = getDOMNodeFromDTM(sourceNode); 232 233 fireSelectedEvent(new SelectionEvent(m_transformer, source, styleNode, 234 attributeName, xpath, selection)); 235 } 236 } 237 238 /** 239 * Fire a selection event. 240 * 241 * @param sourceNode Current source node 242 * @param styleNode node in the style tree reference for the event. 243 * @param attributeName The attribute name from which the selection is made. 244 * @param xpath The XPath that executed the selection. 245 * @param selection The result of the selection. 246 * 247 * @throws javax.xml.transform.TransformerException 248 */ fireSelectedEndEvent( int sourceNode, ElemTemplateElement styleNode, String attributeName, XPath xpath, XObject selection)249 public void fireSelectedEndEvent( 250 int sourceNode, ElemTemplateElement styleNode, String attributeName, 251 XPath xpath, XObject selection) 252 throws javax.xml.transform.TransformerException 253 { 254 255 if (hasTraceListeners()) 256 { 257 Node source = getDOMNodeFromDTM(sourceNode); 258 259 fireSelectedEndEvent(new EndSelectionEvent(m_transformer, source, styleNode, 260 attributeName, xpath, selection)); 261 } 262 } 263 264 /** 265 * Fire a selection event. 266 * 267 * @param se Selection event to fire 268 * 269 * @throws javax.xml.transform.TransformerException 270 */ fireSelectedEndEvent(EndSelectionEvent se)271 public void fireSelectedEndEvent(EndSelectionEvent se) 272 throws javax.xml.transform.TransformerException 273 { 274 275 if (hasTraceListeners()) 276 { 277 int nListeners = m_traceListeners.size(); 278 279 for (int i = 0; i < nListeners; i++) 280 { 281 TraceListener tl = (TraceListener) m_traceListeners.elementAt(i); 282 283 if(tl instanceof TraceListenerEx) 284 ((TraceListenerEx)tl).selectEnd(se); 285 } 286 } 287 } 288 289 /** 290 * Fire a selection event. 291 * 292 * @param se Selection event to fire 293 * 294 * @throws javax.xml.transform.TransformerException 295 */ fireSelectedEvent(SelectionEvent se)296 public void fireSelectedEvent(SelectionEvent se) 297 throws javax.xml.transform.TransformerException 298 { 299 300 if (hasTraceListeners()) 301 { 302 int nListeners = m_traceListeners.size(); 303 304 for (int i = 0; i < nListeners; i++) 305 { 306 TraceListener tl = (TraceListener) m_traceListeners.elementAt(i); 307 308 tl.selected(se); 309 } 310 } 311 } 312 313 314 /** 315 * Fire an end extension event. 316 * 317 * @see java.lang.reflect.Method#invoke 318 * 319 * @param method The java method about to be executed 320 * @param instance The instance the method will be executed on 321 * @param arguments Parameters passed to the method. 322 */ fireExtensionEndEvent(Method method, Object instance, Object[] arguments)323 public void fireExtensionEndEvent(Method method, Object instance, Object[] arguments) 324 { 325 ExtensionEvent ee = new ExtensionEvent(m_transformer, method, instance, arguments); 326 327 if (hasTraceListeners()) 328 { 329 int nListeners = m_traceListeners.size(); 330 331 for (int i = 0; i < nListeners; i++) 332 { 333 TraceListener tl = (TraceListener) m_traceListeners.elementAt(i); 334 if(tl instanceof TraceListenerEx3) 335 { 336 ((TraceListenerEx3)tl).extensionEnd(ee); 337 } 338 } 339 } 340 } 341 342 /** 343 * Fire an end extension event. 344 * 345 * @see java.lang.reflect.Method#invoke 346 * 347 * @param method The java method about to be executed 348 * @param instance The instance the method will be executed on 349 * @param arguments Parameters passed to the method. 350 */ fireExtensionEvent(Method method, Object instance, Object[] arguments)351 public void fireExtensionEvent(Method method, Object instance, Object[] arguments) 352 { 353 ExtensionEvent ee = new ExtensionEvent(m_transformer, method, instance, arguments); 354 355 if (hasTraceListeners()) 356 { 357 int nListeners = m_traceListeners.size(); 358 359 for (int i = 0; i < nListeners; i++) 360 { 361 TraceListener tl = (TraceListener) m_traceListeners.elementAt(i); 362 if(tl instanceof TraceListenerEx3) 363 { 364 ((TraceListenerEx3)tl).extension(ee); 365 } 366 } 367 } 368 } 369 370 /** 371 * Fire an end extension event. 372 * 373 * @see java.lang.reflect.Method#invoke 374 * 375 * @param ee the ExtensionEvent to fire 376 */ fireExtensionEndEvent(ExtensionEvent ee)377 public void fireExtensionEndEvent(ExtensionEvent ee) 378 { 379 if (hasTraceListeners()) 380 { 381 int nListeners = m_traceListeners.size(); 382 383 for (int i = 0; i < nListeners; i++) 384 { 385 TraceListener tl = (TraceListener) m_traceListeners.elementAt(i); 386 if(tl instanceof TraceListenerEx3) 387 { 388 ((TraceListenerEx3)tl).extensionEnd(ee); 389 } 390 } 391 } 392 } 393 394 /** 395 * Fire an end extension event. 396 * 397 * @see java.lang.reflect.Method#invoke 398 * 399 * @param ee the ExtensionEvent to fire 400 */ fireExtensionEvent(ExtensionEvent ee)401 public void fireExtensionEvent(ExtensionEvent ee) 402 { 403 404 if (hasTraceListeners()) 405 { 406 int nListeners = m_traceListeners.size(); 407 408 for (int i = 0; i < nListeners; i++) 409 { 410 TraceListener tl = (TraceListener) m_traceListeners.elementAt(i); 411 if(tl instanceof TraceListenerEx3) 412 { 413 ((TraceListenerEx3)tl).extension(ee); 414 } 415 } 416 } 417 } 418 419 /** 420 * Get the DOM Node of the current XPath context, which is possibly null. 421 * @param sourceNode the handle on the node used by a DTM. 422 */ getDOMNodeFromDTM(int sourceNode)423 private Node getDOMNodeFromDTM(int sourceNode) { 424 org.apache.xml.dtm.DTM dtm = m_transformer.getXPathContext().getDTM(sourceNode); 425 final Node source = (dtm == null) ? null : dtm.getNode(sourceNode); 426 return source; 427 } 428 } 429