/* * Copyright 2007 Sascha Weinreuter * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.intellij.plugins.xsltDebugger.rt.engine.local.saxon; import com.icl.saxon.Context; import com.icl.saxon.Controller; import com.icl.saxon.Mode; import com.icl.saxon.NodeHandler; import com.icl.saxon.om.NamePool; import com.icl.saxon.om.Navigator; import com.icl.saxon.om.NodeInfo; import com.icl.saxon.output.Emitter; import com.icl.saxon.output.GeneralOutputter; import com.icl.saxon.style.StyleElement; import com.icl.saxon.trace.TraceListener; import org.intellij.plugins.xsltDebugger.rt.engine.local.LocalDebugger; import org.intellij.plugins.xsltDebugger.rt.engine.local.OutputEventQueueImpl; import javax.xml.transform.OutputKeys; import javax.xml.transform.TransformerException; import java.lang.reflect.Field; import java.util.Properties; /** * A Simple trace listener that writes messages to System.err */ public class SaxonTraceListener implements TraceListener { private static final boolean TRACE = "true".equals(System.getProperty("xslt.debugger.trace", "false")); private String indent = ""; private final LocalDebugger myDebugger; private final Controller myController; private boolean myIsInitialized; public SaxonTraceListener(LocalDebugger debugger, Controller controller) { myDebugger = debugger; myController = controller; } /** * Called at start */ public void open() { myDebugger.getEventQueue().startDocument(); if (TRACE) { trace("<trace>"); } } private static void trace(String s) { if (TRACE) { System.err.println(s); } } /** * Called at end */ public void close() { myDebugger.getEventQueue().endDocument(); // myDebugger.stopped(); if (TRACE) { trace("</trace>"); } } /** * Called for all top level elements */ public void toplevel(NodeInfo element) { if (!myIsInitialized) { myIsInitialized = true; final Properties properties = myController.getOutputProperties(); final String method = properties.getProperty(OutputKeys.METHOD); if (method == null || "xml".equals(method) || "html".equals(method)) { try { final Emitter emitter = myController.getOutputter().getEmitter(); final GeneralOutputter outputter = new TracingOutputter(emitter, myController.getNamePool()); final Field fOutputter = Controller.class.getDeclaredField("currentOutputter"); fOutputter.setAccessible(true); fOutputter.set(myController, outputter); } catch (Exception e1) { System.err.println("Failed to change output emitter"); e1.printStackTrace(); } } } if (TRACE) { StyleElement e = (StyleElement)element; trace("<Top-level element=\"" + e.getDisplayName() + "\" line=\"" + e.getLineNumber() + "\" file=\"" + e.getSystemId() + "\" precedence=\"" + e.getPrecedence() + "\"/>"); } } /** * Called when a node of the source tree gets processed */ public void enterSource(NodeHandler handler, Context context) { NodeInfo curr = context.getContextNodeInfo(); final String path = Navigator.getPath(curr); if (TRACE) { trace(indent + "<Source node=\"" + path + "\" line=\"" + curr.getLineNumber() + "\" mode=\"" + getModeName(context) + "\">"); indent += " "; } myDebugger.pushSource(new SaxonSourceFrame(myDebugger.getSourceFrame(), curr)); } /** * Called after a node of the source tree got processed */ public void leaveSource(NodeHandler handler, Context context) { if (TRACE) { indent = indent.substring(0, indent.length() - 1); trace(indent + "</Source><!-- " + Navigator.getPath(context.getContextNodeInfo()) + " -->"); } myDebugger.popSource(); } /** * Called when an element of the stylesheet gets processed */ public void enter(NodeInfo element, Context context) { if (element.getNodeType() == NodeInfo.ELEMENT) { if (TRACE) { trace(indent + "<Instruction element=\"" + element.getDisplayName() + "\" line=\"" + element.getLineNumber() + "\">"); indent += " "; } myDebugger.enter(new SaxonFrameImpl(myDebugger.getCurrentFrame(), context, (StyleElement)element)); } } /** * Called after an element of the stylesheet got processed */ public void leave(NodeInfo element, Context context) { if (element.getNodeType() == NodeInfo.ELEMENT) { // final int lineNumber = element.getLineNumber(); // final String uri = element.getSystemId(); myDebugger.leave(); if (TRACE) { indent = indent.substring(0, indent.length() - 1); trace(indent + "</Instruction> <!-- " + element.getDisplayName() + " -->"); } } } static String getModeName(Context context) { Mode mode = context.getMode(); if (mode == null) return "#none"; int nameCode = mode.getNameCode(); if (nameCode == -1) { return "#default"; } else { return context.getController().getNamePool().getDisplayName(nameCode); } } private final class TracingOutputter extends GeneralOutputter { private final NamePool myNamePool; private final OutputEventQueueImpl myEventQueue; public TracingOutputter(Emitter emitter, NamePool namePool) { super(namePool); this.emitter = emitter; myNamePool = namePool; myEventQueue = myDebugger.getEventQueue(); } public void writeAttribute(int nameCode, String value, boolean noEscape) throws TransformerException { if (myEventQueue.isEnabled()) { final String localName = myNamePool.getLocalName(nameCode); final String prefix = myNamePool.getPrefix(nameCode); myEventQueue.attribute(prefix, localName, myNamePool.getURI(nameCode), value); } super.writeAttribute(nameCode, value, noEscape); } public void writeComment(String comment) throws TransformerException { myEventQueue.comment(comment); super.writeComment(comment); } public void writeContent(char[] chars, int start, int length) throws TransformerException { myEventQueue.characters(new String(chars, start, length)); super.writeContent(chars, start, length); } public void writeContent(StringBuffer chars, int start, int len) throws TransformerException { myEventQueue.characters(chars.substring(start, start + len)); super.writeContent(chars, start, len); } public void writeEndTag(int nameCode) throws TransformerException { myEventQueue.endElement(); super.writeEndTag(nameCode); } public void writePI(String target, String data) throws TransformerException { myEventQueue.pi(target, data); super.writePI(target, data); } public void writeStartTag(int nameCode) throws TransformerException { if (myEventQueue.isEnabled()) { final String localName = myNamePool.getLocalName(nameCode); final String prefix = myNamePool.getPrefix(nameCode); myEventQueue.startElement(prefix, localName, myNamePool.getURI(nameCode)); } super.writeStartTag(nameCode); } } }