blob: dbb5ad3152ad91991312ce1a98b7736db32026e7 [file] [log] [blame]
package org.intellij.plugins.xsltDebugger.rt.engine.local.xalan;
import org.apache.xalan.trace.GenerateEvent;
import org.apache.xalan.trace.PrintTraceListener;
import org.apache.xalan.trace.TracerEvent;
import org.apache.xalan.transformer.TransformerImpl;
import org.apache.xml.dtm.DTM;
import org.apache.xml.dtm.DTMIterator;
import org.apache.xml.serializer.SerializationHandler;
import org.apache.xml.serializer.SerializerTrace;
import org.intellij.plugins.xsltDebugger.rt.engine.Debugger;
import org.intellij.plugins.xsltDebugger.rt.engine.local.AbstractFrame;
import org.intellij.plugins.xsltDebugger.rt.engine.local.LocalDebugger;
import javax.xml.transform.SourceLocator;
import java.io.PrintWriter;
/*
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 09.01.2009
*/
public class XalanTraceListener extends PrintTraceListener {
private final LocalDebugger myDebugger;
private final TransformerImpl myTransformer;
private volatile boolean myTracing = false;
private boolean firstTrace = true;
public XalanTraceListener(LocalDebugger localDebugger, TransformerImpl tr) {
super(new PrintWriter(System.out, true));
m_traceElements = false;
m_traceGeneration = false;
m_traceSelection = false;
myDebugger = localDebugger;
myTransformer = tr;
}
@Override
public void trace(TracerEvent ev) {
if (myTracing) return;
myTracing = true; // prevents handling of recursive trace() events
try {
// init
if (firstTrace) {
firstTrace = false;
final SerializationHandler handler = myTransformer.getSerializationHandler();
myTransformer.setSerializationHandler(new TracingSerializationHandler(myDebugger, handler));
}
super.trace(ev);
final DTMIterator iterator = myTransformer.getContextNodeList();
final int node = myTransformer.getMatchedNode();
final Debugger.SourceFrame sourceFrame = myDebugger.getSourceFrame();
final boolean withSource;
if (sourceFrame == null || ((MySourceFrame)sourceFrame).getMatchedNode() != node) {
myDebugger.pushSource(new MySourceFrame(sourceFrame, iterator.getDTM(node), node));
withSource = true;
} else {
withSource = false;
}
myDebugger.enter(new XalanStyleFrame(ev, myDebugger.getCurrentFrame(), withSource));
} finally {
myTracing = false;
}
}
@Override
public void traceEnd(TracerEvent ev) {
if (myTracing) return;
if (myDebugger.getCurrentFrame() == null) {
return;
}
// xsl:choose (and maybe others) don't generate traceEnd()-events
final String instr = XalanStyleFrame.getInstruction(ev.m_styleNode);
if (instr != null) {
while (!instr.equals(myDebugger.getCurrentFrame().getInstruction())) {
leave();
}
}
super.traceEnd(ev);
leave();
}
private void leave() {
if (((XalanStyleFrame)myDebugger.getCurrentFrame()).isWithSourceFrame()) {
myDebugger.popSource();
}
myDebugger.leave();
}
@Override
public void generated(GenerateEvent ev) {
if (!(myTransformer.getSerializationHandler() instanceof TracingSerializationHandler)) {
// internal RTF evaluation, don't care
return;
}
switch (ev.m_eventtype) {
case SerializerTrace.EVENTTYPE_STARTDOCUMENT:
myDebugger.getEventQueue().startDocument();
break;
case SerializerTrace.EVENTTYPE_ENDDOCUMENT:
myDebugger.getEventQueue().endDocument();
break;
case SerializerTrace.EVENTTYPE_ENDELEMENT:
myDebugger.getEventQueue().endElement();
break;
case SerializerTrace.EVENTTYPE_CDATA:
case SerializerTrace.EVENTTYPE_CHARACTERS:
myDebugger.getEventQueue().characters(new String(ev.m_characters, ev.m_start, ev.m_length));
break;
case SerializerTrace.EVENTTYPE_COMMENT:
myDebugger.getEventQueue().comment(ev.m_data);
break;
case SerializerTrace.EVENTTYPE_PI:
myDebugger.getEventQueue().pi(ev.m_name, ev.m_data);
break;
}
}
private static class MySourceFrame extends AbstractFrame<Debugger.SourceFrame> implements Debugger.SourceFrame {
private final String mySystemId;
private final int myLineNumber;
private final int myMatchedNode;
private String myPath;
public MySourceFrame(Debugger.SourceFrame sourceFrame, DTM dtm, int node) {
super(sourceFrame);
final SourceLocator loc = dtm.getSourceLocatorFor(node);
mySystemId = loc.getSystemId();
myLineNumber = loc.getLineNumber();
myPath = XalanSupport.getPath(dtm, node);
myMatchedNode = node;
}
public String getXPath() {
return myPath;
}
public String getURI() {
return mySystemId;
}
public int getLineNumber() {
return myLineNumber;
}
public int getMatchedNode() {
return myMatchedNode;
}
}
}