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 }