mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-13 21:55:01 +07:00
xslt debugger initial commit
This commit is contained in:
Generated
+2
@@ -100,6 +100,8 @@
|
||||
<module fileurl="file://$PROJECT_DIR$/xml/openapi/xml-openapi.iml" filepath="$PROJECT_DIR$/xml/openapi/xml-openapi.iml" group="xml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/xpath/xpath.iml" filepath="$PROJECT_DIR$/plugins/xpath/xpath.iml" group="plugins" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/xpath/xslt-rt/xslt-rt.iml" filepath="$PROJECT_DIR$/plugins/xpath/xslt-rt/xslt-rt.iml" group="plugins" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/xslt-debugger/xslt-debugger.iml" filepath="$PROJECT_DIR$/plugins/xslt-debugger/xslt-debugger.iml" group="plugins" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/xslt-debugger/rt/xslt-debugger-rt.iml" filepath="$PROJECT_DIR$/plugins/xslt-debugger/rt/xslt-debugger-rt.iml" group="plugins" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
|
||||
@@ -77,6 +77,7 @@
|
||||
<orderEntry type="module" module-name="IntelliLang-javaee" />
|
||||
<orderEntry type="module" module-name="IntelliLang-xml" />
|
||||
<orderEntry type="module" module-name="xpath" />
|
||||
<orderEntry type="module" module-name="xslt-debugger" />
|
||||
<orderEntry type="module" module-name="tasks-core" />
|
||||
<orderEntry type="module" module-name="jira-connector" />
|
||||
<orderEntry type="module" module-name="tasks-api" />
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
#idea.home=C:\\Programme\\IntelliJ Selena
|
||||
idea.home=C:\\work\\Programme\\IntelliJ 10
|
||||
idea.plugins.home=${idea.home}/plugins
|
||||
|
||||
xpathview.src.home=../xpath
|
||||
|
||||
compile.debug=true
|
||||
compile.optimize=true
|
||||
@@ -0,0 +1,198 @@
|
||||
<project default="rebuild" name="xslt-debugger">
|
||||
|
||||
<property file="build.properties"/>
|
||||
|
||||
<dirname file="${ant.file}" property="project.dir"/>
|
||||
<property name="src.dir" value="${project.dir}/src"/>
|
||||
<property name="src.rt.dir" value="${project.dir}/rt/src"/>
|
||||
|
||||
<property name="build.dir" value="${basedir}/build"/>
|
||||
<property name="build.classes.dir" value="${build.dir}/classes"/>
|
||||
<property name="build.classes.rt.dir" value="${build.dir}/rt/classes"/>
|
||||
|
||||
<path id="classpath.uidesigner">
|
||||
<fileset dir="${idea.home}">
|
||||
<include name="lib/*.jar"/>
|
||||
<include name="redist/*.jar"/>
|
||||
</fileset>
|
||||
</path>
|
||||
|
||||
<taskdef name="javac2" classname="com.intellij.ant.Javac2">
|
||||
<classpath refid="classpath.uidesigner"/>
|
||||
</taskdef>
|
||||
<taskdef name="jflex" classname="JFlex.anttask.JFlexTask">
|
||||
<classpath location="${idea.home}/tools/jflex/lib/JFlex.jar"/>
|
||||
</taskdef>
|
||||
|
||||
<path id="idea.classpath">
|
||||
<fileset dir="${idea.home}">
|
||||
<include name="lib/*.jar"/>
|
||||
<include name="redist/*.jar"/>
|
||||
</fileset>
|
||||
</path>
|
||||
|
||||
<path id="rt.classpath">
|
||||
<fileset dir="${idea.home}/lib">
|
||||
<include name="trove4j.jar" />
|
||||
</fileset>
|
||||
<fileset dir="rt/lib">
|
||||
<include name="*.jar"/>
|
||||
</fileset>
|
||||
</path>
|
||||
|
||||
<property name="xpathview.plugin.home" value="${idea.plugins.home}/xpath"/>
|
||||
|
||||
<target name="init">
|
||||
<condition property="xpathview.src.available">
|
||||
<available file="${xpathview.src.home}/build.xml"/>
|
||||
</condition>
|
||||
</target>
|
||||
|
||||
<target name="xpathview.compile" depends="init" if="xpathview.src.available">
|
||||
<echo message="Building XPathView from source: ${xpathview.src.home}"/>
|
||||
|
||||
<property name="build.xpathview.dir" value="${build.dir}/xpathview"/>
|
||||
<mkdir dir="${build.xpathview.dir}"/>
|
||||
|
||||
<ant dir="${xpathview.src.home}" target="jar">
|
||||
<property name="build.dir" value="${build.xpathview.dir}"/>
|
||||
</ant>
|
||||
|
||||
<path id="xpathview.classpath">
|
||||
<fileset dir="${build.xpathview.dir}">
|
||||
<include name="xpath-lang/*.jar"/>
|
||||
<include name="*.jar"/>
|
||||
</fileset>
|
||||
</path>
|
||||
<path id="xpathview.rt.classpath">
|
||||
<fileset dir="${build.xpathview.dir}">
|
||||
<include name="xpath-lang/xslt-rt/*.jar"/>
|
||||
</fileset>
|
||||
</path>
|
||||
</target>
|
||||
|
||||
<target name="xpathview.binary" depends="init" unless="xpathview.src.available">
|
||||
<available file="${xpathview.plugin.home}/lib/xpath.jar" property="xpathview.binary.available"/>
|
||||
<available file="${xpathview.plugin.home}/lib/xpath-view.jar" property="xpathview.binary.available"/>
|
||||
<fail unless="xpathview.binary.available">
|
||||
The XPathView plugin is required to build the XSLT-Debugger. Please set the property "xpathview.plugin.home" to
|
||||
point to the installation of the plugin in IntelliJ IDEA.
|
||||
</fail>
|
||||
|
||||
<path id="xpathview.classpath">
|
||||
<fileset dir="${xpathview.plugin.home}">
|
||||
<include name="lib/*.jar"/>
|
||||
</fileset>
|
||||
</path>
|
||||
<path id="xpathview.rt.classpath">
|
||||
<fileset dir="${xpathview.plugin.home}">
|
||||
<include name="lib/rt/*.jar"/>
|
||||
</fileset>
|
||||
</path>
|
||||
</target>
|
||||
|
||||
<target name="compile" depends="init, xpathview.compile, xpathview.binary">
|
||||
<mkdir dir="${build.classes.dir}"/>
|
||||
<mkdir dir="${build.classes.rt.dir}"/>
|
||||
|
||||
<javac2 srcdir="${src.rt.dir}" destdir="${build.classes.rt.dir}" source="1.5" target="1.5" debug="${compile.debug}"
|
||||
optimize="${compile.optimize}">
|
||||
<classpath refid="rt.classpath"/>
|
||||
<classpath refid="xpathview.rt.classpath"/>
|
||||
<exclude name="com/**/*"/>
|
||||
</javac2>
|
||||
|
||||
<javac2 srcdir="${src.dir}" destdir="${build.classes.dir}" source="1.5" target="1.5" debug="${compile.debug}"
|
||||
optimize="${compile.optimize}">
|
||||
<classpath refid="idea.classpath"/>
|
||||
<classpath refid="xpathview.classpath"/>
|
||||
<classpath location="${build.classes.rt.dir}"/>
|
||||
<exclude name="com/**/*"/>
|
||||
<exclude name="Main.java"/>
|
||||
</javac2>
|
||||
|
||||
<rmic base="${build.classes.rt.dir}">
|
||||
<include name="**/remote/Remote*Impl.class"/>
|
||||
<include name="**/remote/DebuggerServer.class"/>
|
||||
</rmic>
|
||||
|
||||
<jar destfile="${build.dir}/rmi-stubs.jar">
|
||||
<fileset dir="${build.classes.rt.dir}">
|
||||
<include name="**/remote/Remote*Impl_*.class"/>
|
||||
<include name="**/remote/DebuggerServer_*.class"/>
|
||||
</fileset>
|
||||
</jar>
|
||||
</target>
|
||||
|
||||
<target name="build" depends="compile" description="Build project"/>
|
||||
|
||||
<target name="jar" depends="build">
|
||||
<jar file="${build.dir}/xslt-debugger.jar" compress="false">
|
||||
<zipfileset dir="${build.classes.dir}">
|
||||
<include name="**/*"/>
|
||||
</zipfileset>
|
||||
<zipfileset dir=".">
|
||||
<include name="META-INF/*.xml"/>
|
||||
</zipfileset>
|
||||
<zipfileset dir="${src.dir}">
|
||||
<include name="**/*.xml"/>
|
||||
<include name="**/*.png"/>
|
||||
</zipfileset>
|
||||
</jar>
|
||||
|
||||
<mkdir dir="${build.dir}/rt"/>
|
||||
<jar file="${build.dir}/xslt-debugger-engine.jar" compress="false">
|
||||
<zipfileset dir="${build.classes.rt.dir}">
|
||||
<include name="**/*"/>
|
||||
</zipfileset>
|
||||
<zipfileset dir="${src.rt.dir}">
|
||||
<include name="**/*.xml"/>
|
||||
<include name="**/*.png"/>
|
||||
</zipfileset>
|
||||
</jar>
|
||||
</target>
|
||||
|
||||
<target name="rebuild" depends="clean, jar" description="Clean and rebuild"/>
|
||||
|
||||
<target name="clean">
|
||||
<delete dir="build"/>
|
||||
</target>
|
||||
|
||||
<target name="dist" depends="rebuild" description="Build distribution ZIP">
|
||||
<mkdir dir="dist"/>
|
||||
<zip file="dist/xslt-debugger.zip">
|
||||
<zipfileset dir="build" prefix="xslt-debugger/lib">
|
||||
<include name="*.jar"/>
|
||||
</zipfileset>
|
||||
<zipfileset dir="rt/lib" prefix="xslt-debugger/lib/rt">
|
||||
<include name="saxon*"/>
|
||||
<include name="xalan.jar"/>
|
||||
<include name="serializer.jar"/>
|
||||
</zipfileset>
|
||||
<zipfileset dir="doc" prefix="xslt-debugger/help">
|
||||
<include name="help.jar"/>
|
||||
</zipfileset>
|
||||
<zipfileset dir="." prefix="xslt-debugger">
|
||||
<include name="LICENSE"/>
|
||||
</zipfileset>
|
||||
</zip>
|
||||
<zip file="dist/xslt-debugger_src.zip">
|
||||
<zipfileset dir="." prefix="xslt-debugger">
|
||||
<include name="src/**/*"/>
|
||||
<include name="rt/src/**/*"/>
|
||||
|
||||
<include name="rt/*.iml"/>
|
||||
<include name="*.iml"/>
|
||||
<include name="*.ipr"/>
|
||||
|
||||
<include name="META-INF/*.xml"/>
|
||||
|
||||
<include name="build.xml"/>
|
||||
<include name="build.properties"/>
|
||||
|
||||
<include name="LICENSE"/>
|
||||
<include name="readme-project.txt"/>
|
||||
</zipfileset>
|
||||
</zip>
|
||||
</target>
|
||||
</project>
|
||||
Binary file not shown.
@@ -0,0 +1,148 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>SAXON: Conditions of Use</title>
|
||||
|
||||
</head>
|
||||
|
||||
<body leftmargin="150" bgcolor="#ddeeff"><font face="Arial, Helvetica, sans-serif">
|
||||
<div align=right><a href="index.html">SAXON home page</a></div>
|
||||
<h1><big><font color="#FF0080">SAXON: Conditions of Use</font></big></h1>
|
||||
|
||||
|
||||
<h2>Saxon</h2>
|
||||
|
||||
<p>The contents of the downloaded file (saxon.zip), with the exception of the
|
||||
Ælfred parser (see below),
|
||||
are subject to the Mozilla Public License Version 1.0
|
||||
(the "License"); you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
<a href="http://www.mozilla.org/MPL/">http://www.mozilla.org/MPL/</a></p>
|
||||
|
||||
<p>Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing rights and limitations under the License.
|
||||
|
||||
<p>
|
||||
|
||||
<p>The Original Code of SAXON comprises all those components which are not explicitly attributed
|
||||
to other parties. It does not include the Ælfred parser, which is redistributed under
|
||||
the licence described below.</p>
|
||||
|
||||
<p>The Initial Developer of the Original Code was Michael Kay.
|
||||
Individual modules identified as being created by James Clark, David Megginson, or John Cowan include
|
||||
separate IPR notices. All Rights Reserved.</p>
|
||||
|
||||
<p>
|
||||
<small><i>Until January 2001 Michael Kay worked for International Computers Limited (ICL, now part
|
||||
of Fujitsu), and from February 2001 to January 2004 he worked for Software AG. These two companies
|
||||
both sponsored the development of Saxon and authorised its release under this license, but are not
|
||||
themselves parties to the license. Michael Kay now runs his own company, Saxonica, which has taken
|
||||
over all responsibility for Saxon development and support.</i></small>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<small><i>For reasons of continuity,
|
||||
the icl.com domain name is retained in package names and namespace URIs with the tacit
|
||||
consent of ICL, but this should not be taken to imply any ongoing ICL involvement.</small>
|
||||
</i></p>
|
||||
|
||||
<p>If you produce a product that includes or requires SAXON, please refer to it as
|
||||
"The SAXON XSLT Processor from Michael Kay", and include the URL of the
|
||||
home page, which is at
|
||||
<a HREF="http://saxon.sourceforge.net/">http://saxon.sourceforge.net/</a>.</p>
|
||||
|
||||
<p>There is no guarantee of technical support, though I am usually able to answer enquiries
|
||||
within a few days. Please subscribe to the mailing list available at
|
||||
<a href="http://lists.sourceforge.net/lists/listinfo/saxon-help"/>
|
||||
http://lists.sourceforge.net/lists/listinfo/saxon-help</a> and raise any enquiries there.
|
||||
Also check the Saxon project pages on sourceforge for details of known errors; all bugs are
|
||||
listed there as soon as I have sufficient evidence to describe the nature of the problem.</p>
|
||||
<hr>
|
||||
|
||||
<h2>Ælfred</h2>
|
||||
|
||||
<p>Included in the Saxon distribution is a modified version of the Ælfred XML parser
|
||||
originally developed by David Megginson at Microstar (no longer in existence).
|
||||
I have taken the relevant part of
|
||||
<A href="mailto:david-b@pacbell.net">David Brownell</a>'s
|
||||
<a href="http://home.pacbell.net/david-b/xml/">Ælfred2</a> distribution, repackaged it,
|
||||
and fixed a few bugs. All changes are clearly documented in the source code.</p>
|
||||
|
||||
<p>This is distributed under the terms of Microstar's terms and conditions, which are as follows:</p>
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td width=100></td>
|
||||
<td>
|
||||
<p>AElfred, Version 1.2<br>
|
||||
Microstar's Java-Based XML Parser<br>
|
||||
Copyright (c) 1997, 1998 by Microstar Software Ltd.<br>
|
||||
Home Page: http://www.microstar.com/XML/</p>
|
||||
|
||||
<p>AElfred is free for both commercial and non-commercial use and
|
||||
redistribution, provided that Microstar's copyright and disclaimer are
|
||||
retained intact. You are free to modify AElfred for your own use and
|
||||
to redistribute AElfred with your modifications, provided that the
|
||||
modifications are clearly documented.</p>
|
||||
|
||||
|
||||
<p><u>DISCLAIMER</u></p>
|
||||
|
||||
|
||||
<p>This program is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
merchantability or fitness for a particular purpose. Please use it AT
|
||||
YOUR OWN RISK.</p>
|
||||
|
||||
|
||||
</td>
|
||||
<td width=100></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p>David Brownell added the following statement: </p>
|
||||
<code><pre>
|
||||
|
||||
/*
|
||||
* Copyright (c) 1999-2000 by David Brownell. All Rights Reserved.
|
||||
*
|
||||
* This program is open source software; you may use, copy, modify, and
|
||||
* redistribute it under the terms of the LICENSE with which it was
|
||||
* originally distributed.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* LICENSE for more details.
|
||||
*/
|
||||
</pre>
|
||||
</code>
|
||||
|
||||
<p>The version included with Saxon is David Brownell's code of 26 Feb 2000,
|
||||
modified as follows:</p>
|
||||
|
||||
<ul>
|
||||
<li>Changed the package name to com.icl.saxon.aelfred to prevent any accidental confusion with the
|
||||
original Microstar code or with David Brownell's version.
|
||||
</li>
|
||||
<li>Fixed several bugs: (1) a bug in namespace handling (where an attribute xxx:name precedes the xmlns:xxx
|
||||
declaration) (2) poor diagnostics when end of file occurs prematurely
|
||||
</li>
|
||||
<li>Subsetting the code to include only the XML non-validating parser and SAX driver, with appropriate
|
||||
changes to the setFeature() and getFeature() methods.
|
||||
</li>
|
||||
<li>Some further changes made by David Brownell up to June 2001 have been incorporated.</li>
|
||||
</ul>
|
||||
|
||||
<hr>
|
||||
|
||||
<p align="center">Michael H. Kay<br>
|
||||
<a href="http://www.saxonica.com/">Saxonica Limited</a><br>
|
||||
22 June 2005</p>
|
||||
|
||||
|
||||
</font>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+58
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 2002-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;
|
||||
|
||||
import org.intellij.plugins.xslt.run.rt.XSLTMain;
|
||||
import org.intellij.plugins.xslt.run.rt.XSLTRunner;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.local.saxon.SaxonSupport;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.local.saxon9.Saxon9Support;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.local.xalan.XalanSupport;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.remote.DebuggerServer;
|
||||
|
||||
import javax.xml.transform.*;
|
||||
import java.rmi.RemoteException;
|
||||
|
||||
|
||||
/*
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: sweinreuter
|
||||
* Date: 23.11.2007
|
||||
*/
|
||||
public class XSLTDebuggerMain implements XSLTMain {
|
||||
|
||||
public TransformerFactory createTransformerFactory() throws ClassNotFoundException, InstantiationException, IllegalAccessException {
|
||||
final String type = System.getProperty("xslt.transformer.type");
|
||||
if ("xalan".equalsIgnoreCase(type)) {
|
||||
return XalanSupport.createTransformerFactory();
|
||||
} else if ("saxon".equalsIgnoreCase(type)) {
|
||||
return SaxonSupport.createTransformerFactory();
|
||||
} else if ("saxon9".equalsIgnoreCase(type)) {
|
||||
return Saxon9Support.createTransformerFactory();
|
||||
} else if (type != null) {
|
||||
throw new UnsupportedOperationException("Unsupported Transformer type '" + type + "'");
|
||||
}
|
||||
return XalanSupport.prepareFactory(XSLTRunner.createTransformerFactoryStatic());
|
||||
}
|
||||
|
||||
public void start(Transformer transformer, Source source, Result result) throws TransformerException {
|
||||
try {
|
||||
DebuggerServer.create(transformer, source, result, Integer.getInteger("xslt.debugger.port"));
|
||||
} catch (RemoteException e) {
|
||||
throw new TransformerException(e.getMessage(), e.getCause());
|
||||
}
|
||||
}
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: sweinreuter
|
||||
* Date: 29.05.2007
|
||||
*/
|
||||
public interface Breakpoint {
|
||||
String getUri();
|
||||
|
||||
int getLine();
|
||||
|
||||
boolean isEnabled();
|
||||
|
||||
void setEnabled(boolean enabled);
|
||||
|
||||
String getCondition();
|
||||
|
||||
void setCondition(String expr);
|
||||
|
||||
String getLogMessage();
|
||||
|
||||
void setLogMessage(String expr);
|
||||
|
||||
String getTraceMessage();
|
||||
|
||||
void setTraceMessage(String expr);
|
||||
|
||||
boolean isSuspend();
|
||||
|
||||
void setSuspend(boolean suspend);
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: sweinreuter
|
||||
* Date: 23.05.2007
|
||||
*/
|
||||
public interface BreakpointManager {
|
||||
Breakpoint setBreakpoint(File file, int line);
|
||||
|
||||
Breakpoint setBreakpoint(String uri, int line);
|
||||
|
||||
void removeBreakpoint(Breakpoint bp);
|
||||
|
||||
void removeBreakpoint(String uri, int line);
|
||||
|
||||
List<Breakpoint> getBreakpoints();
|
||||
|
||||
Breakpoint getBreakpoint(String uri, int lineNumber);
|
||||
}
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: sweinreuter
|
||||
* Date: 23.05.2007
|
||||
*/
|
||||
public interface Debugger extends Watchable {
|
||||
enum State {
|
||||
CREATED, RUNNING, SUSPENDED, STOPPED
|
||||
}
|
||||
|
||||
State getState();
|
||||
|
||||
boolean start();
|
||||
|
||||
void stop(boolean force);
|
||||
|
||||
void step();
|
||||
|
||||
void stepInto();
|
||||
|
||||
void resume();
|
||||
|
||||
void pause();
|
||||
|
||||
boolean isStopped();
|
||||
|
||||
StyleFrame getCurrentFrame();
|
||||
|
||||
SourceFrame getSourceFrame();
|
||||
|
||||
Value eval(String expr) throws EvaluationException;
|
||||
|
||||
List<Variable> getGlobalVariables();
|
||||
|
||||
BreakpointManager getBreakpointManager();
|
||||
|
||||
OutputEventQueue getEventQueue();
|
||||
|
||||
boolean waitForDebuggee();
|
||||
|
||||
State waitForStateChange(State state);
|
||||
|
||||
interface Locatable {
|
||||
String getURI();
|
||||
|
||||
int getLineNumber();
|
||||
}
|
||||
|
||||
interface Frame<T extends Frame> extends Locatable {
|
||||
T getNext();
|
||||
|
||||
T getPrevious();
|
||||
}
|
||||
|
||||
interface StyleFrame extends Frame<StyleFrame> {
|
||||
String getInstruction();
|
||||
|
||||
Value eval(String expr) throws EvaluationException;
|
||||
|
||||
List<Variable> getVariables();
|
||||
}
|
||||
|
||||
interface SourceFrame extends Frame<SourceFrame> {
|
||||
String getXPath();
|
||||
}
|
||||
|
||||
interface Variable extends Locatable {
|
||||
enum Kind {VARIABLE, PARAMETER, EXPRESSION}
|
||||
|
||||
boolean isGlobal();
|
||||
|
||||
Kind getKind();
|
||||
|
||||
String getName();
|
||||
|
||||
Value getValue();
|
||||
}
|
||||
|
||||
class EvaluationException extends Exception {
|
||||
public EvaluationException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: sweinreuter
|
||||
* Date: 24.05.2007
|
||||
*/
|
||||
public class DebuggerStoppedException extends RuntimeException {
|
||||
}
|
||||
+116
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright 2002-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;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: sweinreuter
|
||||
* Date: 08.06.2007
|
||||
*/
|
||||
public interface OutputEventQueue {
|
||||
int START_DOCUMENT = 0;
|
||||
int END_DOCUMENT = 99;
|
||||
int START_ELEMENT = 1;
|
||||
int END_ELEMENT = 2;
|
||||
int ATTRIBUTE = 3;
|
||||
int CHARACTERS = 4;
|
||||
int COMMENT = 5;
|
||||
int PI = 6;
|
||||
|
||||
int TRACE_POINT = 20;
|
||||
|
||||
void setEnabled(boolean b);
|
||||
|
||||
List<NodeEvent> getEvents();
|
||||
|
||||
final class NodeEvent implements Serializable {
|
||||
public static final class QName implements Serializable {
|
||||
public String myPrefix;
|
||||
public String myLocalName;
|
||||
public String myURI;
|
||||
|
||||
public QName(String prefix, String localName, String URI) {
|
||||
myPrefix = prefix;
|
||||
myLocalName = localName;
|
||||
myURI = URI;
|
||||
}
|
||||
|
||||
public QName(String qName, String uri) {
|
||||
myURI = uri;
|
||||
final String[] parts = qName.split(":");
|
||||
if (parts.length == 2) {
|
||||
myPrefix = parts[0];
|
||||
myLocalName = parts[1];
|
||||
} else {
|
||||
myPrefix = null;
|
||||
myLocalName = parts[0];
|
||||
}
|
||||
}
|
||||
|
||||
public QName(String name) {
|
||||
myLocalName = name;
|
||||
myPrefix = null;
|
||||
myURI = null;
|
||||
}
|
||||
|
||||
public String getQName() {
|
||||
return myPrefix != null && myPrefix.length() > 0 ? myPrefix + ":" + myLocalName : myLocalName;
|
||||
}
|
||||
}
|
||||
|
||||
private final int myType;
|
||||
|
||||
public String myValue;
|
||||
public QName myQName;
|
||||
public String myURI;
|
||||
private int myLineNumber;
|
||||
|
||||
public NodeEvent(int type, QName qName, String value) {
|
||||
myType = type;
|
||||
myQName = qName;
|
||||
myValue = value;
|
||||
}
|
||||
|
||||
public int getType() {
|
||||
return myType;
|
||||
}
|
||||
|
||||
public QName getQName() {
|
||||
return myQName;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return myValue;
|
||||
}
|
||||
|
||||
public void setLocation(String uri, int lineNumber) {
|
||||
myURI = uri;
|
||||
myLineNumber = lineNumber;
|
||||
}
|
||||
|
||||
public int getLineNumber() {
|
||||
return myLineNumber;
|
||||
}
|
||||
|
||||
public String getURI() {
|
||||
return myURI;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: sweinreuter
|
||||
* Date: 31.05.2007
|
||||
*/
|
||||
public interface Value extends Serializable {
|
||||
interface Type extends Serializable {
|
||||
String getName();
|
||||
}
|
||||
|
||||
enum XPathType implements Type {
|
||||
BOOLEAN, NUMBER, STRING, NODESET, OBJECT, UNKNOWN;
|
||||
|
||||
public String getName() {
|
||||
return name().toLowerCase();
|
||||
}
|
||||
}
|
||||
|
||||
final class ObjectType implements Type {
|
||||
private final String myName;
|
||||
|
||||
public ObjectType(String name) {
|
||||
myName = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return myName;
|
||||
}
|
||||
}
|
||||
|
||||
Object getValue();
|
||||
|
||||
Type getType();
|
||||
|
||||
class NodeSet implements Serializable {
|
||||
public final String myStringValue;
|
||||
private final List<Node> myNodes;
|
||||
|
||||
public NodeSet(String stringValue, List<Node> nodes) {
|
||||
myStringValue = stringValue;
|
||||
myNodes = nodes;
|
||||
}
|
||||
|
||||
public List<Node> getNodes() {
|
||||
return myNodes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return myStringValue;
|
||||
}
|
||||
}
|
||||
|
||||
class Node implements Serializable, Debugger.Locatable {
|
||||
public final String myURI;
|
||||
public final int myLineNumber;
|
||||
public final String myXPath;
|
||||
public final String myStringValue;
|
||||
|
||||
public Node(String URI, int lineNumber, String XPath, String stringValue) {
|
||||
myURI = URI;
|
||||
myLineNumber = lineNumber;
|
||||
myXPath = XPath;
|
||||
myStringValue = stringValue;
|
||||
}
|
||||
|
||||
public String getURI() {
|
||||
return myURI;
|
||||
}
|
||||
|
||||
public int getLineNumber() {
|
||||
return myLineNumber;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "Node{" +
|
||||
"myURI='" + myURI + '\'' +
|
||||
", myLineNumber=" + myLineNumber +
|
||||
", myXPath='" + myXPath + '\'' +
|
||||
", myStringValue='" + myStringValue + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright 2000-2011 JetBrains s.r.o.
|
||||
*
|
||||
* 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;
|
||||
|
||||
/*
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: sweinreuter
|
||||
* Date: 09.05.11
|
||||
*/
|
||||
public interface Watchable {
|
||||
boolean ping();
|
||||
}
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.Debugger.Frame;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: sweinreuter
|
||||
* Date: 02.06.2007
|
||||
*/
|
||||
public abstract class AbstractFrame<F extends Frame> implements Frame<F> {
|
||||
private final F myPrev;
|
||||
private F myNext;
|
||||
|
||||
private boolean myValid = true;
|
||||
|
||||
public AbstractFrame(F prev) {
|
||||
myPrev = prev;
|
||||
|
||||
if (prev != null) {
|
||||
((AbstractFrame)prev).myNext = this;
|
||||
}
|
||||
}
|
||||
|
||||
public void invalidate() {
|
||||
assert myValid;
|
||||
assert myNext == null;
|
||||
if (myPrev != null) {
|
||||
((AbstractFrame)myPrev).myNext = null;
|
||||
}
|
||||
myValid = false;
|
||||
}
|
||||
|
||||
public F getNext() {
|
||||
assert myValid;
|
||||
return myNext;
|
||||
}
|
||||
|
||||
public F getPrevious() {
|
||||
assert myValid;
|
||||
return myPrev;
|
||||
}
|
||||
|
||||
public boolean isValid() {
|
||||
return myValid;
|
||||
}
|
||||
}
|
||||
+114
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.Breakpoint;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: sweinreuter
|
||||
* Date: 29.05.2007
|
||||
*/
|
||||
class BreakpointImpl implements Breakpoint {
|
||||
private final String myUri;
|
||||
private final int myLine;
|
||||
private boolean myEnabled;
|
||||
private String myCondition;
|
||||
private String myLogMsg;
|
||||
private String myTraceMsg;
|
||||
private boolean mySuspend;
|
||||
|
||||
public BreakpointImpl(String uri, int line) {
|
||||
myUri = uri;
|
||||
myLine = line;
|
||||
myEnabled = true;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean b) {
|
||||
myEnabled = b;
|
||||
}
|
||||
|
||||
public void setCondition(String expr) {
|
||||
myCondition = expr;
|
||||
}
|
||||
|
||||
public void setLogMessage(String expr) {
|
||||
myLogMsg = expr;
|
||||
}
|
||||
|
||||
public String getTraceMessage() {
|
||||
return myTraceMsg;
|
||||
}
|
||||
|
||||
public void setTraceMessage(String expr) {
|
||||
myTraceMsg = expr;
|
||||
}
|
||||
|
||||
public boolean isSuspend() {
|
||||
return mySuspend;
|
||||
}
|
||||
|
||||
public void setSuspend(boolean suspend) {
|
||||
mySuspend = suspend;
|
||||
}
|
||||
|
||||
public String getCondition() {
|
||||
return myCondition;
|
||||
}
|
||||
|
||||
public String getLogMessage() {
|
||||
return myLogMsg;
|
||||
}
|
||||
|
||||
public String getUri() {
|
||||
return myUri;
|
||||
}
|
||||
|
||||
public int getLine() {
|
||||
return myLine;
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return myEnabled;
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
final BreakpointImpl that = (BreakpointImpl)o;
|
||||
|
||||
if (myLine != that.myLine) return false;
|
||||
return myUri.equals(that.myUri);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
int result;
|
||||
result = myUri.hashCode();
|
||||
result = 31 * result + myLine;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public String toString() {
|
||||
return "Breakpoint{" +
|
||||
"myUri='" + myUri + '\'' +
|
||||
", myLine=" + myLine +
|
||||
", myEnabled=" + myEnabled +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import gnu.trove.TIntObjectHashMap;
|
||||
import gnu.trove.TIntObjectProcedure;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.Breakpoint;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.BreakpointManager;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: sweinreuter
|
||||
* Date: 19.05.2007
|
||||
*/
|
||||
public class BreakpointManagerImpl implements BreakpointManager {
|
||||
private final TIntObjectHashMap<Map<String, Breakpoint>> myBreakpoints =
|
||||
new TIntObjectHashMap<Map<String, Breakpoint>>();
|
||||
|
||||
public Breakpoint setBreakpoint(File file, int line) {
|
||||
return setBreakpoint(file.toURI().toASCIIString(), line);
|
||||
}
|
||||
|
||||
public synchronized void removeBreakpoint(String uri, int line) {
|
||||
final Map<String, Breakpoint> s = myBreakpoints.get(line);
|
||||
if (s != null) {
|
||||
s.remove(normalizeUri(uri));
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized List<Breakpoint> getBreakpoints() {
|
||||
final ArrayList<Breakpoint> breakpoints = new ArrayList<Breakpoint>();
|
||||
myBreakpoints.forEachEntry(new TIntObjectProcedure<Map<String, Breakpoint>>() {
|
||||
public boolean execute(int i, Map<String, Breakpoint> map) {
|
||||
breakpoints.addAll(map.values());
|
||||
return true;
|
||||
}
|
||||
});
|
||||
return breakpoints;
|
||||
}
|
||||
|
||||
public void removeBreakpoint(Breakpoint bp) {
|
||||
removeBreakpoint(bp.getUri(), bp.getLine());
|
||||
}
|
||||
|
||||
public synchronized Breakpoint setBreakpoint(String uri, int line) {
|
||||
assert line > 0 : "No line number for breakpoint in file " + uri;
|
||||
|
||||
uri = normalizeUri(uri);
|
||||
final Map<String, Breakpoint> s = myBreakpoints.get(line);
|
||||
final BreakpointImpl bp = new BreakpointImpl(uri, line);
|
||||
if (s == null) {
|
||||
final HashMap<String, Breakpoint> map = new HashMap<String, Breakpoint>();
|
||||
map.put(uri, bp);
|
||||
myBreakpoints.put(line, map);
|
||||
} else {
|
||||
s.put(uri, bp);
|
||||
}
|
||||
return bp;
|
||||
}
|
||||
|
||||
private static String normalizeUri(String uri) {
|
||||
// hmm, this code sucks, but seems to be a good guess to ensure the same format of
|
||||
// strings (file:/C:/... vs, file:///C:/...) on both sides...
|
||||
try {
|
||||
try {
|
||||
uri = uri.replaceAll(" ", "%20");
|
||||
return new File(new URI(uri)).toURI().toASCIIString();
|
||||
} catch (IllegalArgumentException e) {
|
||||
return new URI(uri).normalize().toASCIIString();
|
||||
}
|
||||
} catch (URISyntaxException e) {
|
||||
System.err.println("Failed to parse <" + uri + ">: " + e);
|
||||
return uri;
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized boolean isBreakpoint(String uri, int lineNumber) {
|
||||
final Breakpoint breakpoint = getBreakpoint(uri, lineNumber);
|
||||
return breakpoint != null && breakpoint.isEnabled();
|
||||
}
|
||||
|
||||
public synchronized Breakpoint getBreakpoint(String uri, int lineNumber) {
|
||||
final Map<String, Breakpoint> s = myBreakpoints.get(lineNumber);
|
||||
if (s != null) {
|
||||
return s.get(normalizeUri(uri));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+408
@@ -0,0 +1,408 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.Breakpoint;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.BreakpointManager;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.Debugger;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.DebuggerStoppedException;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.local.saxon.SaxonSupport;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.local.saxon9.Saxon9Support;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.local.xalan.XalanSupport;
|
||||
|
||||
import javax.xml.transform.Result;
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: sweinreuter
|
||||
* Date: 19.05.2007
|
||||
*/
|
||||
public class LocalDebugger implements Debugger {
|
||||
private final Thread myThread;
|
||||
|
||||
private final BreakpointManager myBreakpointManager;
|
||||
private final OutputEventQueueImpl myEventQueue;
|
||||
private volatile Condition myCurrentStopCondition;
|
||||
|
||||
private final Object theLock = new Object();
|
||||
|
||||
private volatile State myState = State.CREATED;
|
||||
|
||||
private final LinkedList<StyleFrame> myFrames = new LinkedList<StyleFrame>();
|
||||
private final LinkedList<SourceFrame> mySourceFrames = new LinkedList<SourceFrame>();
|
||||
|
||||
public LocalDebugger(final Transformer transformer, final Source source, final Result result) {
|
||||
prepareTransformer(transformer);
|
||||
|
||||
myBreakpointManager = new BreakpointManagerImpl();
|
||||
myEventQueue = new OutputEventQueueImpl(this);
|
||||
|
||||
myThread = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
synchronized (theLock) {
|
||||
myState = State.RUNNING;
|
||||
theLock.notifyAll();
|
||||
}
|
||||
transformer.transform(source, result);
|
||||
stopped();
|
||||
} catch (DebuggerStoppedException e) {
|
||||
// OK
|
||||
} catch (TransformerException e) {
|
||||
// TODO: log, pass to client
|
||||
e.printStackTrace();
|
||||
stopped();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected void prepareTransformer(Transformer transformer) {
|
||||
try {
|
||||
if (Saxon9Support.init(transformer, this)) {
|
||||
return;
|
||||
}
|
||||
} catch (NoClassDefFoundError e1) {
|
||||
// ignore
|
||||
}
|
||||
try {
|
||||
if (SaxonSupport.init(transformer, this)) {
|
||||
return;
|
||||
}
|
||||
} catch (NoClassDefFoundError e) {
|
||||
// ignore
|
||||
}
|
||||
try {
|
||||
if (XalanSupport.init(transformer, this)) {
|
||||
return;
|
||||
}
|
||||
} catch (NoClassDefFoundError e1) {
|
||||
// ignore
|
||||
}
|
||||
throw new UnsupportedOperationException("Unsupported Transformer: " + transformer.getClass().getName());
|
||||
}
|
||||
|
||||
private void suspendAndWait() throws DebuggerStoppedException {
|
||||
try {
|
||||
synchronized (theLock) {
|
||||
myCurrentStopCondition = null;
|
||||
|
||||
myState = State.SUSPENDED;
|
||||
theLock.notifyAll();
|
||||
|
||||
do {
|
||||
theLock.wait();
|
||||
}
|
||||
while (myState == State.SUSPENDED);
|
||||
|
||||
if (myState == State.STOPPED) {
|
||||
throw new DebuggerStoppedException();
|
||||
}
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
throw new DebuggerStoppedException();
|
||||
}
|
||||
}
|
||||
|
||||
public void resume() throws DebuggerStoppedException {
|
||||
synchronized (theLock) {
|
||||
if (myState == State.STOPPED) {
|
||||
throw new DebuggerStoppedException();
|
||||
} else if (myState != State.SUSPENDED) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
myState = State.RUNNING;
|
||||
theLock.notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
public void pause() {
|
||||
synchronized (theLock) {
|
||||
if (myState == State.STOPPED) {
|
||||
throw new DebuggerStoppedException();
|
||||
} else if (myState != State.RUNNING) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
myCurrentStopCondition = Condition.TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
public void stopped() {
|
||||
assert Thread.currentThread() == myThread;
|
||||
stop0();
|
||||
}
|
||||
|
||||
private void stop0() {
|
||||
synchronized (theLock) {
|
||||
myState = State.STOPPED;
|
||||
theLock.notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
public State getState() {
|
||||
synchronized (theLock) {
|
||||
return myState;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "deprecation" })
|
||||
public void stop(boolean force) {
|
||||
stop0();
|
||||
myThread.interrupt();
|
||||
|
||||
if (!force) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
myThread.join(1000);
|
||||
if (myThread.isAlive()) {
|
||||
myThread.stop();
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
public State waitForStateChange(State state) {
|
||||
try {
|
||||
synchronized (theLock) {
|
||||
if (myState == State.STOPPED) {
|
||||
return State.STOPPED;
|
||||
}
|
||||
while (myState == state) {
|
||||
theLock.wait();
|
||||
}
|
||||
|
||||
return myState;
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean waitForDebuggee() {
|
||||
try {
|
||||
synchronized (theLock) {
|
||||
while (myState == State.RUNNING) {
|
||||
theLock.wait();
|
||||
}
|
||||
|
||||
return myState != State.STOPPED;
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isStopped() {
|
||||
synchronized (theLock) {
|
||||
return myState == State.STOPPED;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean start() {
|
||||
assert myState == State.CREATED : "Already started";
|
||||
|
||||
myThread.start();
|
||||
|
||||
try {
|
||||
synchronized (theLock) {
|
||||
while (myState == State.CREATED) {
|
||||
theLock.wait();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} catch (InterruptedException e) {
|
||||
//
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void enter(StyleFrame frame) {
|
||||
assert Thread.currentThread() == myThread;
|
||||
|
||||
myFrames.addFirst(frame);
|
||||
final String uri = frame.getURI();
|
||||
|
||||
final StyleFrame previous = frame.getPrevious();
|
||||
if (previous != null && previous.getLineNumber() == frame.getLineNumber() && uri != null && uri.equals(previous.getURI())) {
|
||||
if (frame.getInstruction().equals(previous.getInstruction())) {
|
||||
System.err.println(
|
||||
"WARN: Same instruction <" + frame.getInstruction() + "> on line " + frame.getLineNumber() + " encountered more than once");
|
||||
}
|
||||
}
|
||||
|
||||
if (isStopped()) {
|
||||
throw new DebuggerStoppedException();
|
||||
} else if (myCurrentStopCondition != null && myCurrentStopCondition.value()) {
|
||||
suspendAndWait();
|
||||
} else {
|
||||
final int lineNumber = frame.getLineNumber();
|
||||
final Breakpoint breakpoint = myBreakpointManager.getBreakpoint(uri, lineNumber);
|
||||
if (breakpoint != null && breakpoint.isEnabled()) {
|
||||
// do not evaluate a log or condition bp more than once on the same line
|
||||
if (previous == null || previous.getLineNumber() != lineNumber) {
|
||||
final String condition = breakpoint.getCondition();
|
||||
try {
|
||||
if (evalCondition(condition)) {
|
||||
final String logMessage = breakpoint.getLogMessage();
|
||||
final String traceMessage = breakpoint.getTraceMessage();
|
||||
|
||||
if (logBreakpoint(frame, logMessage, traceMessage) || breakpoint.isSuspend()) {
|
||||
suspendAndWait();
|
||||
}
|
||||
}
|
||||
} catch (EvaluationException e) {
|
||||
// TODO: send to IDEA
|
||||
System.err.println("[" + lineNumber + "]: Failed to evaluate expression: " + condition + " -- " + e.getMessage());
|
||||
breakpoint.setEnabled(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean evalCondition(String condition) throws EvaluationException {
|
||||
if (condition != null && condition.length() > 0) {
|
||||
if (!"true".equals(eval("boolean(" + condition + ")").getValue().toString())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean logBreakpoint(StyleFrame frame, String logMessage, String traceMessage) throws EvaluationException {
|
||||
if (logMessage != null) {
|
||||
final String uri = frame.getURI();
|
||||
final String pos = uri.substring(uri.lastIndexOf('/') + 1) + ":" + frame.getLineNumber();
|
||||
System.out.println("[" + pos + "]: " + (logMessage.length() > 0 ? eval(logMessage).getValue().toString() : "<no message>"));
|
||||
|
||||
if (traceMessage != null) {
|
||||
myEventQueue.trace(makeTraceMessage(traceMessage));
|
||||
}
|
||||
return false;
|
||||
} else if (traceMessage != null) {
|
||||
myEventQueue.trace(makeTraceMessage(traceMessage));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private String makeTraceMessage(String traceMessage) throws EvaluationException {
|
||||
if (traceMessage.length() > 0) {
|
||||
return eval(traceMessage).getValue().toString();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void leave() {
|
||||
assert Thread.currentThread() == myThread;
|
||||
|
||||
if (isStopped()) {
|
||||
throw new DebuggerStoppedException();
|
||||
// } else if (myBreakpointManager.isBreakpoint(uri, lineNumber)) {
|
||||
// suspendAndWait();
|
||||
// } else if (myCurrentStopCondition != null && myCurrentStopCondition.value()) {
|
||||
// suspendAndWait();
|
||||
}
|
||||
|
||||
((AbstractFrame)myFrames.removeFirst()).invalidate();
|
||||
}
|
||||
|
||||
public void step() {
|
||||
final int targetSize = myFrames.size();
|
||||
|
||||
myCurrentStopCondition = new Condition() {
|
||||
public boolean value() {
|
||||
return myFrames.size() <= targetSize;
|
||||
}
|
||||
};
|
||||
resume();
|
||||
}
|
||||
|
||||
public void stepInto() {
|
||||
myCurrentStopCondition = Condition.TRUE;
|
||||
|
||||
resume();
|
||||
}
|
||||
|
||||
public org.intellij.plugins.xsltDebugger.rt.engine.Value eval(String expr) throws EvaluationException {
|
||||
final StyleFrame frame = getCurrentFrame();
|
||||
if (frame == null) {
|
||||
throw new EvaluationException("No frame available");
|
||||
}
|
||||
return frame.eval(expr);
|
||||
}
|
||||
|
||||
public StyleFrame getCurrentFrame() {
|
||||
return myFrames.size() > 0 ? myFrames.getFirst() : null;
|
||||
}
|
||||
|
||||
public SourceFrame getSourceFrame() {
|
||||
return mySourceFrames.size() > 0 ? mySourceFrames.getFirst() : null;
|
||||
}
|
||||
|
||||
public List<Debugger.Variable> getGlobalVariables() {
|
||||
final List<Variable> vars = getCurrentFrame().getVariables();
|
||||
for (Iterator<Variable> it = vars.iterator(); it.hasNext(); ) {
|
||||
Variable var = it.next();
|
||||
if (!var.isGlobal()) {
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
return vars;
|
||||
}
|
||||
|
||||
public BreakpointManager getBreakpointManager() {
|
||||
return myBreakpointManager;
|
||||
}
|
||||
|
||||
public void pushSource(SourceFrame sourceFrame) {
|
||||
mySourceFrames.addFirst(sourceFrame);
|
||||
}
|
||||
|
||||
public void popSource() {
|
||||
((AbstractFrame)mySourceFrames.removeFirst()).invalidate();
|
||||
}
|
||||
|
||||
interface Condition {
|
||||
Condition TRUE = new Condition() {
|
||||
public boolean value() {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
boolean value();
|
||||
}
|
||||
|
||||
public OutputEventQueueImpl getEventQueue() {
|
||||
return myEventQueue;
|
||||
}
|
||||
|
||||
public boolean ping() {
|
||||
System.out.println(".");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright 2002-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;
|
||||
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.Debugger;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.OutputEventQueue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: sweinreuter
|
||||
* Date: 08.06.2007
|
||||
*/
|
||||
public class OutputEventQueueImpl implements OutputEventQueue {
|
||||
private final Debugger myDebugger;
|
||||
|
||||
private final List<NodeEvent> myEvents = new ArrayList<NodeEvent>();
|
||||
|
||||
private boolean myEnabled = true;
|
||||
|
||||
public OutputEventQueueImpl(Debugger debugger) {
|
||||
myDebugger = debugger;
|
||||
}
|
||||
|
||||
public void startDocument() {
|
||||
if (myEnabled) {
|
||||
myEvents.add(new NodeEvent(START_DOCUMENT, null, null));
|
||||
}
|
||||
}
|
||||
|
||||
public void endDocument() {
|
||||
if (myEnabled) {
|
||||
myEvents.add(new NodeEvent(END_DOCUMENT, null, null));
|
||||
}
|
||||
}
|
||||
|
||||
public void startElement(String prefix, String localName, String uri) {
|
||||
addEvent(new NodeEvent(OutputEventQueue.START_ELEMENT, new NodeEvent.QName(prefix, localName, uri), null));
|
||||
}
|
||||
|
||||
public void attribute(String prefix, String localName, String uri, String value) {
|
||||
addEvent(new NodeEvent(ATTRIBUTE, new NodeEvent.QName(prefix, localName, uri), value));
|
||||
}
|
||||
|
||||
public void endElement() {
|
||||
addEvent(new NodeEvent(END_ELEMENT, null, null));
|
||||
}
|
||||
|
||||
public void characters(String s) {
|
||||
addEvent(new NodeEvent(CHARACTERS, null, s));
|
||||
}
|
||||
|
||||
public void comment(String s) {
|
||||
addEvent(new NodeEvent(COMMENT, null, s));
|
||||
}
|
||||
|
||||
public void pi(String target, String data) {
|
||||
addEvent(new NodeEvent(PI, new NodeEvent.QName(target), data));
|
||||
}
|
||||
|
||||
public void trace(String text) {
|
||||
addEvent(new NodeEvent(TRACE_POINT, null, text));
|
||||
}
|
||||
|
||||
public void setEnabled(boolean b) {
|
||||
myEnabled = b;
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return myEnabled;
|
||||
}
|
||||
|
||||
private void addEvent(NodeEvent event) {
|
||||
if (myEnabled) {
|
||||
final Debugger.StyleFrame frame = myDebugger.getCurrentFrame();
|
||||
if (frame != null) {
|
||||
event.setLocation(frame.getURI(), frame.getLineNumber());
|
||||
}
|
||||
myEvents.add(event);
|
||||
}
|
||||
}
|
||||
|
||||
public List<NodeEvent> getEvents() {
|
||||
try {
|
||||
return new ArrayList<NodeEvent>(myEvents);
|
||||
} finally {
|
||||
myEvents.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
package org.intellij.plugins.xsltDebugger.rt.engine.local;
|
||||
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.Debugger;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
public final class VariableComparator implements Comparator<Debugger.Variable> {
|
||||
public static final VariableComparator INSTANCE = new VariableComparator();
|
||||
|
||||
private VariableComparator() {
|
||||
}
|
||||
|
||||
public int compare(Debugger.Variable o1, Debugger.Variable o2) {
|
||||
final boolean og = o2.isGlobal();
|
||||
final boolean g = o1.isGlobal();
|
||||
if (og && !g) {
|
||||
return 1;
|
||||
} else if (!og && g) {
|
||||
return -1;
|
||||
} else {
|
||||
return o1.getName().compareTo(o2.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.Debugger;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.Value;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: sweinreuter
|
||||
* Date: 23.05.2007
|
||||
*/
|
||||
public class VariableImpl implements Debugger.Variable {
|
||||
private final boolean myGlobal;
|
||||
private final Kind myKind;
|
||||
private final String myRealname;
|
||||
private final Value myValue;
|
||||
private final String myUri;
|
||||
private final int myLineNumber;
|
||||
|
||||
public VariableImpl(String realname, Value value, boolean global, Kind kind, String uri, int lineNumber) {
|
||||
myValue = value;
|
||||
myRealname = realname;
|
||||
myGlobal = global;
|
||||
myKind = kind;
|
||||
myUri = uri;
|
||||
myLineNumber = lineNumber;
|
||||
}
|
||||
|
||||
public String getURI() {
|
||||
return myUri;
|
||||
}
|
||||
|
||||
public int getLineNumber() {
|
||||
return myLineNumber;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return myRealname;
|
||||
}
|
||||
|
||||
public Value getValue() {
|
||||
return myValue;
|
||||
}
|
||||
|
||||
public boolean isGlobal() {
|
||||
return myGlobal;
|
||||
}
|
||||
|
||||
public Kind getKind() {
|
||||
return myKind;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return (myGlobal ? "global:" : "") + "{" + myKind + ":" + myRealname + "=" + myValue + "}";
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
final VariableImpl that = (VariableImpl)o;
|
||||
|
||||
return myRealname.equals(that.myRealname);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return myRealname.hashCode();
|
||||
}
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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.om.NodeInfo;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.Debugger;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.local.AbstractFrame;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: sweinreuter
|
||||
* Date: 02.06.2007
|
||||
*/
|
||||
class AbstractSaxonFrame<F extends Debugger.Frame, N extends NodeInfo> extends AbstractFrame<F> {
|
||||
protected final N myElement;
|
||||
|
||||
protected AbstractSaxonFrame(F prev, N element) {
|
||||
super(prev);
|
||||
myElement = element;
|
||||
}
|
||||
|
||||
public int getLineNumber() {
|
||||
return myElement.getLineNumber();
|
||||
}
|
||||
|
||||
public String getURI() {
|
||||
final String uri = myElement.getSystemId();
|
||||
return uri != null ? uri.replaceAll(" ", "%20") : null;
|
||||
}
|
||||
}
|
||||
+269
@@ -0,0 +1,269 @@
|
||||
/*
|
||||
* 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.Bindery;
|
||||
import com.icl.saxon.Binding;
|
||||
import com.icl.saxon.Context;
|
||||
import com.icl.saxon.expr.*;
|
||||
import com.icl.saxon.om.*;
|
||||
import com.icl.saxon.output.GeneralOutputter;
|
||||
import com.icl.saxon.style.ExpressionContext;
|
||||
import com.icl.saxon.style.StyleElement;
|
||||
import com.icl.saxon.style.XSLGeneralVariable;
|
||||
import com.icl.saxon.style.XSLParam;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.Debugger;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.Value;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.local.VariableComparator;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.local.VariableImpl;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
import javax.xml.transform.OutputKeys;
|
||||
import javax.xml.transform.TransformerConfigurationException;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import java.io.StringWriter;
|
||||
import java.lang.reflect.Field;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: sweinreuter
|
||||
* Date: 23.05.2007
|
||||
*/
|
||||
class SaxonFrameImpl extends AbstractSaxonFrame<Debugger.StyleFrame, StyleElement> implements Debugger.StyleFrame {
|
||||
|
||||
private static Field fGeneralUseAllowed;
|
||||
|
||||
static {
|
||||
try {
|
||||
fGeneralUseAllowed = SingletonNodeSet.class.getDeclaredField("generalUseAllowed");
|
||||
fGeneralUseAllowed.setAccessible(true);
|
||||
} catch (NoSuchFieldException e) {
|
||||
fGeneralUseAllowed = null;
|
||||
System.err.println("Failed to get field com.icl.saxon.expr.SingletonNodeSet.generalUseAllowed - incompatible Saxon version?");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private final Context myContext;
|
||||
private final int myFrameId;
|
||||
|
||||
SaxonFrameImpl(Debugger.StyleFrame prev, Context context, StyleElement element) {
|
||||
super(prev, element);
|
||||
myContext = context;
|
||||
myFrameId = context.getBindery().getFrameId();
|
||||
}
|
||||
|
||||
public String getInstruction() {
|
||||
return myElement.getDisplayName();
|
||||
}
|
||||
|
||||
public List<Debugger.Variable> getVariables() {
|
||||
assert isValid();
|
||||
|
||||
final ArrayList<Debugger.Variable> variables = new ArrayList<Debugger.Variable>();
|
||||
final Enumeration[] variableNames = myElement.getVariableNames();
|
||||
|
||||
this.addVariables(myElement, variables, variableNames[0], true);
|
||||
this.addVariables(myElement, variables, variableNames[1], false);
|
||||
|
||||
Collections.sort(variables, VariableComparator.INSTANCE);
|
||||
|
||||
return variables;
|
||||
}
|
||||
|
||||
public Value eval(String expr) throws Debugger.EvaluationException {
|
||||
assert isValid();
|
||||
|
||||
try {
|
||||
// trick to avoid exception when evaluating variable references on xsl:template frames
|
||||
final MyDummyElement dummy = new MyDummyElement(myElement);
|
||||
final Expression expression = Expression.make(expr, dummy.getStaticContext());
|
||||
return convertValue(expression.evaluate(myContext));
|
||||
} catch (XPathException e) {
|
||||
throw new Debugger.EvaluationException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private Value convertValue(com.icl.saxon.expr.Value v) throws XPathException {
|
||||
return MyValue.create(v, myContext);
|
||||
}
|
||||
|
||||
void addVariables(StyleElement element, ArrayList<Debugger.Variable> variables, Enumeration enumeration, boolean isGlobal) {
|
||||
final Context context = myContext;
|
||||
final StaticContext ctx = context.getStaticContext();
|
||||
|
||||
final NamePool pool = element.getNamePool();
|
||||
final Bindery bindery = context.getBindery();
|
||||
|
||||
while (enumeration.hasMoreElements()) {
|
||||
String name = (String)enumeration.nextElement();
|
||||
try {
|
||||
final String[] parts = name.split("\\^");
|
||||
final String realname = parts[1];
|
||||
final int fingerprint = ctx != null ? ctx.getFingerprint(realname, false) : pool.getFingerprint(parts[0], realname);
|
||||
final Binding binding = element.getVariableBinding(fingerprint);
|
||||
final Debugger.Variable.Kind kind =
|
||||
binding instanceof XSLParam ? Debugger.Variable.Kind.PARAMETER : Debugger.Variable.Kind.VARIABLE;
|
||||
final com.icl.saxon.expr.Value value = bindery.getValue(binding, myFrameId);
|
||||
|
||||
if (binding instanceof XSLGeneralVariable) {
|
||||
final XSLGeneralVariable v = (XSLGeneralVariable)binding;
|
||||
final String id = v.getSystemId();
|
||||
variables.add(new VariableImpl(realname, convertValue(value), isGlobal, kind, id != null ? id.replaceAll(" ", "%20") : null,
|
||||
v.getLineNumber()));
|
||||
} else {
|
||||
variables.add(new VariableImpl(realname, convertValue(value), isGlobal, kind, null, -1));
|
||||
}
|
||||
} catch (XPathException e) {
|
||||
// this should never happen I guess...
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class MyValue implements Value {
|
||||
private final Object myValue;
|
||||
private final Type myType;
|
||||
|
||||
public MyValue(Object value, String type) {
|
||||
myValue = value;
|
||||
myType = new ObjectType(type);
|
||||
}
|
||||
|
||||
public MyValue(Object value, int type) {
|
||||
myValue = value;
|
||||
myType = mapType(type);
|
||||
}
|
||||
|
||||
public Object getValue() {
|
||||
return myValue;
|
||||
}
|
||||
|
||||
public Type getType() {
|
||||
return myType;
|
||||
}
|
||||
|
||||
private static Type mapType(int type) {
|
||||
switch (type) {
|
||||
case com.icl.saxon.expr.Value.BOOLEAN:
|
||||
return XPathType.BOOLEAN;
|
||||
case com.icl.saxon.expr.Value.NODESET:
|
||||
return XPathType.NODESET;
|
||||
case com.icl.saxon.expr.Value.NUMBER:
|
||||
return XPathType.NUMBER;
|
||||
case com.icl.saxon.expr.Value.STRING:
|
||||
return XPathType.STRING;
|
||||
case com.icl.saxon.expr.Value.OBJECT:
|
||||
return XPathType.OBJECT;
|
||||
default:
|
||||
return XPathType.UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
public static Value create(com.icl.saxon.expr.Value v, Context context) throws XPathException {
|
||||
if (v instanceof NodeSetValue) {
|
||||
if (v instanceof FragmentValue) {
|
||||
final FragmentValue value = (FragmentValue)v;
|
||||
final boolean b = value.isGeneralUseAllowed();
|
||||
try {
|
||||
if (!b) value.allowGeneralUse();
|
||||
|
||||
final DocumentInfo node = value.getRootNode();
|
||||
final GeneralOutputter outputter = new GeneralOutputter(node.getNamePool());
|
||||
final StringWriter writer = new StringWriter();
|
||||
final Properties props = new Properties();
|
||||
props.setProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
|
||||
outputter.setOutputDestination(props, new StreamResult(writer));
|
||||
node.copy(outputter);
|
||||
|
||||
return new MyValue(writer.toString(), v.getDataType());
|
||||
} catch (TransformerException e) {
|
||||
return new MyValue(v.asString(), v.getDataType());
|
||||
} finally {
|
||||
if (!b && fGeneralUseAllowed != null) {
|
||||
resetGeneralUseAllowed(value);
|
||||
}
|
||||
}
|
||||
} else if (v instanceof TextFragmentValue) {
|
||||
// this really is just a string
|
||||
return new MyValue(v.asString(), com.icl.saxon.expr.Value.STRING);
|
||||
}
|
||||
|
||||
final List<Node> list = new ArrayList<Node>();
|
||||
final NodeEnumeration nodeEnumeration = ((NodeSetValue)v).enumerate();
|
||||
while (nodeEnumeration.hasMoreElements()) {
|
||||
final NodeInfo node = nodeEnumeration.nextElement();
|
||||
final String path = Navigator.getPath(node);
|
||||
final String id = node.getSystemId();
|
||||
if (id != null) {
|
||||
try {
|
||||
list.add(new Node(new URI(id.replaceAll(" ", "%20")).normalize().toASCIIString(), node.getLineNumber(), path,
|
||||
node.getStringValue()));
|
||||
} catch (URISyntaxException e) {
|
||||
e.printStackTrace();
|
||||
list.add(new Node(id, node.getLineNumber(), path, node.getStringValue()));
|
||||
}
|
||||
} else {
|
||||
list.add(new Node(null, -1, path, node.getStringValue()));
|
||||
}
|
||||
}
|
||||
return new MyValue(new NodeSet(v.asString(), list), v.getDataType());
|
||||
} else if (v instanceof ObjectValue) {
|
||||
final Object o = ((ObjectValue)v).getObject();
|
||||
return new MyValue(o, o != null ? o.getClass().getName() : "null");
|
||||
} else {
|
||||
return new MyValue(v.evaluateAsString(context), v.getDataType());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void resetGeneralUseAllowed(FragmentValue value) {
|
||||
try {
|
||||
fGeneralUseAllowed.set(value, false);
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static class MyDummyElement extends StyleElement {
|
||||
private final StyleElement myElement;
|
||||
|
||||
public MyDummyElement(StyleElement element) {
|
||||
myElement = element;
|
||||
substituteFor(element);
|
||||
}
|
||||
|
||||
public void prepareAttributes() throws TransformerConfigurationException {
|
||||
}
|
||||
|
||||
public void process(Context context) throws TransformerException {
|
||||
}
|
||||
|
||||
public StaticContext getStaticContext() {
|
||||
return new ExpressionContext(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node getPreviousSibling() {
|
||||
return myElement.getPreviousSibling();
|
||||
}
|
||||
}
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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.om.Navigator;
|
||||
import com.icl.saxon.om.NodeInfo;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.Debugger;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: sweinreuter
|
||||
* Date: 03.06.2007
|
||||
*/
|
||||
class SaxonSourceFrame extends AbstractSaxonFrame<Debugger.SourceFrame, NodeInfo> implements Debugger.SourceFrame {
|
||||
public SaxonSourceFrame(Debugger.SourceFrame prev, NodeInfo element) {
|
||||
super(prev, element);
|
||||
}
|
||||
|
||||
public String getXPath() {
|
||||
return Navigator.getPath(myElement);
|
||||
}
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
package org.intellij.plugins.xsltDebugger.rt.engine.local.saxon;
|
||||
|
||||
import com.icl.saxon.Controller;
|
||||
import com.icl.saxon.TransformerFactoryImpl;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.local.LocalDebugger;
|
||||
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
|
||||
/*
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: sweinreuter
|
||||
* Date: 12.01.2009
|
||||
*/
|
||||
public class SaxonSupport {
|
||||
public static boolean init(Transformer transformer, LocalDebugger dbg) {
|
||||
if (transformer instanceof Controller) {
|
||||
System.out.println("SAXON");
|
||||
final Controller controller = (Controller)transformer;
|
||||
controller.setLineNumbering(true);
|
||||
controller.addTraceListener(new SaxonTraceListener(dbg, controller));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static TransformerFactory createTransformerFactory() {
|
||||
return new TransformerFactoryImpl();
|
||||
}
|
||||
}
|
||||
+242
@@ -0,0 +1,242 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
package org.intellij.plugins.xsltDebugger.rt.engine.local.saxon9;
|
||||
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.Debugger;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.local.AbstractFrame;
|
||||
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.transform.SourceLocator;
|
||||
|
||||
/*
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: sweinreuter
|
||||
* Date: 04.05.11
|
||||
*/
|
||||
class AbstractSaxon9Frame<F extends Debugger.Frame, N extends Source> extends AbstractFrame<F> {
|
||||
protected final N myElement;
|
||||
|
||||
protected AbstractSaxon9Frame(F prev, N element) {
|
||||
super(prev);
|
||||
myElement = element;
|
||||
}
|
||||
|
||||
public int getLineNumber() {
|
||||
return ((SourceLocator)myElement).getLineNumber();
|
||||
}
|
||||
|
||||
public String getURI() {
|
||||
final String uri = myElement.getSystemId();
|
||||
return uri != null ? uri.replaceAll(" ", "%20") : null;
|
||||
}
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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.saxon9;
|
||||
|
||||
import net.sf.saxon.om.NodeInfo;
|
||||
import net.sf.saxon.tree.util.Navigator;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.Debugger;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: sweinreuter
|
||||
* Date: 02.06.2007
|
||||
*/
|
||||
class Saxon9SourceFrame<N extends NodeInfo> extends AbstractSaxon9Frame<Debugger.SourceFrame, N> implements Debugger.SourceFrame {
|
||||
|
||||
protected Saxon9SourceFrame(Debugger.SourceFrame prev, N element) {
|
||||
super(prev, element);
|
||||
}
|
||||
|
||||
|
||||
public String getXPath() {
|
||||
return Navigator.getPath(myElement);
|
||||
}
|
||||
}
|
||||
+98
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* 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.saxon9;
|
||||
|
||||
import net.sf.saxon.expr.StackFrame;
|
||||
import net.sf.saxon.expr.XPathContext;
|
||||
import net.sf.saxon.expr.instruct.SlotManager;
|
||||
import net.sf.saxon.om.ValueRepresentation;
|
||||
import net.sf.saxon.style.StyleElement;
|
||||
import net.sf.saxon.trans.XPathException;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.Debugger;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.Value;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.local.VariableImpl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: sweinreuter
|
||||
* Date: 02.06.2007
|
||||
*/
|
||||
class Saxon9StyleFrame<N extends StyleElement> extends AbstractSaxon9Frame<Debugger.StyleFrame, N> implements Debugger.StyleFrame {
|
||||
|
||||
private final XPathContext myXPathContext;
|
||||
private final StackFrame myStackFrame;
|
||||
|
||||
protected Saxon9StyleFrame(Debugger.StyleFrame prev, N element, XPathContext xPathContext) {
|
||||
super(prev, element);
|
||||
myXPathContext = xPathContext;
|
||||
myStackFrame = myXPathContext.getStackFrame();
|
||||
}
|
||||
|
||||
public String getInstruction() {
|
||||
return myElement.getDisplayName();
|
||||
}
|
||||
|
||||
public Value eval(String expr) throws Debugger.EvaluationException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<Debugger.Variable> getVariables() {
|
||||
final ArrayList<Debugger.Variable> variables = new ArrayList<Debugger.Variable>();
|
||||
|
||||
XPathContext context = myXPathContext;
|
||||
while (context != null) {
|
||||
final StackFrame frame = context.getStackFrame();
|
||||
final SlotManager map = frame.getStackFrameMap();
|
||||
final int numberOfVariables = map.getNumberOfVariables();
|
||||
System.out.println("numberOfVariables = " + numberOfVariables);
|
||||
|
||||
for (int i = 0; i < numberOfVariables; i++) {
|
||||
final ValueRepresentation valueRepresentation = context.evaluateLocalVariable(i);
|
||||
System.out.println("valueRepresentation = " + valueRepresentation);
|
||||
}
|
||||
final ValueRepresentation[] values = frame.getStackFrameValues();
|
||||
System.out.println("values = " + Arrays.toString(values));
|
||||
|
||||
for (int i = 0, valuesLength = values.length; i < valuesLength; i++) {
|
||||
final ValueRepresentation value = values[i];
|
||||
|
||||
variables.add(new VariableImpl(map.getVariableMap().get(i).getDisplayName(), new Value() {
|
||||
public Object getValue() {
|
||||
try {
|
||||
return value.getStringValue();
|
||||
} catch (XPathException e) {
|
||||
return " - error: " + e.getMessage() + " - ";
|
||||
}
|
||||
}
|
||||
|
||||
public Type getType() {
|
||||
return XPathType.UNKNOWN;
|
||||
}
|
||||
}, false, Debugger.Variable.Kind.VARIABLE, "", -1));
|
||||
}
|
||||
|
||||
context = context.getCaller();
|
||||
System.out.println("context = " + context);
|
||||
}
|
||||
|
||||
return variables;
|
||||
}
|
||||
}
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
package org.intellij.plugins.xsltDebugger.rt.engine.local.saxon9;
|
||||
|
||||
import net.sf.saxon.Controller;
|
||||
import net.sf.saxon.TransformerFactoryImpl;
|
||||
import net.sf.saxon.event.PipelineConfiguration;
|
||||
import net.sf.saxon.event.ProxyReceiver;
|
||||
import net.sf.saxon.event.Receiver;
|
||||
import net.sf.saxon.expr.instruct.Debugger;
|
||||
import net.sf.saxon.expr.instruct.SlotManager;
|
||||
import net.sf.saxon.lib.FeatureKeys;
|
||||
import net.sf.saxon.lib.SerializerFactory;
|
||||
import net.sf.saxon.om.StructuredQName;
|
||||
import net.sf.saxon.serialize.CharacterMapExpander;
|
||||
import net.sf.saxon.serialize.Emitter;
|
||||
import net.sf.saxon.trans.XPathException;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.local.LocalDebugger;
|
||||
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import java.util.Properties;
|
||||
|
||||
/*
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: sweinreuter
|
||||
* Date: 12.01.2009
|
||||
*/
|
||||
public class Saxon9Support {
|
||||
public static boolean init(Transformer transformer, final LocalDebugger dbg) {
|
||||
if (transformer instanceof Controller) {
|
||||
System.out.println("SAXON 9");
|
||||
final Controller controller = (Controller)transformer;
|
||||
((Saxon9TraceListener)controller.getConfiguration().getTraceListener()).setDebugger(dbg);
|
||||
controller.getConfiguration().setLineNumbering(true);
|
||||
controller.getConfiguration().setCompileWithTracing(true);
|
||||
controller.getConfiguration().setMultiThreading(false);
|
||||
controller.getConfiguration().setSerializerFactory(new SerializerFactory(controller.getConfiguration()) {
|
||||
@Override
|
||||
protected Receiver createXMLSerializer(Emitter emitter,
|
||||
Properties props,
|
||||
PipelineConfiguration pipe,
|
||||
CharacterMapExpander characterMapExpander,
|
||||
ProxyReceiver normalizer) throws XPathException {
|
||||
return super.createXMLSerializer(emitter, props, pipe, characterMapExpander, normalizer);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Emitter newXMLEmitter() {
|
||||
return new TracingOutputter(dbg.getEventQueue(), super.newXMLEmitter());
|
||||
}
|
||||
});
|
||||
controller.getConfiguration().setDebugger(new Debugger() {
|
||||
public SlotManager makeSlotManager() {
|
||||
return new SlotManager() {
|
||||
@Override
|
||||
public int allocateSlotNumber(StructuredQName qName) {
|
||||
System.out.println("qName = " + qName);
|
||||
return super.allocateSlotNumber(qName);
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static TransformerFactory createTransformerFactory() {
|
||||
final TransformerFactoryImpl factory = new TransformerFactoryImpl();
|
||||
factory.setAttribute(FeatureKeys.TRACE_LISTENER, new Saxon9TraceListener());
|
||||
return factory;
|
||||
}
|
||||
}
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* 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.saxon9;
|
||||
|
||||
import net.sf.saxon.expr.XPathContext;
|
||||
import net.sf.saxon.lib.TraceListener;
|
||||
import net.sf.saxon.om.Item;
|
||||
import net.sf.saxon.om.NodeInfo;
|
||||
import net.sf.saxon.style.StyleElement;
|
||||
import net.sf.saxon.trace.InstructionInfo;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.local.LocalDebugger;
|
||||
|
||||
public class Saxon9TraceListener implements TraceListener {
|
||||
private static final boolean TRACE = "true".equals(System.getProperty("xslt.debugger.trace", "false"));
|
||||
|
||||
private LocalDebugger myDebugger;
|
||||
|
||||
public Saxon9TraceListener() {
|
||||
}
|
||||
|
||||
public void setDebugger(LocalDebugger debugger) {
|
||||
myDebugger = debugger;
|
||||
}
|
||||
|
||||
private static void trace(String s) {
|
||||
if (TRACE) {
|
||||
System.err.println(s);
|
||||
}
|
||||
}
|
||||
|
||||
public void open() {
|
||||
myDebugger.getEventQueue().startDocument();
|
||||
if (TRACE) {
|
||||
trace("<trace>");
|
||||
}
|
||||
}
|
||||
|
||||
public void close() {
|
||||
myDebugger.getEventQueue().endDocument();
|
||||
|
||||
if (TRACE) {
|
||||
trace("</trace>");
|
||||
}
|
||||
}
|
||||
|
||||
public void enter(InstructionInfo instructionInfo, XPathContext xPathContext) {
|
||||
if (TRACE) {
|
||||
trace("<" + instructionInfo + ">");
|
||||
}
|
||||
if (instructionInfo instanceof StyleElement) {
|
||||
myDebugger.enter(new Saxon9StyleFrame(myDebugger.getCurrentFrame(), (StyleElement)instructionInfo, xPathContext));
|
||||
}
|
||||
}
|
||||
|
||||
public void leave(InstructionInfo instructionInfo) {
|
||||
if (TRACE) {
|
||||
trace("</>");
|
||||
}
|
||||
if (instructionInfo instanceof StyleElement) {
|
||||
myDebugger.leave();
|
||||
}
|
||||
}
|
||||
|
||||
public void startCurrentItem(Item item) {
|
||||
if (item instanceof NodeInfo) {
|
||||
if (TRACE) {
|
||||
trace("<" + ((NodeInfo)item).getDisplayName() + ">");
|
||||
}
|
||||
myDebugger.pushSource(new Saxon9SourceFrame(myDebugger.getSourceFrame(), (NodeInfo)item));
|
||||
}
|
||||
}
|
||||
|
||||
public void endCurrentItem(Item item) {
|
||||
myDebugger.popSource();
|
||||
}
|
||||
}
|
||||
+124
@@ -0,0 +1,124 @@
|
||||
package org.intellij.plugins.xsltDebugger.rt.engine.local.saxon9;
|
||||
|
||||
import net.sf.saxon.event.PipelineConfiguration;
|
||||
import net.sf.saxon.serialize.Emitter;
|
||||
import net.sf.saxon.trans.XPathException;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.local.OutputEventQueueImpl;
|
||||
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Writer;
|
||||
import java.util.Properties;
|
||||
|
||||
final class TracingOutputter extends Emitter {
|
||||
private final OutputEventQueueImpl myEventQueue;
|
||||
private final Emitter myEmitter;
|
||||
|
||||
public TracingOutputter(OutputEventQueueImpl queue, Emitter emitter) {
|
||||
myEmitter = emitter;
|
||||
myEventQueue = queue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPipelineConfiguration(PipelineConfiguration pipe) {
|
||||
super.setPipelineConfiguration(pipe);
|
||||
myEmitter.setPipelineConfiguration(pipe);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSystemId(String systemId) {
|
||||
myEmitter.setSystemId(systemId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOutputProperties(Properties details) throws XPathException {
|
||||
myEmitter.setOutputProperties(details);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStreamResult(StreamResult result) throws XPathException {
|
||||
myEmitter.setStreamResult(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setWriter(Writer writer) throws XPathException {
|
||||
myEmitter.setWriter(writer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOutputStream(OutputStream stream) throws XPathException {
|
||||
myEmitter.setOutputStream(stream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUnparsedEntity(String name, String uri, String publicId) throws XPathException {
|
||||
myEmitter.setUnparsedEntity(name, uri, publicId);
|
||||
}
|
||||
|
||||
public void open() throws XPathException {
|
||||
myEmitter.open();
|
||||
}
|
||||
|
||||
public void startDocument(int properties) throws XPathException {
|
||||
myEmitter.startDocument(properties);
|
||||
}
|
||||
|
||||
public void endDocument() throws XPathException {
|
||||
myEmitter.endDocument();
|
||||
}
|
||||
|
||||
public void namespace(int namespaceCode, int properties) throws XPathException {
|
||||
myEmitter.namespace(namespaceCode, properties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws XPathException {
|
||||
myEmitter.close();
|
||||
}
|
||||
|
||||
public void startElement(int nameCode, int typeCode, int locationId, int properties) throws XPathException {
|
||||
if (myEventQueue.isEnabled()) {
|
||||
final String localName = namePool.getLocalName(nameCode);
|
||||
final String prefix = namePool.getPrefix(nameCode);
|
||||
myEventQueue.startElement(prefix, localName, namePool.getURI(nameCode));
|
||||
}
|
||||
myEmitter.startElement(nameCode, typeCode, locationId, properties);
|
||||
}
|
||||
|
||||
|
||||
public void attribute(int nameCode, int typeCode, CharSequence value, int locationId, int properties) throws XPathException {
|
||||
if (myEventQueue.isEnabled()) {
|
||||
final String localName = namePool.getLocalName(nameCode);
|
||||
final String prefix = namePool.getPrefix(nameCode);
|
||||
myEventQueue.attribute(prefix, localName, namePool.getURI(nameCode), value.toString());
|
||||
}
|
||||
myEmitter.attribute(nameCode, typeCode, value, locationId, properties);
|
||||
}
|
||||
|
||||
public void startContent() throws XPathException {
|
||||
}
|
||||
|
||||
public void endElement() throws XPathException {
|
||||
myEventQueue.endElement();
|
||||
myEmitter.endElement();
|
||||
}
|
||||
|
||||
public void characters(CharSequence chars, int locationId, int properties) throws XPathException {
|
||||
myEventQueue.characters(chars.toString());
|
||||
myEmitter.characters(chars, locationId, properties);
|
||||
}
|
||||
|
||||
public void processingInstruction(String name, CharSequence data, int locationId, int properties) throws XPathException {
|
||||
myEventQueue.pi(name, data.toString());
|
||||
myEmitter.processingInstruction(name, data, locationId, properties);
|
||||
}
|
||||
|
||||
public void comment(CharSequence content, int locationId, int properties) throws XPathException {
|
||||
myEventQueue.comment(content.toString());
|
||||
myEmitter.comment(content, locationId, properties);
|
||||
}
|
||||
|
||||
public boolean usesTypeAnnotations() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
+397
@@ -0,0 +1,397 @@
|
||||
package org.intellij.plugins.xsltDebugger.rt.engine.local.xalan;
|
||||
|
||||
import org.apache.xml.serializer.DOMSerializer;
|
||||
import org.apache.xml.serializer.NamespaceMappings;
|
||||
import org.apache.xml.serializer.SerializationHandler;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.local.LocalDebugger;
|
||||
import org.w3c.dom.Node;
|
||||
import org.xml.sax.*;
|
||||
|
||||
import javax.xml.transform.SourceLocator;
|
||||
import javax.xml.transform.Transformer;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Writer;
|
||||
import java.util.Properties;
|
||||
import java.util.Vector;
|
||||
|
||||
class TracingSerializationHandler implements SerializationHandler {
|
||||
private final LocalDebugger myDebugger;
|
||||
private final SerializationHandler mySerializationHandler;
|
||||
|
||||
public TracingSerializationHandler(LocalDebugger debugger, SerializationHandler handler) {
|
||||
myDebugger = debugger;
|
||||
mySerializationHandler = handler;
|
||||
|
||||
// final URL location = SerializationHandler.class.getProtectionDomain().getCodeSource().getLocation();
|
||||
// System.out.println("location = " + location);
|
||||
}
|
||||
|
||||
private static String calcPrefix(String qname) {
|
||||
return qname.indexOf(':') == -1 ? "" : qname.split(":")[0];
|
||||
}
|
||||
|
||||
public void setContentHandler(ContentHandler ch) {
|
||||
mySerializationHandler.setContentHandler(ch);
|
||||
}
|
||||
|
||||
public void close() {
|
||||
mySerializationHandler.close();
|
||||
}
|
||||
|
||||
public void serialize(Node node) throws IOException {
|
||||
mySerializationHandler.serialize(node);
|
||||
}
|
||||
|
||||
public boolean setEscaping(boolean escape) throws SAXException {
|
||||
return mySerializationHandler.setEscaping(escape);
|
||||
}
|
||||
|
||||
public void setIndentAmount(int spaces) {
|
||||
mySerializationHandler.setIndentAmount(spaces);
|
||||
}
|
||||
|
||||
public void setTransformer(Transformer transformer) {
|
||||
mySerializationHandler.setTransformer(transformer);
|
||||
}
|
||||
|
||||
public Transformer getTransformer() {
|
||||
return mySerializationHandler.getTransformer();
|
||||
}
|
||||
|
||||
public void setNamespaceMappings(NamespaceMappings mappings) {
|
||||
mySerializationHandler.setNamespaceMappings(mappings);
|
||||
}
|
||||
|
||||
public void flushPending() throws SAXException {
|
||||
mySerializationHandler.flushPending();
|
||||
}
|
||||
|
||||
public void setDTDEntityExpansion(boolean expand) {
|
||||
mySerializationHandler.setDTDEntityExpansion(expand);
|
||||
}
|
||||
|
||||
public void addAttribute(String uri, String localName, String rawName, String type, String value, boolean XSLAttribute)
|
||||
throws SAXException {
|
||||
myDebugger.getEventQueue().attribute(calcPrefix(rawName), localName, uri, value);
|
||||
mySerializationHandler.addAttribute(uri, localName, rawName, type, value, XSLAttribute);
|
||||
}
|
||||
|
||||
public void addAttribute(String uri, String localName, String rawName, String type, String value) throws SAXException {
|
||||
myDebugger.getEventQueue().attribute("", localName, uri, value);
|
||||
mySerializationHandler.addAttribute(uri, localName, rawName, type, value);
|
||||
}
|
||||
|
||||
public void addAttributes(Attributes atts) throws SAXException {
|
||||
mySerializationHandler.addAttributes(atts);
|
||||
}
|
||||
|
||||
public void addAttribute(String qName, String value) {
|
||||
mySerializationHandler.addAttribute(qName, value);
|
||||
}
|
||||
|
||||
public void characters(String chars) throws SAXException {
|
||||
mySerializationHandler.characters(chars);
|
||||
}
|
||||
|
||||
public void characters(Node node) throws SAXException {
|
||||
mySerializationHandler.characters(node);
|
||||
}
|
||||
|
||||
public void endElement(String elemName) throws SAXException {
|
||||
mySerializationHandler.endElement(elemName);
|
||||
}
|
||||
|
||||
public void startElement(String uri, String localName, String qName) throws SAXException {
|
||||
myDebugger.getEventQueue().startElement(calcPrefix(qName), localName, uri);
|
||||
mySerializationHandler.startElement(uri, localName, qName);
|
||||
}
|
||||
|
||||
public void startElement(String qName) throws SAXException {
|
||||
mySerializationHandler.startElement(qName);
|
||||
}
|
||||
|
||||
public void namespaceAfterStartElement(String uri, String prefix) throws SAXException {
|
||||
mySerializationHandler.namespaceAfterStartElement(uri, prefix);
|
||||
}
|
||||
|
||||
public boolean startPrefixMapping(String prefix, String uri, boolean shouldFlush) throws SAXException {
|
||||
return mySerializationHandler.startPrefixMapping(prefix, uri, shouldFlush);
|
||||
}
|
||||
|
||||
public void entityReference(String entityName) throws SAXException {
|
||||
mySerializationHandler.entityReference(entityName);
|
||||
}
|
||||
|
||||
public NamespaceMappings getNamespaceMappings() {
|
||||
return mySerializationHandler.getNamespaceMappings();
|
||||
}
|
||||
|
||||
public String getPrefix(String uri) {
|
||||
return mySerializationHandler.getPrefix(uri);
|
||||
}
|
||||
|
||||
public String getNamespaceURI(String name, boolean isElement) {
|
||||
return mySerializationHandler.getNamespaceURI(name, isElement);
|
||||
}
|
||||
|
||||
public String getNamespaceURIFromPrefix(String prefix) {
|
||||
return mySerializationHandler.getNamespaceURIFromPrefix(prefix);
|
||||
}
|
||||
|
||||
public void setSourceLocator(SourceLocator locator) {
|
||||
mySerializationHandler.setSourceLocator(locator);
|
||||
}
|
||||
|
||||
public void addUniqueAttribute(String qName, String value, int flags) throws SAXException {
|
||||
mySerializationHandler.addUniqueAttribute(qName, value, flags);
|
||||
}
|
||||
|
||||
public void addXSLAttribute(String qName, String value, String uri) {
|
||||
mySerializationHandler.addXSLAttribute(qName, value, uri);
|
||||
}
|
||||
|
||||
public void setDocumentLocator(Locator locator) {
|
||||
mySerializationHandler.setDocumentLocator(locator);
|
||||
}
|
||||
|
||||
public void startDocument() throws SAXException {
|
||||
mySerializationHandler.startDocument();
|
||||
}
|
||||
|
||||
public void endDocument() throws SAXException {
|
||||
mySerializationHandler.endDocument();
|
||||
}
|
||||
|
||||
public void startPrefixMapping(String prefix, String uri) throws SAXException {
|
||||
mySerializationHandler.startPrefixMapping(prefix, uri);
|
||||
}
|
||||
|
||||
public void endPrefixMapping(String prefix) throws SAXException {
|
||||
mySerializationHandler.endPrefixMapping(prefix);
|
||||
}
|
||||
|
||||
public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
|
||||
mySerializationHandler.startElement(uri, localName, qName, atts);
|
||||
}
|
||||
|
||||
public void endElement(String uri, String localName, String qName) throws SAXException {
|
||||
mySerializationHandler.endElement(uri, localName, qName);
|
||||
}
|
||||
|
||||
public void characters(char[] ch, int start, int length) throws SAXException {
|
||||
mySerializationHandler.characters(ch, start, length);
|
||||
}
|
||||
|
||||
public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException {
|
||||
mySerializationHandler.ignorableWhitespace(ch, start, length);
|
||||
}
|
||||
|
||||
public void processingInstruction(String target, String data) throws SAXException {
|
||||
mySerializationHandler.processingInstruction(target, data);
|
||||
}
|
||||
|
||||
public void skippedEntity(String name) throws SAXException {
|
||||
mySerializationHandler.skippedEntity(name);
|
||||
}
|
||||
|
||||
public void comment(String comment) throws SAXException {
|
||||
mySerializationHandler.comment(comment);
|
||||
}
|
||||
|
||||
public void startDTD(String name, String publicId, String systemId) throws SAXException {
|
||||
mySerializationHandler.startDTD(name, publicId, systemId);
|
||||
}
|
||||
|
||||
public void endDTD() throws SAXException {
|
||||
mySerializationHandler.endDTD();
|
||||
}
|
||||
|
||||
public void startEntity(String name) throws SAXException {
|
||||
mySerializationHandler.startEntity(name);
|
||||
}
|
||||
|
||||
public void endEntity(String name) throws SAXException {
|
||||
mySerializationHandler.endEntity(name);
|
||||
}
|
||||
|
||||
public void startCDATA() throws SAXException {
|
||||
mySerializationHandler.startCDATA();
|
||||
}
|
||||
|
||||
public void endCDATA() throws SAXException {
|
||||
mySerializationHandler.endCDATA();
|
||||
}
|
||||
|
||||
public void comment(char[] ch, int start, int length) throws SAXException {
|
||||
mySerializationHandler.comment(ch, start, length);
|
||||
}
|
||||
|
||||
public String getDoctypePublic() {
|
||||
return mySerializationHandler.getDoctypePublic();
|
||||
}
|
||||
|
||||
public String getDoctypeSystem() {
|
||||
return mySerializationHandler.getDoctypeSystem();
|
||||
}
|
||||
|
||||
public String getEncoding() {
|
||||
return mySerializationHandler.getEncoding();
|
||||
}
|
||||
|
||||
public boolean getIndent() {
|
||||
return mySerializationHandler.getIndent();
|
||||
}
|
||||
|
||||
public int getIndentAmount() {
|
||||
return mySerializationHandler.getIndentAmount();
|
||||
}
|
||||
|
||||
public String getMediaType() {
|
||||
return mySerializationHandler.getMediaType();
|
||||
}
|
||||
|
||||
public boolean getOmitXMLDeclaration() {
|
||||
return mySerializationHandler.getOmitXMLDeclaration();
|
||||
}
|
||||
|
||||
public String getStandalone() {
|
||||
return mySerializationHandler.getStandalone();
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return mySerializationHandler.getVersion();
|
||||
}
|
||||
|
||||
public void setCdataSectionElements(Vector URI_and_localNames) {
|
||||
mySerializationHandler.setCdataSectionElements(URI_and_localNames);
|
||||
}
|
||||
|
||||
public void setDoctype(String system, String pub) {
|
||||
mySerializationHandler.setDoctype(system, pub);
|
||||
}
|
||||
|
||||
public void setDoctypePublic(String doctype) {
|
||||
mySerializationHandler.setDoctypePublic(doctype);
|
||||
}
|
||||
|
||||
public void setDoctypeSystem(String doctype) {
|
||||
mySerializationHandler.setDoctypeSystem(doctype);
|
||||
}
|
||||
|
||||
public void setEncoding(String encoding) {
|
||||
mySerializationHandler.setEncoding(encoding);
|
||||
}
|
||||
|
||||
public void setIndent(boolean indent) {
|
||||
mySerializationHandler.setIndent(indent);
|
||||
}
|
||||
|
||||
public void setMediaType(String mediatype) {
|
||||
mySerializationHandler.setMediaType(mediatype);
|
||||
}
|
||||
|
||||
public void setOmitXMLDeclaration(boolean b) {
|
||||
mySerializationHandler.setOmitXMLDeclaration(b);
|
||||
}
|
||||
|
||||
public void setStandalone(String standalone) {
|
||||
mySerializationHandler.setStandalone(standalone);
|
||||
}
|
||||
|
||||
public void setVersion(String version) {
|
||||
mySerializationHandler.setVersion(version);
|
||||
}
|
||||
|
||||
public String getOutputProperty(String name) {
|
||||
return mySerializationHandler.getOutputProperty(name);
|
||||
}
|
||||
|
||||
public String getOutputPropertyDefault(String name) {
|
||||
return mySerializationHandler.getOutputPropertyDefault(name);
|
||||
}
|
||||
|
||||
public void setOutputProperty(String name, String val) {
|
||||
mySerializationHandler.setOutputProperty(name, val);
|
||||
}
|
||||
|
||||
public void setOutputPropertyDefault(String name, String val) {
|
||||
mySerializationHandler.setOutputPropertyDefault(name, val);
|
||||
}
|
||||
|
||||
public void elementDecl(String name, String model) throws SAXException {
|
||||
mySerializationHandler.elementDecl(name, model);
|
||||
}
|
||||
|
||||
public void attributeDecl(String eName, String aName, String type, String mode, String value) throws SAXException {
|
||||
mySerializationHandler.attributeDecl(eName, aName, type, mode, value);
|
||||
}
|
||||
|
||||
public void internalEntityDecl(String name, String value) throws SAXException {
|
||||
mySerializationHandler.internalEntityDecl(name, value);
|
||||
}
|
||||
|
||||
public void externalEntityDecl(String name, String publicId, String systemId) throws SAXException {
|
||||
mySerializationHandler.externalEntityDecl(name, publicId, systemId);
|
||||
}
|
||||
|
||||
public void notationDecl(String name, String publicId, String systemId) throws SAXException {
|
||||
mySerializationHandler.notationDecl(name, publicId, systemId);
|
||||
}
|
||||
|
||||
public void unparsedEntityDecl(String name, String publicId, String systemId, String notationName) throws SAXException {
|
||||
mySerializationHandler.unparsedEntityDecl(name, publicId, systemId, notationName);
|
||||
}
|
||||
|
||||
public void warning(SAXParseException exception) throws SAXException {
|
||||
mySerializationHandler.warning(exception);
|
||||
}
|
||||
|
||||
public void error(SAXParseException exception) throws SAXException {
|
||||
mySerializationHandler.error(exception);
|
||||
}
|
||||
|
||||
public void fatalError(SAXParseException exception) throws SAXException {
|
||||
mySerializationHandler.fatalError(exception);
|
||||
}
|
||||
|
||||
public void setOutputStream(OutputStream output) {
|
||||
mySerializationHandler.setOutputStream(output);
|
||||
}
|
||||
|
||||
public OutputStream getOutputStream() {
|
||||
return mySerializationHandler.getOutputStream();
|
||||
}
|
||||
|
||||
public void setWriter(Writer writer) {
|
||||
mySerializationHandler.setWriter(writer);
|
||||
}
|
||||
|
||||
public Writer getWriter() {
|
||||
return mySerializationHandler.getWriter();
|
||||
}
|
||||
|
||||
public void setOutputFormat(Properties format) {
|
||||
mySerializationHandler.setOutputFormat(format);
|
||||
}
|
||||
|
||||
public Properties getOutputFormat() {
|
||||
return mySerializationHandler.getOutputFormat();
|
||||
}
|
||||
|
||||
public ContentHandler asContentHandler() throws IOException {
|
||||
return mySerializationHandler.asContentHandler();
|
||||
}
|
||||
|
||||
public DOMSerializer asDOMSerializer() throws IOException {
|
||||
return mySerializationHandler.asDOMSerializer();
|
||||
}
|
||||
|
||||
public boolean reset() {
|
||||
return mySerializationHandler.reset();
|
||||
}
|
||||
|
||||
public Object asDOM3Serializer() throws IOException {
|
||||
return mySerializationHandler.asDOM3Serializer();
|
||||
}
|
||||
}
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
package org.intellij.plugins.xsltDebugger.rt.engine.local.xalan;
|
||||
|
||||
import org.apache.xml.dtm.DTM;
|
||||
import org.apache.xml.dtm.DTMIterator;
|
||||
import org.apache.xml.dtm.ref.DTMNodeIterator;
|
||||
import org.apache.xml.serializer.ToXMLStream;
|
||||
import org.apache.xpath.objects.XNodeSet;
|
||||
import org.apache.xpath.objects.XObject;
|
||||
import org.apache.xpath.objects.XRTreeFrag;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.Value;
|
||||
|
||||
import javax.xml.transform.SourceLocator;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import java.io.StringWriter;
|
||||
import java.util.ArrayList;
|
||||
|
||||
class XObjectValue implements Value {
|
||||
private String myTypeString;
|
||||
private Object myValue;
|
||||
|
||||
public XObjectValue(XObject value) {
|
||||
try {
|
||||
if (value != null) {
|
||||
myTypeString = value.getTypeString().replaceAll("#", "");
|
||||
} else {
|
||||
myTypeString = "undefined";
|
||||
}
|
||||
|
||||
if (value instanceof XNodeSet) {
|
||||
final ArrayList<Node> nodes = new ArrayList<Node>();
|
||||
final DTMIterator v = value.mutableNodeset();
|
||||
for (int i = 0; i < v.getLength(); i++) {
|
||||
final int p = v.item(i);
|
||||
final DTM dtm = v.getDTM(p);
|
||||
if (dtm == null) continue;
|
||||
|
||||
final SourceLocator loc = dtm.getSourceLocatorFor(p);
|
||||
nodes.add(new Node(loc != null ? loc.getSystemId() : null, loc != null ? loc.getLineNumber() : -1, XalanSupport.getPath(dtm, p),
|
||||
dtm.getStringValue(p).toString()));
|
||||
}
|
||||
|
||||
myValue = new NodeSet(value.str(), nodes);
|
||||
} else if (value instanceof XRTreeFrag) {
|
||||
final org.w3c.dom.Node node = ((DTMNodeIterator)value.object()).nextNode();
|
||||
if (node == null) {
|
||||
myValue = "";
|
||||
} else {
|
||||
try {
|
||||
final ToXMLStream stream = new ToXMLStream();
|
||||
final StringWriter writer = new StringWriter();
|
||||
stream.setWriter(writer);
|
||||
stream.setOmitXMLDeclaration(true);
|
||||
stream.serialize(node);
|
||||
|
||||
myValue = writer.toString();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
myValue = "???";
|
||||
}
|
||||
}
|
||||
} else if (value != null) {
|
||||
myValue = value.object();
|
||||
}
|
||||
} catch (TransformerException e) {
|
||||
myTypeString = "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
public Object getValue() {
|
||||
return myValue;
|
||||
}
|
||||
|
||||
public Type getType() {
|
||||
try {
|
||||
return XPathType.valueOf(myTypeString.toUpperCase());
|
||||
} catch (IllegalArgumentException e) {
|
||||
return new ObjectType(myTypeString);
|
||||
}
|
||||
}
|
||||
}
|
||||
+182
@@ -0,0 +1,182 @@
|
||||
package org.intellij.plugins.xsltDebugger.rt.engine.local.xalan;
|
||||
|
||||
import org.apache.xalan.templates.ElemLiteralResult;
|
||||
import org.apache.xalan.templates.ElemParam;
|
||||
import org.apache.xalan.templates.ElemTemplateElement;
|
||||
import org.apache.xalan.templates.ElemVariable;
|
||||
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.dtm.ref.DTMNodeProxy;
|
||||
import org.apache.xml.utils.PrefixResolver;
|
||||
import org.apache.xml.utils.PrefixResolverDefault;
|
||||
import org.apache.xpath.XPath;
|
||||
import org.apache.xpath.XPathContext;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.Debugger;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.Value;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.local.AbstractFrame;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.local.VariableComparator;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.local.VariableImpl;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
import javax.xml.transform.TransformerException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Vector;
|
||||
|
||||
class XalanStyleFrame extends AbstractFrame<Debugger.StyleFrame> implements Debugger.StyleFrame {
|
||||
private final boolean myWithSourceFrame;
|
||||
|
||||
private final TransformerImpl myTransformer;
|
||||
private final ElemTemplateElement myCurrentElement;
|
||||
private final XPathContext myContext;
|
||||
private final int myCurrentNode;
|
||||
|
||||
private final int myLineNumber;
|
||||
private final String myURI;
|
||||
private final String myInstr;
|
||||
|
||||
public XalanStyleFrame(TracerEvent ev, Debugger.StyleFrame currentFrame, boolean withSourceFrame) {
|
||||
super(currentFrame);
|
||||
myWithSourceFrame = withSourceFrame;
|
||||
|
||||
myInstr = getInstruction(ev.m_styleNode);
|
||||
|
||||
myLineNumber = ev.m_styleNode.getLineNumber();
|
||||
if (ev.m_styleNode.getSystemId() != null) {
|
||||
myURI = ev.m_styleNode.getSystemId();
|
||||
} else if (currentFrame != null && currentFrame.getURI() != null) {
|
||||
myURI = currentFrame.getURI();
|
||||
} else {
|
||||
myURI = ev.m_processor.getStylesheet().getSystemId();
|
||||
}
|
||||
myTransformer = ev.m_processor;
|
||||
|
||||
myCurrentElement = myTransformer.getCurrentElement();
|
||||
myContext = ev.m_processor.getXPathContext();
|
||||
myCurrentNode = myContext.getCurrentNode();
|
||||
}
|
||||
|
||||
private void addVariable(ElemVariable variable, boolean global, List<Debugger.Variable> variables) {
|
||||
final Debugger.Variable.Kind kind = variable instanceof ElemParam ?
|
||||
Debugger.Variable.Kind.PARAMETER : Debugger.Variable.Kind.VARIABLE;
|
||||
|
||||
assert global == variable.getIsTopLevel() : global + " vs. " + variable.getIsTopLevel() + " (" + variable.getName() + ")";
|
||||
|
||||
final String name = variable.getName().getLocalName();
|
||||
try {
|
||||
final Value value = new XObjectValue(variable.getValue(myTransformer, myCurrentNode));
|
||||
|
||||
variables.add(new VariableImpl(name, value, global, kind, variable.getSystemId(), variable.getLineNumber()));
|
||||
} catch (TransformerException e) {
|
||||
// TODO
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isWithSourceFrame() {
|
||||
return myWithSourceFrame;
|
||||
}
|
||||
|
||||
public String getInstruction() {
|
||||
return myInstr;
|
||||
}
|
||||
|
||||
public List<Debugger.Variable> getVariables() {
|
||||
return collectVariables();
|
||||
}
|
||||
|
||||
private List<Debugger.Variable> collectVariables() {
|
||||
List<Debugger.Variable> variables = new ArrayList<Debugger.Variable>();
|
||||
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
final Vector<ElemVariable> globals = myTransformer.getStylesheet().getVariablesAndParamsComposed();
|
||||
for (ElemVariable variable : globals) {
|
||||
addVariable(variable, true, variables);
|
||||
}
|
||||
|
||||
ElemTemplateElement p = myCurrentElement;
|
||||
while (p != null) {
|
||||
ElemTemplateElement s = p;
|
||||
while ((s = s.getPreviousSiblingElem()) != null) {
|
||||
if (s instanceof ElemVariable) {
|
||||
final ElemVariable variable = (ElemVariable)s;
|
||||
if (variable.getIsTopLevel()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
addVariable(variable, false, variables);
|
||||
}
|
||||
}
|
||||
p = p.getParentElem();
|
||||
}
|
||||
|
||||
Collections.sort(variables, VariableComparator.INSTANCE);
|
||||
|
||||
return variables;
|
||||
}
|
||||
|
||||
public String getURI() {
|
||||
return myURI;
|
||||
}
|
||||
|
||||
public int getLineNumber() {
|
||||
return myLineNumber;
|
||||
}
|
||||
|
||||
public Value eval(String expr) throws Debugger.EvaluationException {
|
||||
try {
|
||||
final DTMIterator context = myTransformer.getContextNodeList();
|
||||
|
||||
final int ctx;
|
||||
final DTM dtm = context.getDTM(myCurrentNode);
|
||||
if (dtm.getDocumentRoot(myCurrentNode) == myCurrentNode) {
|
||||
ctx = dtm.getFirstChild(myCurrentNode);
|
||||
} else {
|
||||
ctx = myCurrentNode;
|
||||
}
|
||||
|
||||
final DTMNodeProxy c = new DTMNodeProxy(dtm, ctx);
|
||||
final PrefixResolver prefixResolver = new PrefixResolverDefault(c) {
|
||||
public String getNamespaceForPrefix(String prefix, Node context) {
|
||||
if (context instanceof DTMNodeProxy) {
|
||||
final DTMNodeProxy proxy = (DTMNodeProxy)context;
|
||||
final DTM dtm = proxy.getDTM();
|
||||
int p = proxy.getDTMNodeNumber();
|
||||
while (p != DTM.NULL) {
|
||||
int nsNode = dtm.getFirstNamespaceNode(p, true);
|
||||
while (nsNode != DTM.NULL) {
|
||||
final String s = dtm.getLocalName(nsNode);
|
||||
if (s.equals(prefix)) {
|
||||
return dtm.getNodeValue(nsNode);
|
||||
}
|
||||
nsNode = dtm.getNextNamespaceNode(p, nsNode, true);
|
||||
}
|
||||
p = dtm.getParent(p);
|
||||
}
|
||||
}
|
||||
return super.getNamespaceForPrefix(prefix, context);
|
||||
}
|
||||
};
|
||||
|
||||
final XPath xPath = new XPath(expr, myCurrentElement, prefixResolver, XPath.SELECT, myTransformer.getErrorListener());
|
||||
return new XObjectValue(xPath.execute(myContext, myCurrentNode, myCurrentElement));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
final String message = e.getMessage();
|
||||
throw new Debugger.EvaluationException(message != null ? message : e.getClass().getSimpleName());
|
||||
}
|
||||
}
|
||||
|
||||
static String getInstruction(ElemTemplateElement node) {
|
||||
final String name = node.getNodeName();
|
||||
if (node instanceof ElemLiteralResult) {
|
||||
return name;
|
||||
} else if (name != null && name.indexOf(':') == -1) {
|
||||
return "xsl:" + name;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
}
|
||||
+123
@@ -0,0 +1,123 @@
|
||||
package org.intellij.plugins.xsltDebugger.rt.engine.local.xalan;
|
||||
|
||||
import org.apache.xalan.processor.TransformerFactoryImpl;
|
||||
import org.apache.xalan.transformer.TransformerImpl;
|
||||
import org.apache.xml.dtm.DTM;
|
||||
import org.apache.xml.utils.DefaultErrorHandler;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.DebuggerStoppedException;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.local.LocalDebugger;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import java.util.TooManyListenersException;
|
||||
|
||||
/*
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: sweinreuter
|
||||
* Date: 12.01.2009
|
||||
*/
|
||||
public class XalanSupport {
|
||||
public static boolean init(Transformer transformer, LocalDebugger dbg) {
|
||||
if (transformer instanceof TransformerImpl) {
|
||||
try {
|
||||
System.out.println("XALAN: " +
|
||||
Class.forName("org.apache.xalan.Version", true, transformer.getClass().getClassLoader()).getMethod("getVersion")
|
||||
.invoke(null));
|
||||
final TransformerImpl tr = (TransformerImpl)transformer;
|
||||
|
||||
tr.setErrorListener(new DefaultErrorHandler(false) {
|
||||
@Override
|
||||
public void fatalError(TransformerException exception) throws TransformerException {
|
||||
if (!(exception.getCause() instanceof DebuggerStoppedException)) {
|
||||
super.fatalError(exception);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
tr.getTraceManager().addTraceListener(new XalanTraceListener(dbg, tr));
|
||||
} catch (TooManyListenersException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static TransformerFactory createTransformerFactory() {
|
||||
final TransformerFactoryImpl factory = new TransformerFactoryImpl();
|
||||
prepareFactory(factory);
|
||||
return factory;
|
||||
}
|
||||
|
||||
public static TransformerFactory prepareFactory(TransformerFactory factory) {
|
||||
try {
|
||||
factory.setAttribute("http://xml.apache.org/xalan/properties/source-location", Boolean.TRUE);
|
||||
factory.setAttribute("http://xml.apache.org/xalan/features/optimize", Boolean.FALSE);
|
||||
} catch (Exception e) {
|
||||
// ignore
|
||||
}
|
||||
return factory;
|
||||
}
|
||||
|
||||
public static String getPath(DTM dtm, int node) {
|
||||
String pre;
|
||||
switch (dtm.getNodeType(node)) {
|
||||
case Node.DOCUMENT_NODE:
|
||||
return "/";
|
||||
case Node.ELEMENT_NODE:
|
||||
pre = getPath(dtm, dtm.getParent(node));
|
||||
return (pre.equals("/") ? "" : pre) +
|
||||
"/" + dtm.getNodeName(node) + "[" + getNumberSimple(dtm, node) + "]";
|
||||
case Node.ATTRIBUTE_NODE:
|
||||
return getPath(dtm, dtm.getParent(node)) + "/@" + dtm.getNodeNameX(node);
|
||||
case Node.TEXT_NODE:
|
||||
pre = getPath(dtm, dtm.getParent(node));
|
||||
return (pre.equals("/") ? "" : pre) +
|
||||
"/text()[" + getNumberSimple(dtm, node) + "]";
|
||||
case Node.COMMENT_NODE:
|
||||
pre = getPath(dtm, dtm.getParent(node));
|
||||
return (pre.equals("/") ? "" : pre) +
|
||||
"/comment()[" + getNumberSimple(dtm, node) + "]";
|
||||
case Node.PROCESSING_INSTRUCTION_NODE:
|
||||
pre = getPath(dtm, dtm.getParent(node));
|
||||
return (pre.equals("/") ? "" : pre) +
|
||||
"/processing-instruction()[" + getNumberSimple(dtm, node) + "]";
|
||||
}
|
||||
return "?";
|
||||
}
|
||||
|
||||
private static int getNumberSimple(DTM dtm, int node) {
|
||||
final String localName = dtm.getLocalName(node);
|
||||
|
||||
String uri = dtm.getNamespaceURI(node);
|
||||
if (uri == null) uri = "";
|
||||
|
||||
final short type = dtm.getNodeType(node);
|
||||
|
||||
int i = 1;
|
||||
int p = node;
|
||||
while ((p = dtm.getPreviousSibling(p)) != DTM.NULL) {
|
||||
if (dtm.getNodeType(p) == type) {
|
||||
switch (type) {
|
||||
case Node.TEXT_NODE:
|
||||
case Node.COMMENT_NODE:
|
||||
case Node.PROCESSING_INSTRUCTION_NODE:
|
||||
i++;
|
||||
break;
|
||||
default:
|
||||
if (localName.equals(dtm.getLocalName(p)) && uri.equals(dtm.getNamespaceURI(p))) {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
}
|
||||
+162
@@ -0,0 +1,162 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
+153
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* 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.remote;
|
||||
|
||||
import com.icl.saxon.TransformerFactoryImpl;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.Debugger;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.Value;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.local.LocalDebugger;
|
||||
|
||||
import javax.rmi.PortableRemoteObject;
|
||||
import javax.xml.transform.Result;
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.TransformerConfigurationException;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import javax.xml.transform.stream.StreamSource;
|
||||
import java.io.File;
|
||||
import java.rmi.NotBoundException;
|
||||
import java.rmi.RemoteException;
|
||||
import java.rmi.registry.LocateRegistry;
|
||||
import java.rmi.registry.Registry;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: sweinreuter
|
||||
* Date: 23.05.2007
|
||||
*/
|
||||
public class DebuggerServer extends PortableRemoteObject implements RemoteDebugger {
|
||||
private static final String XSLT_DEBUGGER = "XsltDebugger";
|
||||
public static final int PORT = 34275;
|
||||
|
||||
private final Debugger myDebugger;
|
||||
private final RemoteBreakpointManagerImpl myBreakpointManager;
|
||||
private final RemoteEventQueueImpl myEventQueue;
|
||||
private final int myPort;
|
||||
|
||||
private DebuggerServer(Transformer transformer, Source xml, Result out, int port)
|
||||
throws TransformerConfigurationException, RemoteException {
|
||||
myPort = port;
|
||||
myDebugger = new LocalDebugger(transformer, xml, out) {
|
||||
@Override
|
||||
public void stop(boolean b) {
|
||||
try {
|
||||
super.stop(b);
|
||||
} finally {
|
||||
if (b) System.exit(0);
|
||||
}
|
||||
}
|
||||
};
|
||||
myBreakpointManager = new RemoteBreakpointManagerImpl(myDebugger.getBreakpointManager());
|
||||
myEventQueue = new RemoteEventQueueImpl(myDebugger.getEventQueue());
|
||||
}
|
||||
|
||||
public static DebuggerServer create(Transformer xsl, Source xml, Result out, int port)
|
||||
throws TransformerConfigurationException, RemoteException {
|
||||
final DebuggerServer server = new DebuggerServer(xsl, xml, out, port);
|
||||
final Registry registry = LocateRegistry.createRegistry(port);
|
||||
registry.rebind(XSLT_DEBUGGER, server);
|
||||
return server;
|
||||
}
|
||||
|
||||
public static DebuggerServer create(File f, File x) throws TransformerConfigurationException, RemoteException {
|
||||
return create(new TransformerFactoryImpl().newTransformer(new StreamSource(f)), new StreamSource(x), new StreamResult(), PORT);
|
||||
}
|
||||
|
||||
public void stop(boolean force) throws RemoteException {
|
||||
myDebugger.stop(force);
|
||||
try {
|
||||
LocateRegistry.getRegistry(myPort).unbind(XSLT_DEBUGGER);
|
||||
} catch (NotBoundException e) {
|
||||
// hu?
|
||||
}
|
||||
}
|
||||
|
||||
public boolean ping() throws RemoteException {
|
||||
return myDebugger.ping();
|
||||
}
|
||||
|
||||
public Debugger.State waitForStateChange(Debugger.State state) throws RemoteException {
|
||||
return myDebugger.waitForStateChange(state);
|
||||
}
|
||||
|
||||
public boolean waitForDebuggee() throws RemoteException {
|
||||
return myDebugger.waitForDebuggee();
|
||||
}
|
||||
|
||||
public boolean start() throws RemoteException {
|
||||
return myDebugger.start();
|
||||
}
|
||||
|
||||
public void step() throws RemoteException {
|
||||
myDebugger.step();
|
||||
}
|
||||
|
||||
public void stepInto() throws RemoteException {
|
||||
myDebugger.stepInto();
|
||||
}
|
||||
|
||||
public void resume() throws RemoteException {
|
||||
myDebugger.resume();
|
||||
}
|
||||
|
||||
public boolean isStopped() throws RemoteException {
|
||||
return myDebugger.isStopped();
|
||||
}
|
||||
|
||||
public Frame getCurrentFrame() throws RemoteException {
|
||||
return RemoteFrameImpl.create(myDebugger.getCurrentFrame());
|
||||
}
|
||||
|
||||
public Frame getSourceFrame() throws RemoteException {
|
||||
return RemoteFrameImpl.create(myDebugger.getSourceFrame());
|
||||
}
|
||||
|
||||
public Value eval(String expr) throws RemoteException, Debugger.EvaluationException {
|
||||
return getCurrentFrame().eval(expr);
|
||||
}
|
||||
|
||||
public List<Variable> getGlobalVariables() throws RemoteException {
|
||||
return RemoteVariableImpl.convert(myDebugger.getGlobalVariables());
|
||||
}
|
||||
|
||||
public RemoteBreakpointManager getBreakpointManager() throws RemoteException {
|
||||
return myBreakpointManager;
|
||||
}
|
||||
|
||||
public Debugger.State getState() throws RemoteException {
|
||||
return myDebugger.getState();
|
||||
}
|
||||
|
||||
public void pause() throws RemoteException {
|
||||
myDebugger.pause();
|
||||
}
|
||||
|
||||
public EventQueue getEventQueue() throws RemoteException {
|
||||
return myEventQueue;
|
||||
}
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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.remote;
|
||||
|
||||
import java.rmi.Remote;
|
||||
import java.rmi.RemoteException;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: sweinreuter
|
||||
* Date: 29.05.2007
|
||||
*/
|
||||
public interface RemoteBreakpoint extends Remote {
|
||||
String getUri() throws RemoteException;
|
||||
|
||||
int getLine() throws RemoteException;
|
||||
|
||||
boolean isEnabled() throws RemoteException;
|
||||
|
||||
void setEnabled(boolean b) throws RemoteException;
|
||||
|
||||
String getCondition() throws RemoteException;
|
||||
|
||||
void setCondition(String expr) throws RemoteException;
|
||||
|
||||
String getLogMessage() throws RemoteException;
|
||||
|
||||
void setLogMessage(String expr) throws RemoteException;
|
||||
|
||||
String getTraceMessage() throws RemoteException;
|
||||
|
||||
void setTraceMessage(String expr) throws RemoteException;
|
||||
|
||||
boolean isSuspend() throws RemoteException;
|
||||
|
||||
void setSuspend(boolean suspend) throws RemoteException;
|
||||
}
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* 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.remote;
|
||||
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.Breakpoint;
|
||||
|
||||
import javax.rmi.PortableRemoteObject;
|
||||
import java.rmi.RemoteException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: sweinreuter
|
||||
* Date: 29.05.2007
|
||||
*/
|
||||
class RemoteBreakpointImpl extends PortableRemoteObject implements RemoteBreakpoint {
|
||||
private final Breakpoint myBreakpoint;
|
||||
|
||||
public RemoteBreakpointImpl(Breakpoint breakpoint) throws RemoteException {
|
||||
myBreakpoint = breakpoint;
|
||||
}
|
||||
|
||||
public String getUri() throws RemoteException {
|
||||
return myBreakpoint.getUri();
|
||||
}
|
||||
|
||||
public int getLine() throws RemoteException {
|
||||
return myBreakpoint.getLine();
|
||||
}
|
||||
|
||||
public boolean isEnabled() throws RemoteException {
|
||||
return myBreakpoint.isEnabled();
|
||||
}
|
||||
|
||||
public String getCondition() {
|
||||
return myBreakpoint.getCondition();
|
||||
}
|
||||
|
||||
public String getLogMessage() {
|
||||
return myBreakpoint.getLogMessage();
|
||||
}
|
||||
|
||||
public void setCondition(String expr) {
|
||||
myBreakpoint.setCondition(expr);
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
myBreakpoint.setEnabled(enabled);
|
||||
}
|
||||
|
||||
public void setLogMessage(String expr) {
|
||||
myBreakpoint.setLogMessage(expr);
|
||||
}
|
||||
|
||||
public String getTraceMessage() throws RemoteException {
|
||||
return myBreakpoint.getTraceMessage();
|
||||
}
|
||||
|
||||
public void setTraceMessage(String expr) throws RemoteException {
|
||||
myBreakpoint.setTraceMessage(expr);
|
||||
}
|
||||
|
||||
public boolean isSuspend() {
|
||||
return myBreakpoint.isSuspend();
|
||||
}
|
||||
|
||||
public void setSuspend(boolean suspend) {
|
||||
myBreakpoint.setSuspend(suspend);
|
||||
}
|
||||
|
||||
public static List<RemoteBreakpoint> convert(List<Breakpoint> list) throws RemoteException {
|
||||
final ArrayList<RemoteBreakpoint> breakpoints = new ArrayList<RemoteBreakpoint>(list.size());
|
||||
for (Breakpoint breakpoint : list) {
|
||||
breakpoints.add(new RemoteBreakpointImpl(breakpoint));
|
||||
}
|
||||
return breakpoints;
|
||||
}
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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.remote;
|
||||
|
||||
import java.io.File;
|
||||
import java.rmi.Remote;
|
||||
import java.rmi.RemoteException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: sweinreuter
|
||||
* Date: 24.05.2007
|
||||
*/
|
||||
public interface RemoteBreakpointManager extends Remote {
|
||||
RemoteBreakpoint setBreakpoint(File file, int line) throws RemoteException;
|
||||
|
||||
RemoteBreakpoint setBreakpoint(String uri, int line) throws RemoteException;
|
||||
|
||||
void removeBreakpoint(String uri, int line) throws RemoteException;
|
||||
|
||||
List<RemoteBreakpoint> getBreakpoints() throws RemoteException;
|
||||
|
||||
RemoteBreakpoint getBreakpoint(String uri, int lineNumber) throws RemoteException;
|
||||
}
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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.remote;
|
||||
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.BreakpointManager;
|
||||
|
||||
import javax.rmi.PortableRemoteObject;
|
||||
import java.io.File;
|
||||
import java.rmi.RemoteException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: sweinreuter
|
||||
* Date: 24.05.2007
|
||||
*/
|
||||
class RemoteBreakpointManagerImpl extends PortableRemoteObject implements RemoteBreakpointManager {
|
||||
private final BreakpointManager myManager;
|
||||
|
||||
public RemoteBreakpointManagerImpl(BreakpointManager manager) throws RemoteException {
|
||||
super();
|
||||
myManager = manager;
|
||||
}
|
||||
|
||||
public RemoteBreakpoint setBreakpoint(File file, int line) throws RemoteException {
|
||||
return new RemoteBreakpointImpl(myManager.setBreakpoint(file, line));
|
||||
}
|
||||
|
||||
public RemoteBreakpoint setBreakpoint(String uri, int line) throws RemoteException {
|
||||
return new RemoteBreakpointImpl(myManager.setBreakpoint(uri, line));
|
||||
}
|
||||
|
||||
public void removeBreakpoint(String uri, int line) {
|
||||
myManager.removeBreakpoint(uri, line);
|
||||
}
|
||||
|
||||
public List<RemoteBreakpoint> getBreakpoints() throws RemoteException {
|
||||
return RemoteBreakpointImpl.convert(myManager.getBreakpoints());
|
||||
}
|
||||
|
||||
public RemoteBreakpoint getBreakpoint(String uri, int lineNumber) throws RemoteException {
|
||||
return new RemoteBreakpointImpl(myManager.getBreakpoint(uri, lineNumber));
|
||||
}
|
||||
}
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* 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.remote;
|
||||
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.Debugger;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.OutputEventQueue;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.Value;
|
||||
|
||||
import java.rmi.Remote;
|
||||
import java.rmi.RemoteException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: sweinreuter
|
||||
* Date: 24.05.2007
|
||||
*/
|
||||
public interface RemoteDebugger extends Remote {
|
||||
boolean ping() throws RemoteException;
|
||||
|
||||
void stop(boolean force) throws RemoteException;
|
||||
|
||||
Debugger.State waitForStateChange(Debugger.State currentState) throws RemoteException;
|
||||
|
||||
boolean waitForDebuggee() throws RemoteException;
|
||||
|
||||
boolean start() throws RemoteException;
|
||||
|
||||
void step() throws RemoteException;
|
||||
|
||||
void stepInto() throws RemoteException;
|
||||
|
||||
void resume() throws RemoteException;
|
||||
|
||||
boolean isStopped() throws RemoteException;
|
||||
|
||||
Frame getCurrentFrame() throws RemoteException;
|
||||
|
||||
Frame getSourceFrame() throws RemoteException;
|
||||
|
||||
Value eval(String expr) throws RemoteException, Debugger.EvaluationException;
|
||||
|
||||
List<Variable> getGlobalVariables() throws RemoteException;
|
||||
|
||||
RemoteBreakpointManager getBreakpointManager() throws RemoteException;
|
||||
|
||||
Debugger.State getState() throws RemoteException;
|
||||
|
||||
void pause() throws RemoteException;
|
||||
|
||||
EventQueue getEventQueue() throws RemoteException;
|
||||
|
||||
interface EventQueue extends Remote {
|
||||
List<OutputEventQueue.NodeEvent> getEvents() throws RemoteException;
|
||||
|
||||
void setEnabled(boolean b) throws RemoteException;
|
||||
}
|
||||
|
||||
interface Frame extends Remote {
|
||||
int getLineNumber() throws RemoteException;
|
||||
|
||||
String getURI() throws RemoteException;
|
||||
|
||||
Frame getNext() throws RemoteException;
|
||||
|
||||
Frame getPrevious() throws RemoteException;
|
||||
|
||||
String getXPath() throws RemoteException;
|
||||
|
||||
Value eval(String expr) throws RemoteException, Debugger.EvaluationException;
|
||||
|
||||
List<Variable> getVariables() throws RemoteException;
|
||||
|
||||
String getInstruction() throws RemoteException;
|
||||
}
|
||||
|
||||
public interface Variable extends Remote {
|
||||
boolean isGlobal() throws RemoteException;
|
||||
|
||||
Debugger.Variable.Kind getKind() throws RemoteException;
|
||||
|
||||
String getName() throws RemoteException;
|
||||
|
||||
Value getValue() throws RemoteException;
|
||||
|
||||
String getURI() throws RemoteException;
|
||||
|
||||
int getLineNumber() throws RemoteException;
|
||||
}
|
||||
}
|
||||
+545
@@ -0,0 +1,545 @@
|
||||
/*
|
||||
* 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.remote;
|
||||
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.*;
|
||||
|
||||
import java.io.EOFException;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.SocketException;
|
||||
import java.rmi.Naming;
|
||||
import java.rmi.NotBoundException;
|
||||
import java.rmi.RemoteException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: sweinreuter
|
||||
* Date: 23.05.2007
|
||||
*/
|
||||
public class RemoteDebuggerClient implements Debugger {
|
||||
private final RemoteDebugger myRemote;
|
||||
private final BreakpointManager myBreakpointManager;
|
||||
private final OutputEventQueue myEventQueue;
|
||||
|
||||
public RemoteDebuggerClient(int port) throws IOException, NotBoundException {
|
||||
myRemote = (RemoteDebugger)Naming.lookup("rmi://127.0.0.1:" + port + "/XsltDebugger");
|
||||
|
||||
final RemoteBreakpointManager manager = myRemote.getBreakpointManager();
|
||||
myBreakpointManager = new MyBreakpointManager(manager);
|
||||
|
||||
final RemoteDebugger.EventQueue eventQueue = myRemote.getEventQueue();
|
||||
myEventQueue = new MyOutputEventQueue(eventQueue);
|
||||
}
|
||||
|
||||
public boolean ping() {
|
||||
try {
|
||||
return myRemote.ping();
|
||||
} catch (RemoteException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public State getState() {
|
||||
try {
|
||||
return myRemote.getState();
|
||||
} catch (RemoteException e) {
|
||||
throw handleRemoteException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void stop(boolean force) {
|
||||
try {
|
||||
myRemote.stop(force);
|
||||
} catch (RemoteException e) {
|
||||
throw handleRemoteException(e);
|
||||
}
|
||||
}
|
||||
|
||||
static RuntimeException handleRemoteException(RemoteException e) {
|
||||
Throwable t = e.getCause();
|
||||
while (t != null) {
|
||||
if (t instanceof SocketException || t instanceof EOFException) {
|
||||
throw new DebuggerStoppedException();
|
||||
}
|
||||
t = t.getCause();
|
||||
}
|
||||
return e.getCause() instanceof RuntimeException ? (RuntimeException)e.getCause() : new RuntimeException(e);
|
||||
}
|
||||
|
||||
public Debugger.State waitForStateChange(State state) {
|
||||
try {
|
||||
return myRemote.waitForStateChange(state);
|
||||
} catch (RemoteException e) {
|
||||
throw handleRemoteException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean waitForDebuggee() {
|
||||
try {
|
||||
return myRemote.waitForDebuggee();
|
||||
} catch (RemoteException e) {
|
||||
throw handleRemoteException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean start() {
|
||||
try {
|
||||
return myRemote.start();
|
||||
} catch (RemoteException e) {
|
||||
throw handleRemoteException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void step() {
|
||||
try {
|
||||
myRemote.step();
|
||||
} catch (RemoteException e) {
|
||||
throw handleRemoteException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void stepInto() {
|
||||
try {
|
||||
myRemote.stepInto();
|
||||
} catch (RemoteException e) {
|
||||
throw handleRemoteException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void resume() {
|
||||
try {
|
||||
myRemote.resume();
|
||||
} catch (RemoteException e) {
|
||||
throw handleRemoteException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void pause() {
|
||||
try {
|
||||
myRemote.pause();
|
||||
} catch (RemoteException e) {
|
||||
throw handleRemoteException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isStopped() {
|
||||
try {
|
||||
return myRemote.isStopped();
|
||||
} catch (RemoteException e) {
|
||||
throw handleRemoteException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public StyleFrame getCurrentFrame() {
|
||||
try {
|
||||
return MyFrame.create(myRemote.getCurrentFrame());
|
||||
} catch (RemoteException e) {
|
||||
throw handleRemoteException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public SourceFrame getSourceFrame() {
|
||||
try {
|
||||
return MySourceFrame.create(myRemote.getSourceFrame());
|
||||
} catch (RemoteException e) {
|
||||
throw handleRemoteException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public Value eval(String expr) throws EvaluationException {
|
||||
try {
|
||||
return myRemote.eval(expr);
|
||||
} catch (RemoteException e) {
|
||||
throw handleRemoteException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public List<Variable> getGlobalVariables() {
|
||||
try {
|
||||
return MyVariable.convert(myRemote.getGlobalVariables());
|
||||
} catch (RemoteException e) {
|
||||
throw handleRemoteException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public BreakpointManager getBreakpointManager() {
|
||||
return myBreakpointManager;
|
||||
}
|
||||
|
||||
public OutputEventQueue getEventQueue() {
|
||||
return myEventQueue;
|
||||
}
|
||||
|
||||
private static class MyBreakpointManager implements BreakpointManager {
|
||||
private final RemoteBreakpointManager myManager;
|
||||
|
||||
public MyBreakpointManager(RemoteBreakpointManager manager) {
|
||||
myManager = manager;
|
||||
}
|
||||
|
||||
public Breakpoint setBreakpoint(File file, int line) {
|
||||
try {
|
||||
return new MyBreakpoint(myManager.setBreakpoint(file, line));
|
||||
} catch (RemoteException e) {
|
||||
throw handleRemoteException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public Breakpoint setBreakpoint(String uri, int line) {
|
||||
try {
|
||||
return new MyBreakpoint(myManager.setBreakpoint(uri, line));
|
||||
} catch (RemoteException e) {
|
||||
throw handleRemoteException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeBreakpoint(Breakpoint bp) {
|
||||
try {
|
||||
myManager.removeBreakpoint(bp.getUri(), bp.getLine());
|
||||
} catch (RemoteException e) {
|
||||
throw handleRemoteException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeBreakpoint(String uri, int line) {
|
||||
try {
|
||||
myManager.removeBreakpoint(uri, line);
|
||||
} catch (RemoteException e) {
|
||||
throw handleRemoteException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public List<Breakpoint> getBreakpoints() {
|
||||
try {
|
||||
final List<RemoteBreakpoint> list = myManager.getBreakpoints();
|
||||
final ArrayList<Breakpoint> breakpoints = new ArrayList<Breakpoint>(list.size());
|
||||
for (RemoteBreakpoint breakpoint : list) {
|
||||
breakpoints.add(new MyBreakpoint(breakpoint));
|
||||
}
|
||||
return breakpoints;
|
||||
} catch (RemoteException e) {
|
||||
throw handleRemoteException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public Breakpoint getBreakpoint(String uri, int lineNumber) {
|
||||
try {
|
||||
final RemoteBreakpoint breakpoint = myManager.getBreakpoint(uri, lineNumber);
|
||||
return breakpoint != null ? new MyBreakpoint(breakpoint) : null;
|
||||
} catch (RemoteException e) {
|
||||
throw handleRemoteException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static class MyBreakpoint implements Breakpoint {
|
||||
private final RemoteBreakpoint myBreakpoint;
|
||||
|
||||
public MyBreakpoint(RemoteBreakpoint breakpoint) {
|
||||
myBreakpoint = breakpoint;
|
||||
}
|
||||
|
||||
public String getUri() {
|
||||
try {
|
||||
return myBreakpoint.getUri();
|
||||
} catch (RemoteException e) {
|
||||
throw handleRemoteException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public int getLine() {
|
||||
try {
|
||||
return myBreakpoint.getLine();
|
||||
} catch (RemoteException e) {
|
||||
throw handleRemoteException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
try {
|
||||
return myBreakpoint.isEnabled();
|
||||
} catch (RemoteException e) {
|
||||
throw handleRemoteException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public String getCondition() {
|
||||
try {
|
||||
return myBreakpoint.getCondition();
|
||||
} catch (RemoteException e) {
|
||||
throw handleRemoteException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public String getLogMessage() {
|
||||
try {
|
||||
return myBreakpoint.getLogMessage();
|
||||
} catch (RemoteException e) {
|
||||
throw handleRemoteException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void setCondition(String expr) {
|
||||
try {
|
||||
myBreakpoint.setCondition(expr);
|
||||
} catch (RemoteException e) {
|
||||
throw handleRemoteException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
try {
|
||||
myBreakpoint.setEnabled(enabled);
|
||||
} catch (RemoteException e) {
|
||||
throw handleRemoteException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void setLogMessage(String expr) {
|
||||
try {
|
||||
myBreakpoint.setLogMessage(expr);
|
||||
} catch (RemoteException e) {
|
||||
throw handleRemoteException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public String getTraceMessage() {
|
||||
try {
|
||||
return myBreakpoint.getTraceMessage();
|
||||
} catch (RemoteException e) {
|
||||
throw handleRemoteException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void setTraceMessage(String expr) {
|
||||
try {
|
||||
myBreakpoint.setTraceMessage(expr);
|
||||
} catch (RemoteException e) {
|
||||
throw handleRemoteException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isSuspend() {
|
||||
try {
|
||||
return myBreakpoint.isSuspend();
|
||||
} catch (RemoteException e) {
|
||||
throw handleRemoteException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void setSuspend(boolean suspend) {
|
||||
try {
|
||||
myBreakpoint.setSuspend(suspend);
|
||||
} catch (RemoteException e) {
|
||||
throw handleRemoteException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static abstract class MyAbstractFrame<F extends Frame> implements Frame<F> {
|
||||
protected final RemoteDebugger.Frame myFrame;
|
||||
|
||||
protected MyAbstractFrame(RemoteDebugger.Frame frame) {
|
||||
myFrame = frame;
|
||||
}
|
||||
|
||||
public int getLineNumber() {
|
||||
try {
|
||||
return myFrame.getLineNumber();
|
||||
} catch (RemoteException e) {
|
||||
throw handleRemoteException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public String getURI() {
|
||||
try {
|
||||
return myFrame.getURI();
|
||||
} catch (RemoteException e) {
|
||||
throw handleRemoteException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public F getNext() {
|
||||
try {
|
||||
return createImpl(myFrame.getNext());
|
||||
} catch (RemoteException e) {
|
||||
throw handleRemoteException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public F getPrevious() {
|
||||
try {
|
||||
return createImpl(myFrame.getPrevious());
|
||||
} catch (RemoteException e) {
|
||||
throw handleRemoteException(e);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract F createImpl(RemoteDebugger.Frame frame);
|
||||
|
||||
public String getXPath() {
|
||||
try {
|
||||
return myFrame.getXPath();
|
||||
} catch (RemoteException e) {
|
||||
throw handleRemoteException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public Value eval(String expr) throws EvaluationException {
|
||||
try {
|
||||
return myFrame.eval(expr);
|
||||
} catch (RemoteException e) {
|
||||
throw handleRemoteException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public List<Variable> getVariables() {
|
||||
try {
|
||||
return MyVariable.convert(myFrame.getVariables());
|
||||
} catch (RemoteException e) {
|
||||
throw handleRemoteException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class MyFrame extends MyAbstractFrame<StyleFrame> implements StyleFrame {
|
||||
protected MyFrame(RemoteDebugger.Frame frame) {
|
||||
super(frame);
|
||||
}
|
||||
|
||||
public String getInstruction() {
|
||||
try {
|
||||
return myFrame.getInstruction();
|
||||
} catch (RemoteException e) {
|
||||
throw handleRemoteException(e);
|
||||
}
|
||||
}
|
||||
|
||||
protected StyleFrame createImpl(RemoteDebugger.Frame frame) {
|
||||
return create(frame);
|
||||
}
|
||||
|
||||
public static StyleFrame create(RemoteDebugger.Frame currentFrame) {
|
||||
return currentFrame != null ? new MyFrame(currentFrame) : null;
|
||||
}
|
||||
}
|
||||
|
||||
private static class MySourceFrame extends MyAbstractFrame<SourceFrame> implements SourceFrame {
|
||||
protected MySourceFrame(RemoteDebugger.Frame frame) {
|
||||
super(frame);
|
||||
}
|
||||
|
||||
public SourceFrame createImpl(RemoteDebugger.Frame frame) {
|
||||
return create(frame);
|
||||
}
|
||||
|
||||
public static SourceFrame create(RemoteDebugger.Frame currentFrame) {
|
||||
return currentFrame != null ? new MySourceFrame(currentFrame) : null;
|
||||
}
|
||||
}
|
||||
|
||||
private static class MyVariable implements Variable {
|
||||
private final RemoteDebugger.Variable myVariable;
|
||||
|
||||
public MyVariable(RemoteDebugger.Variable variable) {
|
||||
myVariable = variable;
|
||||
}
|
||||
|
||||
public String getURI() {
|
||||
try {
|
||||
return myVariable.getURI();
|
||||
} catch (RemoteException e) {
|
||||
throw handleRemoteException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public int getLineNumber() {
|
||||
try {
|
||||
return myVariable.getLineNumber();
|
||||
} catch (RemoteException e) {
|
||||
throw handleRemoteException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isGlobal() {
|
||||
try {
|
||||
return myVariable.isGlobal();
|
||||
} catch (RemoteException e) {
|
||||
throw handleRemoteException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public Kind getKind() {
|
||||
try {
|
||||
return myVariable.getKind();
|
||||
} catch (RemoteException e) {
|
||||
throw handleRemoteException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
try {
|
||||
return myVariable.getName();
|
||||
} catch (RemoteException e) {
|
||||
throw handleRemoteException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public Value getValue() {
|
||||
try {
|
||||
return myVariable.getValue();
|
||||
} catch (RemoteException e) {
|
||||
throw handleRemoteException(e);
|
||||
}
|
||||
}
|
||||
|
||||
static List<Variable> convert(List<RemoteDebugger.Variable> list) {
|
||||
final ArrayList<Variable> variables = new ArrayList<Variable>(list.size());
|
||||
for (final RemoteDebugger.Variable variable : list) {
|
||||
variables.add(new MyVariable(variable));
|
||||
}
|
||||
return variables;
|
||||
}
|
||||
}
|
||||
|
||||
private static class MyOutputEventQueue implements OutputEventQueue {
|
||||
private final RemoteDebugger.EventQueue myEventQueue;
|
||||
|
||||
public MyOutputEventQueue(RemoteDebugger.EventQueue eventQueue) {
|
||||
myEventQueue = eventQueue;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean b) {
|
||||
try {
|
||||
myEventQueue.setEnabled(b);
|
||||
} catch (RemoteException e) {
|
||||
throw handleRemoteException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public List<NodeEvent> getEvents() {
|
||||
try {
|
||||
return myEventQueue.getEvents();
|
||||
} catch (RemoteException e) {
|
||||
throw handleRemoteException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2002-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.remote;
|
||||
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.OutputEventQueue;
|
||||
|
||||
import javax.rmi.PortableRemoteObject;
|
||||
import java.rmi.RemoteException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: sweinreuter
|
||||
* Date: 08.06.2007
|
||||
*/
|
||||
public class RemoteEventQueueImpl extends PortableRemoteObject implements RemoteDebugger.EventQueue {
|
||||
private final OutputEventQueue myQueue;
|
||||
|
||||
public RemoteEventQueueImpl(OutputEventQueue queue) throws RemoteException {
|
||||
myQueue = queue;
|
||||
}
|
||||
|
||||
public List<OutputEventQueue.NodeEvent> getEvents() throws RemoteException {
|
||||
return myQueue.getEvents();
|
||||
}
|
||||
|
||||
public void setEnabled(boolean b) throws RemoteException {
|
||||
myQueue.setEnabled(b);
|
||||
}
|
||||
}
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* 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.remote;
|
||||
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.Debugger;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.Debugger.Frame;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.Value;
|
||||
|
||||
import javax.rmi.PortableRemoteObject;
|
||||
import java.rmi.RemoteException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: sweinreuter
|
||||
* Date: 28.05.2007
|
||||
*/
|
||||
class RemoteFrameImpl extends PortableRemoteObject implements RemoteDebugger.Frame {
|
||||
private final Frame myFrame;
|
||||
|
||||
private RemoteFrameImpl(Frame frame) throws RemoteException {
|
||||
myFrame = frame;
|
||||
}
|
||||
|
||||
public int getLineNumber() {
|
||||
return myFrame.getLineNumber();
|
||||
}
|
||||
|
||||
public String getURI() {
|
||||
return myFrame.getURI();
|
||||
}
|
||||
|
||||
public RemoteDebugger.Frame getNext() throws RemoteException {
|
||||
return create(myFrame.getNext());
|
||||
}
|
||||
|
||||
public RemoteDebugger.Frame getPrevious() throws RemoteException {
|
||||
return create(myFrame.getPrevious());
|
||||
}
|
||||
|
||||
public String getXPath() throws RemoteException {
|
||||
return ((Debugger.SourceFrame)myFrame).getXPath();
|
||||
}
|
||||
|
||||
public ValueImpl eval(String expr) throws Debugger.EvaluationException {
|
||||
final Value value = ((Debugger.StyleFrame)myFrame).eval(expr);
|
||||
return new ValueImpl(value.getValue(), value.getType());
|
||||
}
|
||||
|
||||
public List<RemoteDebugger.Variable> getVariables() throws RemoteException {
|
||||
return RemoteVariableImpl.convert(((Debugger.StyleFrame)myFrame).getVariables());
|
||||
}
|
||||
|
||||
public String getInstruction() throws RemoteException {
|
||||
return ((Debugger.StyleFrame)myFrame).getInstruction();
|
||||
}
|
||||
|
||||
public static RemoteFrameImpl create(Frame frame) throws RemoteException {
|
||||
return frame != null ? new RemoteFrameImpl(frame) : null;
|
||||
}
|
||||
}
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* 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.remote;
|
||||
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.Debugger;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.Value;
|
||||
|
||||
import javax.rmi.PortableRemoteObject;
|
||||
import java.rmi.RemoteException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: sweinreuter
|
||||
* Date: 28.05.2007
|
||||
*/
|
||||
class RemoteVariableImpl extends PortableRemoteObject implements RemoteDebugger.Variable {
|
||||
private final Debugger.Variable myVariable;
|
||||
|
||||
public RemoteVariableImpl(Debugger.Variable variable) throws RemoteException {
|
||||
myVariable = variable;
|
||||
}
|
||||
|
||||
public String getURI() throws RemoteException {
|
||||
return myVariable.getURI();
|
||||
}
|
||||
|
||||
public int getLineNumber() throws RemoteException {
|
||||
return myVariable.getLineNumber();
|
||||
}
|
||||
|
||||
public boolean isGlobal() {
|
||||
return myVariable.isGlobal();
|
||||
}
|
||||
|
||||
public Debugger.Variable.Kind getKind() throws RemoteException {
|
||||
return myVariable.getKind();
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return myVariable.getName();
|
||||
}
|
||||
|
||||
public Value getValue() {
|
||||
final Value value = myVariable.getValue();
|
||||
return new ValueImpl(value.getValue(), value.getType());
|
||||
}
|
||||
|
||||
static List<RemoteDebugger.Variable> convert(List<Debugger.Variable> list) throws RemoteException {
|
||||
final ArrayList<RemoteDebugger.Variable> variables = new ArrayList<RemoteDebugger.Variable>(list.size());
|
||||
for (final Debugger.Variable variable : list) {
|
||||
variables.add(new RemoteVariableImpl(variable));
|
||||
}
|
||||
return variables;
|
||||
}
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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.remote;
|
||||
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.Value;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: sweinreuter
|
||||
* Date: 28.05.2007
|
||||
*/
|
||||
class ValueImpl implements Value {
|
||||
private final Serializable myValue;
|
||||
private final Type myType;
|
||||
|
||||
public ValueImpl(Object value, Type type) {
|
||||
if (value instanceof Serializable) {
|
||||
myValue = (Serializable)value;
|
||||
} else {
|
||||
myValue = String.valueOf(value);
|
||||
}
|
||||
myType = type;
|
||||
}
|
||||
|
||||
public Serializable getValue() {
|
||||
return myValue;
|
||||
}
|
||||
|
||||
public Type getType() {
|
||||
return myType;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module relativePaths="true" type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_5" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/lib" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="jdk" jdkName="1.5" jdkType="JavaSDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="module" module-name="xslt-rt" />
|
||||
<orderEntry type="module-library">
|
||||
<library name="RMI Stubs">
|
||||
<CLASSES>
|
||||
<root url="jar://$MODULE_DIR$/lib/rmi-stubs.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</orderEntry>
|
||||
<orderEntry type="module-library">
|
||||
<library name="Saxon-9HE">
|
||||
<CLASSES>
|
||||
<root url="jar://$MODULE_DIR$/lib/saxon9he.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</orderEntry>
|
||||
<orderEntry type="module-library">
|
||||
<library name="Saxon-6.5.5">
|
||||
<CLASSES>
|
||||
<root url="jar://$MODULE_DIR$/lib/saxon.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</orderEntry>
|
||||
<orderEntry type="module-library">
|
||||
<library name="Xalan-2.7.1">
|
||||
<CLASSES>
|
||||
<root url="jar://$MODULE_DIR$/lib/xalan.jar!/" />
|
||||
<root url="jar://$MODULE_DIR$/lib/serializer.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</orderEntry>
|
||||
<orderEntry type="library" name="Trove4j" level="project" />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
<idea-plugin version="2" url="http://www.jetbrains.net/confluence/display/CONTEST/XSLT-Debugger">
|
||||
<name>XSLT-Debugger</name>
|
||||
<id>XSLT-Debugger</id>
|
||||
|
||||
<description><![CDATA[
|
||||
Interactive XSLT Debugger. Allows debugging of XSLT stylesheets in IntelliJ IDEA.
|
||||
]]></description>
|
||||
|
||||
<version>1.4</version>
|
||||
<vendor email="sascha.weinreuter@cit.de">Sascha Weinreuter</vendor>
|
||||
<idea-version since-build="96.1"/>
|
||||
|
||||
<depends>XPathView</depends>
|
||||
|
||||
<change-notes>
|
||||
Xalan Support. To debug with Xalan instead of SAXON, a supported Xalan version (2.7.x) should be present in the
|
||||
classpath or "-Dxslt.transformer.type=xalan" should be added as VM argument for the run configuration. Debugging
|
||||
with SAXON can be forced by adding "-Dxslt.transformer.type=saxon".
|
||||
</change-notes>
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<xdebugger.breakpointType implementation="org.intellij.plugins.xsltDebugger.XsltBreakpointType"/>
|
||||
|
||||
<programRunner implementation="org.intellij.plugins.xsltDebugger.XsltDebuggerRunner"/>
|
||||
</extensions>
|
||||
|
||||
<extensions defaultExtensionNs="XPathView">
|
||||
<xsltRunnerExtension implementation="org.intellij.plugins.xsltDebugger.XsltDebuggerExtension"/>
|
||||
</extensions>
|
||||
|
||||
<helpset file="help.jar" path="/Help.hs"/>
|
||||
</idea-plugin>
|
||||
@@ -0,0 +1,53 @@
|
||||
package org.intellij.plugins.xsltDebugger;
|
||||
|
||||
import com.intellij.codeInsight.intention.IntentionAction;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.xml.XmlElement;
|
||||
import com.intellij.psi.xml.XmlTag;
|
||||
import org.intellij.lang.xpath.XPathFile;
|
||||
import org.intellij.lang.xpath.context.VariableContext;
|
||||
import org.intellij.lang.xpath.context.XPathQuickFixFactoryImpl;
|
||||
import org.intellij.lang.xpath.psi.XPathElement;
|
||||
import org.intellij.lang.xpath.psi.XPathVariableReference;
|
||||
import org.intellij.lang.xpath.validation.inspections.quickfix.XPathQuickFixFactory;
|
||||
import org.intellij.lang.xpath.xslt.context.XsltContextProvider;
|
||||
import org.intellij.lang.xpath.xslt.context.XsltVariableContext;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class BreakpointContext extends XsltContextProvider {
|
||||
public BreakpointContext(PsiElement contextElement) {
|
||||
super((XmlElement)contextElement);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public XPathQuickFixFactory getQuickFixFactory() {
|
||||
return XPathQuickFixFactoryImpl.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiFile[] getRelatedFiles(XPathFile file) {
|
||||
return PsiFile.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public VariableContext getVariableContext() {
|
||||
return new XsltVariableContext() {
|
||||
@Override
|
||||
@Nullable
|
||||
protected XmlTag getContextTagImpl(XPathElement element) {
|
||||
return PsiTreeUtil.getParentOfType(getContextElement(), XmlTag.class, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public IntentionAction[] getUnresolvedVariableFixes(XPathVariableReference reference) {
|
||||
return IntentionAction.EMPTY_ARRAY;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import com.intellij.execution.process.ProcessAdapter;
|
||||
import com.intellij.execution.process.ProcessEvent;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.DebuggerStoppedException;
|
||||
|
||||
/**
|
||||
* ProcessListener that manages the connection to the debugged XSLT-process
|
||||
*/
|
||||
class DebugProcessListener extends ProcessAdapter {
|
||||
private final Project myProject;
|
||||
private final int myPort;
|
||||
|
||||
public DebugProcessListener(Project project, int port) {
|
||||
myProject = project;
|
||||
myPort = port;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startNotified(ProcessEvent event) {
|
||||
final DebuggerConnector connector = new DebuggerConnector(myProject, event.getProcessHandler(), myPort);
|
||||
ApplicationManager.getApplication().executeOnPooledThread(connector);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processWillTerminate(ProcessEvent event, boolean willBeDestroyed) {
|
||||
try {
|
||||
final XsltDebuggerSession session = XsltDebuggerSession.getInstance(event.getProcessHandler());
|
||||
if (session != null) {
|
||||
session.stop();
|
||||
}
|
||||
} catch (VMPausedException e) {
|
||||
// VM is paused, no way for a "clean" shutdown
|
||||
} catch (DebuggerStoppedException e) {
|
||||
// OK
|
||||
}
|
||||
|
||||
super.processWillTerminate(event, willBeDestroyed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processTerminated(ProcessEvent event) {
|
||||
super.processTerminated(event);
|
||||
|
||||
final XsltDebuggerSession session = XsltDebuggerSession.getInstance(event.getProcessHandler());
|
||||
if (session != null) {
|
||||
session.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import com.intellij.execution.process.ProcessHandler;
|
||||
import com.intellij.execution.process.ProcessOutputTypes;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import org.intellij.plugins.xsltDebugger.impl.XsltDebugProcess;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.Debugger;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.OutputEventQueue;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.remote.RemoteDebuggerClient;
|
||||
import org.intellij.plugins.xsltDebugger.ui.StructureTabComponent;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.rmi.ConnectException;
|
||||
import java.rmi.NotBoundException;
|
||||
|
||||
/**
|
||||
* Establishes the debugger-connection to the started XSLT-process, starts the debugger-session
|
||||
* and attaches the debugger-UI.
|
||||
*/
|
||||
class DebuggerConnector implements Runnable {
|
||||
|
||||
private final Project myProject;
|
||||
private final ProcessHandler myProcess;
|
||||
private final int myPort;
|
||||
|
||||
public DebuggerConnector(Project project, ProcessHandler process, int port) {
|
||||
myProject = project;
|
||||
myProcess = process;
|
||||
myPort = port;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
final Debugger client = connect();
|
||||
if (client == null) {
|
||||
// client will be null if the process terminated prematurely for some reason. no need for an error message
|
||||
if (!myProcess.isProcessTerminated()) {
|
||||
myProcess.notifyTextAvailable("Failed to connect to debugged process. Terminating.\n", ProcessOutputTypes.SYSTEM);
|
||||
myProcess.destroyProcess();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
final XsltDebuggerSession session = XsltDebuggerSession.create(myProject, myProcess, client);
|
||||
|
||||
final XsltDebugProcess dbgp = XsltDebugProcess.getInstance(myProcess);
|
||||
assert dbgp != null;
|
||||
dbgp.init(client);
|
||||
|
||||
session.addListener(new XsltDebuggerSession.Listener() {
|
||||
@Override
|
||||
public void debuggerSuspended() {
|
||||
final OutputEventQueue queue = client.getEventQueue();
|
||||
StructureTabComponent.getInstance(myProcess).getEventModel().update(queue.getEvents());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debuggerResumed() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debuggerStopped() {
|
||||
try {
|
||||
final OutputEventQueue queue = client.getEventQueue();
|
||||
StructureTabComponent.getInstance(myProcess).getEventModel().finalUpdate(queue.getEvents());
|
||||
} catch (Exception e) {
|
||||
// can fail when debugger is manually terminated
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
session.start();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Debugger connect() {
|
||||
Throwable lastException = null;
|
||||
for (int i = 0; i < 10; i++) {
|
||||
try {
|
||||
final Debugger realClient = EDTGuard.create(new RemoteDebuggerClient(myPort), myProcess);
|
||||
myProcess.notifyTextAvailable("Connected to XSLT debugger on port " + myPort + "\n", ProcessOutputTypes.SYSTEM);
|
||||
return realClient;
|
||||
} catch (ConnectException e) {
|
||||
lastException = e;
|
||||
try {
|
||||
Thread.sleep(500);
|
||||
} catch (InterruptedException e1) {
|
||||
break;
|
||||
}
|
||||
} catch (NotBoundException e) {
|
||||
lastException = e;
|
||||
try {
|
||||
Thread.sleep(200);
|
||||
} catch (InterruptedException e1) {
|
||||
break;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
lastException = e;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (lastException != null) {
|
||||
Logger.getInstance(getClass().getName()).info("Could not connect to debugger", lastException);
|
||||
|
||||
if (lastException.getMessage() != null) {
|
||||
myProcess.notifyTextAvailable("Connection error: " + lastException.getMessage() + "\n", ProcessOutputTypes.SYSTEM);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,294 @@
|
||||
/*
|
||||
* Copyright 2002-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;
|
||||
|
||||
import com.intellij.execution.process.ProcessAdapter;
|
||||
import com.intellij.execution.process.ProcessEvent;
|
||||
import com.intellij.execution.process.ProcessHandler;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.util.Alarm;
|
||||
import gnu.trove.THashMap;
|
||||
import gnu.trove.TObjectHashingStrategy;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.Watchable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
* Utility class that tries to prevent hanging the whole IDE because some call on the EDT waits too long on the debugged
|
||||
* VM, which can especially happen when the VM has been paused (either manually or by a breakpoint on Java code).
|
||||
* <p/>
|
||||
* This is just the second best solution though as it would be better to avoid any interaction with the debuggee on the
|
||||
* EDT, but, at least right now, it seems to be more reliable against bad surprises.
|
||||
*/
|
||||
class EDTGuard implements InvocationHandler {
|
||||
// maximum time to wait for a result on the EDT
|
||||
private static final long MAX_TIMEOUT = 10 * 1000;
|
||||
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
private final Map<Object, Object> myInstanceCache = new THashMap<Object, Object>(TObjectHashingStrategy.IDENTITY);
|
||||
|
||||
private final Object myTarget;
|
||||
|
||||
private final Pair<LinkedBlockingQueue<Call>, LinkedBlockingQueue<Call.Result>> myQueue;
|
||||
private final AtomicBoolean myPausedRef;
|
||||
|
||||
private EDTGuard(Object target,
|
||||
Pair<LinkedBlockingQueue<Call>, LinkedBlockingQueue<Call.Result>> queue,
|
||||
AtomicBoolean ref) {
|
||||
myTarget = target;
|
||||
myQueue = queue;
|
||||
myPausedRef = ref;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Object invoke(Object proxy, @NotNull Method method, Object[] args) throws Throwable {
|
||||
if (SwingUtilities.isEventDispatchThread()) {
|
||||
return invokeAsync(method, args);
|
||||
}
|
||||
|
||||
return invoke(method, args);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Object invokeAsync(Method method, Object[] args) throws Throwable {
|
||||
final Call call = new Call(method, args);
|
||||
|
||||
if (!myQueue.first.offer(call)) {
|
||||
throw new VMPausedException();
|
||||
}
|
||||
|
||||
Call.Result result;
|
||||
final long start = System.currentTimeMillis();
|
||||
do {
|
||||
do {
|
||||
result = myQueue.second.poll(200, TimeUnit.MILLISECONDS);
|
||||
|
||||
if (myPausedRef.get() || result == null && System.currentTimeMillis() - start > MAX_TIMEOUT) {
|
||||
throw new VMPausedException();
|
||||
}
|
||||
}
|
||||
while (result == null);
|
||||
}
|
||||
while (!result.isFromCall(call));
|
||||
|
||||
return result.getValue();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Object invoke(@NotNull Method method, Object[] args) throws Throwable {
|
||||
try {
|
||||
return convert(method.invoke(myTarget, args));
|
||||
} catch (InvocationTargetException e) {
|
||||
final Throwable t = e.getTargetException();
|
||||
if (t instanceof RuntimeException) {
|
||||
throw (RuntimeException)t;
|
||||
} else if (t instanceof Error) {
|
||||
throw (Error)t;
|
||||
} else {
|
||||
throw t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
private Object convert(@Nullable Object o) {
|
||||
if (o != null && !(o instanceof Serializable)) {
|
||||
synchronized (myInstanceCache) {
|
||||
Object instance = myInstanceCache.get(o);
|
||||
if (instance == null) {
|
||||
final ClassLoader loader = o.getClass().getClassLoader();
|
||||
final Class<?>[] interfaces = o.getClass().getInterfaces();
|
||||
final EDTGuard guard = new EDTGuard(o, myQueue, myPausedRef);
|
||||
|
||||
myInstanceCache.put(o, instance = Proxy.newProxyInstance(loader, interfaces, guard));
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
} else if (o instanceof List) {
|
||||
final List list = (List)o;
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
final Object e = list.remove(i);
|
||||
list.add(i, convert(e));
|
||||
}
|
||||
} else if (o instanceof Set) {
|
||||
final Set set = (Set)o;
|
||||
final List s2 = new ArrayList();
|
||||
for (Iterator iterator = set.iterator(); iterator.hasNext(); ) {
|
||||
Object o1 = iterator.next();
|
||||
final Object o2 = convert(o1);
|
||||
if (o1 != o2) {
|
||||
iterator.remove();
|
||||
s2.add(o2);
|
||||
}
|
||||
}
|
||||
set.addAll(s2);
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static <T, O extends Watchable> T create(@NotNull final O target, final ProcessHandler process) {
|
||||
final Pair<LinkedBlockingQueue<Call>, LinkedBlockingQueue<Call.Result>> queue =
|
||||
Pair.create(new LinkedBlockingQueue<Call>(10), new LinkedBlockingQueue<Call.Result>());
|
||||
|
||||
final Thread thread = new Thread("Async Invocation Thread for " + process) {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
while (!Thread.currentThread().isInterrupted()) {
|
||||
final Call call = queue.first.take();
|
||||
if (call != null) {
|
||||
queue.second.offer(call.invoke());
|
||||
}
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
// break
|
||||
}
|
||||
}
|
||||
};
|
||||
thread.start();
|
||||
|
||||
final AtomicBoolean ref = new AtomicBoolean();
|
||||
final Disposable d = new Disposable() {
|
||||
boolean disposed;
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
if (!disposed) {
|
||||
disposed = true;
|
||||
|
||||
ref.set(true);
|
||||
thread.interrupt();
|
||||
}
|
||||
}
|
||||
};
|
||||
process.addProcessListener(new ProcessAdapter() {
|
||||
@Override
|
||||
public void processTerminated(ProcessEvent event) {
|
||||
synchronized (d) {
|
||||
Disposer.dispose(d);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processWillTerminate(ProcessEvent event, boolean willBeDestroyed) {
|
||||
if (!willBeDestroyed) {
|
||||
synchronized (d) {
|
||||
Disposer.dispose(d);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
final Alarm alarm = new Alarm(Alarm.ThreadToUse.SHARED_THREAD, d);
|
||||
final Alarm alarm2 = new Alarm(Alarm.ThreadToUse.OWN_THREAD, alarm);
|
||||
|
||||
final Runnable watchdog = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ref.set(true);
|
||||
}
|
||||
};
|
||||
|
||||
final Runnable ping = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
synchronized (d) {
|
||||
if (alarm.isDisposed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
alarm2.addRequest(watchdog, 200);
|
||||
try {
|
||||
ref.set(!target.ping());
|
||||
} catch (Exception e) {
|
||||
ref.set(true);
|
||||
} finally {
|
||||
alarm2.cancelRequest(watchdog);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
alarm.addRequest(ping, 500);
|
||||
|
||||
final EDTGuard guard = new EDTGuard(target, queue, ref);
|
||||
final ClassLoader classLoader = target.getClass().getClassLoader();
|
||||
final Class<?>[] interfaces = target.getClass().getInterfaces();
|
||||
//noinspection unchecked
|
||||
return (T)Proxy.newProxyInstance(classLoader, interfaces, guard);
|
||||
}
|
||||
|
||||
class Call {
|
||||
private final Method myMethod;
|
||||
private final Object[] myArguments;
|
||||
|
||||
class Result {
|
||||
private final Object myObject;
|
||||
private final Throwable myThrowable;
|
||||
|
||||
public Result(Object o) {
|
||||
myObject = o;
|
||||
myThrowable = null;
|
||||
}
|
||||
|
||||
public Result(Throwable o) {
|
||||
myObject = null;
|
||||
myThrowable = o;
|
||||
}
|
||||
|
||||
public boolean isFromCall(Call call) {
|
||||
return call == Call.this;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Object getValue() throws Throwable {
|
||||
if (myThrowable != null) {
|
||||
throw myThrowable;
|
||||
}
|
||||
return myObject;
|
||||
}
|
||||
}
|
||||
|
||||
public Call(Method method, Object[] arguments) {
|
||||
myMethod = method;
|
||||
myArguments = arguments;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Result invoke() {
|
||||
try {
|
||||
return new Result(EDTGuard.this.invoke(myMethod, myArguments));
|
||||
} catch (Throwable e) {
|
||||
return new Result(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2002-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;
|
||||
|
||||
/**
|
||||
* Thrown by the EDTGuard when some method cannot be completed due to the target VM being paused.
|
||||
*/
|
||||
public class VMPausedException extends RuntimeException {
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package org.intellij.plugins.xsltDebugger;
|
||||
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.openapi.fileTypes.StdFileTypes;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.xdebugger.breakpoints.XBreakpointProperties;
|
||||
import com.intellij.xdebugger.breakpoints.XLineBreakpointType;
|
||||
import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider;
|
||||
import com.intellij.xdebugger.ui.DebuggerIcons;
|
||||
import org.intellij.lang.xpath.xslt.XsltSupport;
|
||||
import org.intellij.plugins.xsltDebugger.impl.XsltDebuggerEditorsProvider;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
/*
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: sweinreuter
|
||||
* Date: 03.03.11
|
||||
*/
|
||||
public final class XsltBreakpointType extends XLineBreakpointType<XBreakpointProperties> {
|
||||
|
||||
private final XsltDebuggerEditorsProvider myMyEditorsProvider = new XsltDebuggerEditorsProvider();
|
||||
|
||||
public XsltBreakpointType() {
|
||||
super("xslt", "XSLT Breakpoints");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPutAt(@NotNull VirtualFile file, int line, @NotNull Project project) {
|
||||
final Document document = FileDocumentManager.getInstance().getDocument(file);
|
||||
if (document == null) return false;
|
||||
|
||||
final PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(document);
|
||||
if (psiFile == null) {
|
||||
return false;
|
||||
}
|
||||
final FileType fileType = psiFile.getFileType();
|
||||
if (fileType != StdFileTypes.XML || !XsltSupport.isXsltFile(psiFile)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public XDebuggerEditorsProvider getEditorsProvider() {
|
||||
return myMyEditorsProvider;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Icon getEnabledIcon() {
|
||||
return XsltSupport.createXsltIcon(DebuggerIcons.ENABLED_BREAKPOINT_ICON);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Icon getDisabledIcon() {
|
||||
return XsltSupport.createXsltIcon(DebuggerIcons.DISABLED_BREAKPOINT_ICON);
|
||||
}
|
||||
|
||||
@Override
|
||||
public XBreakpointProperties createBreakpointProperties(@NotNull VirtualFile file, int line) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+273
@@ -0,0 +1,273 @@
|
||||
/*
|
||||
* Copyright 2002-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;
|
||||
|
||||
import com.intellij.compiler.impl.CompilerUtil;
|
||||
import com.intellij.diagnostic.logging.AdditionalTabComponent;
|
||||
import com.intellij.execution.CantRunException;
|
||||
import com.intellij.execution.configurations.AdditionalTabComponentManager;
|
||||
import com.intellij.execution.configurations.SimpleJavaParameters;
|
||||
import com.intellij.execution.process.ProcessHandler;
|
||||
import com.intellij.execution.process.ProcessListener;
|
||||
import com.intellij.ide.plugins.IdeaPluginDescriptor;
|
||||
import com.intellij.ide.plugins.PluginManager;
|
||||
import com.intellij.openapi.application.PathManager;
|
||||
import com.intellij.openapi.application.ex.ApplicationManagerEx;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.extensions.PluginId;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.util.IconLoader;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.UserDataHolder;
|
||||
import com.intellij.openapi.vfs.JarFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.util.Icons;
|
||||
import com.intellij.util.net.NetUtils;
|
||||
import com.intellij.xdebugger.impl.ui.DebuggerSessionTabBase;
|
||||
import org.intellij.lang.xpath.xslt.XsltSupport;
|
||||
import org.intellij.lang.xpath.xslt.impl.XsltChecker;
|
||||
import org.intellij.lang.xpath.xslt.run.XsltRunConfiguration;
|
||||
import org.intellij.lang.xpath.xslt.run.XsltRunnerExtension;
|
||||
import org.intellij.plugins.xsltDebugger.ui.OutputTabComponent;
|
||||
import org.intellij.plugins.xsltDebugger.ui.StructureTabComponent;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.jar.Attributes;
|
||||
import java.util.jar.Manifest;
|
||||
|
||||
/**
|
||||
* Extension for XPathView that hooks into the execution of XSLT-scripts. Manages the creation of the XSLT-Debugger UI
|
||||
* and ensures the debugged process is started with the required JVM properties.
|
||||
*/
|
||||
public class XsltDebuggerExtension extends XsltRunnerExtension {
|
||||
private static final Logger LOG = Logger.getInstance(XsltDebuggerExtension.class.getName());
|
||||
|
||||
private static final Key<Integer> PORT = Key.create("PORT");
|
||||
private static final Key<Manifest> MANIFEST = Key.create("MANIFEST");
|
||||
|
||||
@NonNls
|
||||
private static final String SAXON_6_JAR = "saxon.jar";
|
||||
|
||||
@NonNls
|
||||
private static final String SAXON_9_JAR = "saxon9he.jar";
|
||||
|
||||
protected boolean supports(XsltRunConfiguration config, boolean debugger) {
|
||||
return (debugger || XsltDebuggerRunner.ACTIVE.get() == Boolean.TRUE) &&
|
||||
config.getOutputType() == XsltRunConfiguration.OutputType.CONSOLE; // ?
|
||||
}
|
||||
|
||||
public ProcessListener createProcessListener(Project project, UserDataHolder extensionData) {
|
||||
final Integer port = extensionData.getUserData(PORT);
|
||||
assert port != null;
|
||||
return new DebugProcessListener(project, port);
|
||||
}
|
||||
|
||||
public boolean createTabs(Project project,
|
||||
AdditionalTabComponentManager manager,
|
||||
AdditionalTabComponent outputConsole,
|
||||
ProcessHandler process) {
|
||||
if (manager instanceof DebuggerSessionTabBase) {
|
||||
final DebuggerSessionTabBase mgr = (DebuggerSessionTabBase)manager;
|
||||
mgr.addAdditionalTabComponent(new OutputTabComponent(outputConsole), "XSLT-Output", IconLoader.getIcon("/debugger/console.png"));
|
||||
mgr.addAdditionalTabComponent(StructureTabComponent.create(process, outputConsole), "XSLT-Structure", Icons.FLATTEN_PACKAGES_ICON);
|
||||
} else {
|
||||
manager.addAdditionalTabComponent(new OutputTabComponent(outputConsole), "XSLT-Output");
|
||||
manager.addAdditionalTabComponent(StructureTabComponent.create(process, outputConsole), "XSLT-Structure");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void patchParameters(final SimpleJavaParameters parameters, XsltRunConfiguration configuration, UserDataHolder extensionData)
|
||||
throws CantRunException {
|
||||
final XsltRunConfiguration.OutputType outputType = configuration.getOutputType();
|
||||
|
||||
final Sdk jdk = configuration.getEffectiveJDK();
|
||||
assert jdk != null;
|
||||
|
||||
final String ver = jdk.getVersionString();
|
||||
if (!(CompilerUtil.isOfVersion(ver, "1.5") ||
|
||||
CompilerUtil.isOfVersion(ver, "5.0") ||
|
||||
CompilerUtil.isOfVersion(ver, "1.6") ||
|
||||
CompilerUtil.isOfVersion(ver, "1.7"))) {
|
||||
|
||||
throw new CantRunException("The XSLT Debugger can only be used with JDK 1.5+");
|
||||
}
|
||||
|
||||
// TODO: fix and remove
|
||||
if (outputType != XsltRunConfiguration.OutputType.CONSOLE) {
|
||||
throw new CantRunException("XSLT Debugger requires Output Type == CONSOLE");
|
||||
}
|
||||
|
||||
try {
|
||||
final int port = NetUtils.findAvailableSocketPort();
|
||||
parameters.getVMParametersList().defineProperty("xslt.debugger.port", String.valueOf(port));
|
||||
extensionData.putUserData(PORT, port);
|
||||
} catch (IOException e) {
|
||||
LOG.info(e);
|
||||
throw new CantRunException("Unable to find a free network port");
|
||||
}
|
||||
|
||||
final char c = File.separatorChar;
|
||||
|
||||
final PluginId pluginId = PluginManager.getPluginByClassName(getClass().getName());
|
||||
assert pluginId != null || System.getProperty("xslt-debugger.plugin.path") != null;
|
||||
|
||||
final File pluginPath;
|
||||
if (pluginId != null) {
|
||||
final IdeaPluginDescriptor descriptor = PluginManager.getPlugin(pluginId);
|
||||
assert descriptor != null;
|
||||
pluginPath = descriptor.getPath();
|
||||
} else {
|
||||
pluginPath = new File(System.getProperty("xslt-debugger.plugin.path"));
|
||||
}
|
||||
|
||||
File rtClasspath = new File(pluginPath, "lib" + c + "xslt-debugger-engine.jar");
|
||||
if (rtClasspath.exists()) {
|
||||
parameters.getClassPath().addTail(rtClasspath.getAbsolutePath());
|
||||
} else {
|
||||
if (!(rtClasspath = new File(pluginPath, "classes")).exists()) {
|
||||
if (ApplicationManagerEx.getApplicationEx().isInternal() && new File(pluginPath, "org").exists()) {
|
||||
rtClasspath = pluginPath;
|
||||
} else {
|
||||
throw new CantRunException("Runtime classes not found");
|
||||
}
|
||||
}
|
||||
|
||||
parameters.getClassPath().addTail(rtClasspath.getAbsolutePath());
|
||||
parameters.getClassPath().addTail(new File(rtClasspath, "rmi-stubs.jar").getAbsolutePath());
|
||||
}
|
||||
|
||||
File trove4j = new File(PathManager.getLibPath() + c + "trove4j.jar");
|
||||
if (!trove4j.exists()) {
|
||||
trove4j = new File(PathManager.getHomePath() + c + "community" + c + "lib" + c + "trove4j.jar");
|
||||
}
|
||||
parameters.getClassPath().addTail(trove4j.getAbsolutePath());
|
||||
|
||||
final String type = parameters.getVMParametersList().getPropertyValue("xslt.transformer.type");
|
||||
if ("saxon".equalsIgnoreCase(type)) {
|
||||
addSaxon(parameters, pluginPath, SAXON_6_JAR);
|
||||
} else if ("saxon9".equalsIgnoreCase(type)) {
|
||||
addSaxon(parameters, pluginPath, SAXON_9_JAR);
|
||||
} else if ("xalan".equalsIgnoreCase(type)) {
|
||||
final Boolean xalanPresent = isValidXalanPresent(parameters);
|
||||
if (xalanPresent == null) {
|
||||
addXalan(parameters, pluginPath);
|
||||
} else if (!xalanPresent) {
|
||||
throw new CantRunException("Unsupported Xalan version is present in classpath.");
|
||||
}
|
||||
} else if (type != null) {
|
||||
throw new CantRunException("Unsupported Transformer type '" + type + "'");
|
||||
} else if (parameters.getClassPath().getPathsString().toLowerCase().contains("xalan")) {
|
||||
if (isValidXalanPresent(parameters) == Boolean.TRUE) {
|
||||
parameters.getVMParametersList().defineProperty("xslt.transformer.type", "xalan");
|
||||
}
|
||||
}
|
||||
if (!parameters.getVMParametersList().hasProperty("xslt.transformer.type")) {
|
||||
// add saxon for backward-compatibility
|
||||
final VirtualFile xsltFile = configuration.findXsltFile();
|
||||
final PsiManager psiManager = PsiManager.getInstance(configuration.getProject());
|
||||
if (xsltFile != null && XsltSupport.getXsltLanguageLevel(psiManager.findFile(xsltFile)) == XsltChecker.LanguageLevel.V2)
|
||||
{
|
||||
parameters.getVMParametersList().defineProperty("xslt.transformer.type", "saxon9");
|
||||
addSaxon(parameters, pluginPath, SAXON_9_JAR);
|
||||
} else {
|
||||
parameters.getVMParametersList().defineProperty("xslt.transformer.type", "saxon");
|
||||
addSaxon(parameters, pluginPath, SAXON_6_JAR);
|
||||
}
|
||||
}
|
||||
|
||||
parameters.getVMParametersList().defineProperty("xslt.main", "org.intellij.plugins.xsltDebugger.rt.XSLTDebuggerMain");
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Boolean isValidXalanPresent(SimpleJavaParameters parameters) {
|
||||
final List<VirtualFile> files = parameters.getClassPath().getVirtualFiles();
|
||||
for (VirtualFile file : files) {
|
||||
if (file.getName().matches(".*xalan.*\\.jar")) {
|
||||
final VirtualFile root = JarFileSystem.getInstance().getJarRootForLocalFile(file);
|
||||
final VirtualFile manifestFile = root != null ? root.findFileByRelativePath("META-INF/MANIFEST.MF") : null;
|
||||
if (manifestFile != null) {
|
||||
try {
|
||||
Manifest manifest = manifestFile.getUserData(MANIFEST);
|
||||
if (manifest == null) {
|
||||
manifest = new Manifest(manifestFile.getInputStream());
|
||||
manifestFile.putUserData(MANIFEST, manifest);
|
||||
}
|
||||
Attributes attributes = manifest.getAttributes("org/apache/xalan/");
|
||||
if (attributes == null) {
|
||||
attributes = manifest.getAttributes("org/apache/xalan");
|
||||
}
|
||||
if (attributes == null) {
|
||||
LOG.info("No manifest attributes for 'org/apache/xalan/' in " + manifestFile.getPresentableUrl());
|
||||
continue;
|
||||
}
|
||||
final String version = attributes.getValue("Implementation-Version");
|
||||
if (version != null) {
|
||||
final String[] parts = version.split("\\.");
|
||||
if (parts.length >= 2) {
|
||||
if (Integer.parseInt(parts[0]) >= 2 && Integer.parseInt(parts[1]) >= 6) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
LOG.info("Unsupported Xalan version: " + version);
|
||||
} else {
|
||||
LOG.info("No Xalan version information in " + file.getPath());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
LOG.warn("Unable to read manifest from " + file.getName(), e);
|
||||
}
|
||||
} else {
|
||||
LOG.info("No manifest file in " + file.getPath());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void addXalan(SimpleJavaParameters parameters, File pluginPath) {
|
||||
final char c = File.separatorChar;
|
||||
File xalan = new File(pluginPath, "lib" + c + "rt" + c + "xalan.jar");
|
||||
if (!xalan.exists()) {
|
||||
if (!(xalan = new File(pluginPath, "lib" + c + "xalan.jar")).exists()) {
|
||||
xalan = new File(pluginPath, "xalan.jar");
|
||||
assert xalan.exists();
|
||||
}
|
||||
}
|
||||
parameters.getClassPath().addTail(xalan.getAbsolutePath());
|
||||
parameters.getClassPath().addTail(new File(xalan.getParentFile(), "serializer.jar").getAbsolutePath());
|
||||
}
|
||||
|
||||
private static void addSaxon(SimpleJavaParameters parameters, File pluginPath, final String saxonJar) {
|
||||
final char c = File.separatorChar;
|
||||
File saxon = new File(pluginPath, "lib" + c + "rt" + c + saxonJar);
|
||||
if (!saxon.exists()) {
|
||||
if (!(saxon = new File(pluginPath, "lib" + c + saxonJar)).exists()) {
|
||||
saxon = new File(pluginPath, saxonJar);
|
||||
assert saxon.exists();
|
||||
}
|
||||
}
|
||||
parameters.getClassPath().addTail(saxon.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
package org.intellij.plugins.xsltDebugger;
|
||||
|
||||
import com.intellij.execution.ExecutionException;
|
||||
import com.intellij.execution.ExecutionResult;
|
||||
import com.intellij.execution.Executor;
|
||||
import com.intellij.execution.configurations.JavaParameters;
|
||||
import com.intellij.execution.configurations.RunProfile;
|
||||
import com.intellij.execution.configurations.RunProfileState;
|
||||
import com.intellij.execution.configurations.RunnerSettings;
|
||||
import com.intellij.execution.runners.ExecutionEnvironment;
|
||||
import com.intellij.execution.runners.JavaPatchableProgramRunner;
|
||||
import com.intellij.execution.ui.RunContentDescriptor;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.xdebugger.XDebugProcess;
|
||||
import com.intellij.xdebugger.XDebugProcessStarter;
|
||||
import com.intellij.xdebugger.XDebugSession;
|
||||
import com.intellij.xdebugger.XDebuggerManager;
|
||||
import org.intellij.lang.xpath.xslt.run.XsltRunConfiguration;
|
||||
import org.intellij.plugins.xsltDebugger.impl.XsltDebugProcess;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/*
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: sweinreuter
|
||||
* Date: 16.11.10
|
||||
*/
|
||||
public class XsltDebuggerRunner extends JavaPatchableProgramRunner {
|
||||
static final ThreadLocal<Boolean> ACTIVE = new ThreadLocal<Boolean>();
|
||||
|
||||
@NonNls
|
||||
private static final String ID = "XsltDebuggerRunner";
|
||||
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getRunnerId() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canRun(@NotNull String executorId, @NotNull RunProfile profile) {
|
||||
return executorId.equals("Debug") && profile instanceof XsltRunConfiguration;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RunContentDescriptor doExecute(Project project,
|
||||
Executor executor,
|
||||
RunProfileState state,
|
||||
RunContentDescriptor contentToReuse,
|
||||
ExecutionEnvironment env) throws ExecutionException {
|
||||
FileDocumentManager.getInstance().saveAllDocuments();
|
||||
return createContentDescriptor(project, executor, state, contentToReuse, env);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void patch(JavaParameters javaParameters, RunnerSettings settings, boolean beforeExecution) throws ExecutionException {
|
||||
javaParameters.setJdk(((XsltRunConfiguration)settings.getRunProfile()).getEffectiveJDK());
|
||||
}
|
||||
|
||||
protected RunContentDescriptor createContentDescriptor(Project project,
|
||||
final Executor executor,
|
||||
final RunProfileState runProfileState,
|
||||
RunContentDescriptor contentToReuse,
|
||||
ExecutionEnvironment executionEnvironment) throws ExecutionException {
|
||||
final XDebugSession debugSession =
|
||||
XDebuggerManager.getInstance(project).startSession(this, executionEnvironment, contentToReuse, new XDebugProcessStarter() {
|
||||
@NotNull
|
||||
public XDebugProcess start(@NotNull final XDebugSession session) {
|
||||
ACTIVE.set(Boolean.TRUE);
|
||||
try {
|
||||
final ExecutionResult result = runProfileState.execute(executor, XsltDebuggerRunner.this);
|
||||
return new XsltDebugProcess(session, result);
|
||||
} catch (ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
ACTIVE.remove();
|
||||
}
|
||||
}
|
||||
});
|
||||
return debugSession.getRunContentDescriptor();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,259 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import com.intellij.execution.process.ProcessHandler;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager;
|
||||
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.vfs.VfsUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.pom.Navigatable;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.util.EventDispatcher;
|
||||
import com.intellij.xdebugger.XSourcePosition;
|
||||
import org.intellij.plugins.xsltDebugger.impl.XsltBreakpointHandler;
|
||||
import org.intellij.plugins.xsltDebugger.impl.XsltDebugProcess;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.Breakpoint;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.BreakpointManager;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.Debugger;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.DebuggerStoppedException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.SocketException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.rmi.RemoteException;
|
||||
import java.util.EventListener;
|
||||
|
||||
/**
|
||||
* This is the main place that interacts with the debugged XSLT processor. Waits until the processor
|
||||
* hits a breakpoint, resumes execution, etc.
|
||||
*/
|
||||
public class XsltDebuggerSession implements Disposable {
|
||||
private static final Key<XsltDebuggerSession> DEBUGGER_SESSION = Key.create("DEBUGGER_SESSION");
|
||||
|
||||
private final Project myProject;
|
||||
private final ProcessHandler myProcess;
|
||||
private final Debugger myClient;
|
||||
private final EventDispatcher<Listener> myEventDispatcher = EventDispatcher.create(Listener.class);
|
||||
|
||||
private Breakpoint myTempBreakpoint;
|
||||
|
||||
private volatile Debugger.State myState;
|
||||
private boolean myClosed;
|
||||
|
||||
private XsltDebuggerSession(Project project, ProcessHandler process, Debugger client) {
|
||||
myProject = project;
|
||||
myProcess = process;
|
||||
myClient = client;
|
||||
Disposer.register(XsltDebugProcess.getInstance(process), this);
|
||||
}
|
||||
|
||||
public void start() {
|
||||
myClient.start();
|
||||
myState = Debugger.State.RUNNING;
|
||||
|
||||
final BreakpointManager breakpointManager = myClient.getBreakpointManager();
|
||||
final Listener multicaster = myEventDispatcher.getMulticaster();
|
||||
try {
|
||||
if (!myClient.waitForDebuggee()) {
|
||||
multicaster.debuggerStopped();
|
||||
return;
|
||||
}
|
||||
myState = Debugger.State.SUSPENDED;
|
||||
do {
|
||||
if (myState == Debugger.State.SUSPENDED) {
|
||||
if (myTempBreakpoint != null) {
|
||||
breakpointManager.removeBreakpoint(myTempBreakpoint);
|
||||
myTempBreakpoint = null;
|
||||
}
|
||||
multicaster.debuggerSuspended();
|
||||
} else if (myState == Debugger.State.RUNNING) {
|
||||
multicaster.debuggerResumed();
|
||||
} else if (myState == Debugger.State.STOPPED) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
while ((myState = myClient.waitForStateChange(myState)) != null);
|
||||
|
||||
multicaster.debuggerStopped();
|
||||
} catch (DebuggerStoppedException e) {
|
||||
multicaster.debuggerStopped();
|
||||
} catch (RuntimeException e) {
|
||||
if (e.getCause() instanceof RemoteException) {
|
||||
if (e.getCause().getCause() instanceof SocketException) {
|
||||
multicaster.debuggerStopped();
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw e;
|
||||
} finally {
|
||||
myState = Debugger.State.STOPPED;
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
public void addListener(Listener listener) {
|
||||
myEventDispatcher.addListener(listener);
|
||||
}
|
||||
|
||||
public void removeListener(Listener listener) {
|
||||
myEventDispatcher.removeListener(listener);
|
||||
}
|
||||
|
||||
public Debugger getClient() {
|
||||
return myClient;
|
||||
}
|
||||
|
||||
public Debugger.State getCurrentState() {
|
||||
return myState;
|
||||
}
|
||||
|
||||
public void pause() {
|
||||
myClient.pause();
|
||||
}
|
||||
|
||||
public void resume() {
|
||||
myClient.resume();
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
try {
|
||||
myClient.stop(false);
|
||||
} catch (DebuggerStoppedException ignore) {
|
||||
}
|
||||
}
|
||||
|
||||
public void stepOver() {
|
||||
myClient.step();
|
||||
}
|
||||
|
||||
public void stepInto() {
|
||||
myClient.stepInto();
|
||||
}
|
||||
|
||||
public boolean canRunTo(final PsiFile file, final int offset) {
|
||||
return XsltBreakpointHandler.getActualLineNumber(myProject, new MyXSourcePosition(file, offset)) != -1;
|
||||
}
|
||||
|
||||
public void runTo(final PsiFile file, final int offset) {
|
||||
assert myTempBreakpoint == null;
|
||||
|
||||
final int lineNumber = XsltBreakpointHandler.getActualLineNumber(myProject, new MyXSourcePosition(file, offset));
|
||||
final String uri = XsltBreakpointHandler.getFileURL(file.getVirtualFile());
|
||||
myTempBreakpoint = myClient.getBreakpointManager().setBreakpoint(uri, lineNumber);
|
||||
|
||||
resume();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static Editor openLocation(Project project, @NotNull String uri, int lineNumber) {
|
||||
try {
|
||||
final VirtualFile file = VfsUtil.findFileByURL(new URI(uri).toURL());
|
||||
final OpenFileDescriptor descriptor = new OpenFileDescriptor(project, file, lineNumber, 0);
|
||||
descriptor.navigate(true);
|
||||
|
||||
return FileEditorManager.getInstance(project).openTextEditor(descriptor, true);
|
||||
} catch (MalformedURLException e) {
|
||||
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
|
||||
return null;
|
||||
} catch (URISyntaxException e) {
|
||||
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void close() {
|
||||
if (myClosed) return;
|
||||
myClosed = true;
|
||||
|
||||
try {
|
||||
myClient.stop(true);
|
||||
} catch (DebuggerStoppedException e) {
|
||||
// OK
|
||||
} finally {
|
||||
myProcess.destroyProcess();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
detach(myProcess);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static XsltDebuggerSession create(Project project, @NotNull ProcessHandler process, Debugger client) {
|
||||
final XsltDebuggerSession session = new XsltDebuggerSession(project, process, client);
|
||||
process.putUserData(DEBUGGER_SESSION, session);
|
||||
return session;
|
||||
}
|
||||
|
||||
public static XsltDebuggerSession getInstance(@NotNull ProcessHandler process) {
|
||||
return process.getUserData(DEBUGGER_SESSION);
|
||||
}
|
||||
|
||||
public static void detach(ProcessHandler processHandler) {
|
||||
processHandler.putUserData(DEBUGGER_SESSION, null);
|
||||
}
|
||||
|
||||
public interface Listener extends EventListener {
|
||||
void debuggerSuspended();
|
||||
|
||||
void debuggerResumed();
|
||||
|
||||
void debuggerStopped();
|
||||
}
|
||||
|
||||
private static class MyXSourcePosition implements XSourcePosition {
|
||||
private final PsiFile myFile;
|
||||
private final int myOffset;
|
||||
|
||||
public MyXSourcePosition(PsiFile file, int offset) {
|
||||
myFile = file;
|
||||
myOffset = offset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLine() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOffset() {
|
||||
return myOffset;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public VirtualFile getFile() {
|
||||
return myFile.getVirtualFile();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Navigatable createNavigatable(@NotNull Project project) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
}
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* 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.impl;
|
||||
|
||||
import com.intellij.psi.xml.XmlElement;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import org.intellij.lang.xpath.context.*;
|
||||
import org.intellij.lang.xpath.psi.XPathElement;
|
||||
import org.intellij.lang.xpath.xslt.context.XsltContextProvider;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.Debugger;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: sweinreuter
|
||||
* Date: 06.06.2007
|
||||
*/
|
||||
public class EvalContextProvider extends ContextProvider {
|
||||
private final List<Debugger.Variable> myVariables;
|
||||
|
||||
public EvalContextProvider(List<Debugger.Variable> model) {
|
||||
myVariables = model;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ContextType getContextType() {
|
||||
return XsltContextProvider.TYPE;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public XmlElement getContextElement() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isValid() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public NamespaceContext getNamespaceContext() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public VariableContext getVariableContext() {
|
||||
return new SimpleVariableContext() {
|
||||
@NotNull
|
||||
public String[] getVariablesInScope(XPathElement element) {
|
||||
final int size = myVariables.size();
|
||||
final ArrayList<String> vars = new ArrayList<String>(size);
|
||||
for (Debugger.Variable myVariable : myVariables) {
|
||||
vars.add(myVariable.getName());
|
||||
}
|
||||
return ArrayUtil.toStringArray(vars);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Set<QName> getAttributes(boolean forValidation) {
|
||||
return null; // TODO
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Set<QName> getElements(boolean forValidation) {
|
||||
return null; // TODO
|
||||
}
|
||||
}
|
||||
+173
@@ -0,0 +1,173 @@
|
||||
package org.intellij.plugins.xsltDebugger.impl;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.MessageType;
|
||||
import com.intellij.openapi.vfs.VfsUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.xml.*;
|
||||
import com.intellij.xdebugger.XDebugSession;
|
||||
import com.intellij.xdebugger.XSourcePosition;
|
||||
import com.intellij.xdebugger.breakpoints.XBreakpointHandler;
|
||||
import com.intellij.xdebugger.breakpoints.XBreakpointProperties;
|
||||
import com.intellij.xdebugger.breakpoints.XLineBreakpoint;
|
||||
import com.intellij.xdebugger.ui.DebuggerIcons;
|
||||
import org.intellij.plugins.xsltDebugger.VMPausedException;
|
||||
import org.intellij.plugins.xsltDebugger.XsltBreakpointType;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.Breakpoint;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.BreakpointManager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class XsltBreakpointHandler extends XBreakpointHandler<XLineBreakpoint<XBreakpointProperties>> {
|
||||
private XsltDebugProcess myXsltDebugProcess;
|
||||
|
||||
public XsltBreakpointHandler(XsltDebugProcess xsltDebugProcess) {
|
||||
super(XsltBreakpointType.class);
|
||||
myXsltDebugProcess = xsltDebugProcess;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerBreakpoint(@NotNull XLineBreakpoint<XBreakpointProperties> breakpoint) {
|
||||
final XSourcePosition sourcePosition = breakpoint.getSourcePosition();
|
||||
if (sourcePosition == null) {
|
||||
// ???
|
||||
return;
|
||||
}
|
||||
final VirtualFile file = sourcePosition.getFile();
|
||||
final Project project = myXsltDebugProcess.getSession().getProject();
|
||||
final String fileURL = getFileURL(file);
|
||||
final int lineNumber = getActualLineNumber(breakpoint, project);
|
||||
|
||||
try {
|
||||
final BreakpointManager manager = myXsltDebugProcess.getBreakpointManager();
|
||||
Breakpoint bp;
|
||||
if ((bp = manager.getBreakpoint(fileURL, lineNumber)) != null) {
|
||||
bp.setEnabled(true);
|
||||
} else {
|
||||
manager.setBreakpoint(fileURL, lineNumber);
|
||||
}
|
||||
} catch (VMPausedException e) {
|
||||
final XDebugSession session = myXsltDebugProcess.getSession();
|
||||
session.reportMessage("Target VM is not responding. Breakpoint can not be set", MessageType.ERROR);
|
||||
session.updateBreakpointPresentation(breakpoint, DebuggerIcons.INVALID_BREAKPOINT_ICON,
|
||||
"Target VM is not responding. Breakpoint can not be set");
|
||||
}
|
||||
}
|
||||
|
||||
public static String getFileURL(VirtualFile file) {
|
||||
return VfsUtil.virtualToIoFile(file).toURI().toASCIIString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterBreakpoint(@NotNull XLineBreakpoint<XBreakpointProperties> breakpoint, final boolean temporary) {
|
||||
final XSourcePosition sourcePosition = breakpoint.getSourcePosition();
|
||||
if (sourcePosition == null) {
|
||||
// ???
|
||||
return;
|
||||
}
|
||||
|
||||
final VirtualFile file = sourcePosition.getFile();
|
||||
final Project project = myXsltDebugProcess.getSession().getProject();
|
||||
final String fileURL = getFileURL(file);
|
||||
final int lineNumber = getActualLineNumber(breakpoint, project);
|
||||
|
||||
try {
|
||||
final BreakpointManager manager = myXsltDebugProcess.getBreakpointManager();
|
||||
if (temporary) {
|
||||
final Breakpoint bp = manager.getBreakpoint(fileURL, lineNumber);
|
||||
if (bp != null) {
|
||||
bp.setEnabled(false);
|
||||
}
|
||||
} else {
|
||||
manager.removeBreakpoint(fileURL, lineNumber);
|
||||
}
|
||||
} catch (VMPausedException e) {
|
||||
myXsltDebugProcess.getSession().reportMessage("Target VM is not responding. Breakpoint can not be removed", MessageType.ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
public static int getActualLineNumber(XLineBreakpoint breakpoint, Project project) {
|
||||
return getActualLineNumber(project, breakpoint.getSourcePosition());
|
||||
}
|
||||
|
||||
public static int getActualLineNumber(Project project, @Nullable XSourcePosition position) {
|
||||
if (position == null) {
|
||||
return -1;
|
||||
}
|
||||
final PsiElement element = findContextElement(project, position);
|
||||
if (element == null) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (element instanceof XmlToken) {
|
||||
final IElementType tokenType = ((XmlToken)element).getTokenType();
|
||||
if (tokenType == XmlTokenType.XML_START_TAG_START || tokenType == XmlTokenType.XML_NAME) {
|
||||
final PsiManager psiManager = PsiManager.getInstance(project);
|
||||
final PsiDocumentManager documentManager = PsiDocumentManager.getInstance(project);
|
||||
final PsiFile psiFile = psiManager.findFile(position.getFile());
|
||||
if (psiFile == null) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
final Document document = documentManager.getDocument(psiFile);
|
||||
if (document == null) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (document.getLineNumber(element.getTextRange().getStartOffset()) == position.getLine()) {
|
||||
final XmlTag tag = PsiTreeUtil.getParentOfType(element, XmlTag.class, false);
|
||||
if (tag != null) {
|
||||
final ASTNode node = tag.getNode();
|
||||
assert node != null;
|
||||
// TODO: re-check if/when Xalan is supported
|
||||
final ASTNode end = XmlChildRole.START_TAG_END_FINDER.findChild(node);
|
||||
if (end != null) {
|
||||
return document.getLineNumber(end.getTextRange().getEndOffset()) + 1;
|
||||
} else {
|
||||
final ASTNode end2 = XmlChildRole.EMPTY_TAG_END_FINDER.findChild(node);
|
||||
if (end2 != null) {
|
||||
return document.getLineNumber(end2.getTextRange().getEndOffset()) + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiElement findContextElement(Project project, @Nullable XSourcePosition position) {
|
||||
if (position == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final PsiFile file = PsiManager.getInstance(project).findFile(position.getFile());
|
||||
if (file == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
int offset = -1;
|
||||
final Document document = PsiDocumentManager.getInstance(project).getDocument(file);
|
||||
if (document != null) {
|
||||
offset = document.getLineStartOffset(position.getLine());
|
||||
}
|
||||
if (offset < 0) {
|
||||
offset = position.getOffset();
|
||||
}
|
||||
|
||||
PsiElement contextElement = file.findElementAt(offset);
|
||||
while (contextElement != null && !(contextElement instanceof XmlElement)) {
|
||||
contextElement = PsiTreeUtil.nextLeaf(contextElement);
|
||||
}
|
||||
return contextElement;
|
||||
}
|
||||
}
|
||||
+189
@@ -0,0 +1,189 @@
|
||||
package org.intellij.plugins.xsltDebugger.impl;
|
||||
|
||||
import com.intellij.execution.ExecutionResult;
|
||||
import com.intellij.execution.process.ProcessHandler;
|
||||
import com.intellij.execution.ui.ExecutionConsole;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.wm.StatusBar;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.xdebugger.XDebugProcess;
|
||||
import com.intellij.xdebugger.XDebugSession;
|
||||
import com.intellij.xdebugger.XSourcePosition;
|
||||
import com.intellij.xdebugger.breakpoints.XBreakpointHandler;
|
||||
import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider;
|
||||
import com.intellij.xdebugger.frame.XExecutionStack;
|
||||
import com.intellij.xdebugger.frame.XSuspendContext;
|
||||
import org.intellij.plugins.xsltDebugger.XsltDebuggerSession;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.Breakpoint;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.BreakpointManager;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.Debugger;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.local.BreakpointManagerImpl;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class XsltDebugProcess extends XDebugProcess implements Disposable {
|
||||
private static final Key<XsltDebugProcess> KEY = Key.create("PROCESS");
|
||||
|
||||
private final XsltDebuggerEditorsProvider myEditorsProvider;
|
||||
private final ProcessHandler myProcessHandler;
|
||||
private final ExecutionConsole myExecutionConsole;
|
||||
|
||||
private BreakpointManager myBreakpointManager = new BreakpointManagerImpl();
|
||||
|
||||
private final XBreakpointHandler<?>[] myXBreakpointHandlers = new XBreakpointHandler<?>[]{
|
||||
new XsltBreakpointHandler(this)
|
||||
};
|
||||
private XsltDebuggerSession myDebuggerSession;
|
||||
|
||||
public XsltDebugProcess(XDebugSession session, ExecutionResult executionResult) {
|
||||
super(session);
|
||||
myProcessHandler = executionResult.getProcessHandler();
|
||||
myProcessHandler.putUserData(KEY, this);
|
||||
myExecutionConsole = executionResult.getExecutionConsole();
|
||||
myEditorsProvider = new XsltDebuggerEditorsProvider();
|
||||
Disposer.register(myExecutionConsole, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public XBreakpointHandler<?>[] getBreakpointHandlers() {
|
||||
return myXBreakpointHandlers;
|
||||
}
|
||||
|
||||
public BreakpointManager getBreakpointManager() {
|
||||
return myBreakpointManager;
|
||||
}
|
||||
|
||||
public void init(Debugger client) {
|
||||
myDebuggerSession = XsltDebuggerSession.getInstance(myProcessHandler);
|
||||
|
||||
myDebuggerSession.addListener(new XsltDebuggerSession.Listener() {
|
||||
@Override
|
||||
public void debuggerSuspended() {
|
||||
final XDebugSession session = XsltDebugProcess.this.getSession();
|
||||
final Debugger c = myDebuggerSession.getClient();
|
||||
session.positionReached(new MySuspendContext(myDebuggerSession, c.getCurrentFrame(), c.getSourceFrame()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debuggerResumed() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debuggerStopped() {
|
||||
}
|
||||
});
|
||||
|
||||
final BreakpointManager mgr = client.getBreakpointManager();
|
||||
if (myBreakpointManager != mgr) {
|
||||
final List<Breakpoint> breakpoints = myBreakpointManager.getBreakpoints();
|
||||
for (Breakpoint breakpoint : breakpoints) {
|
||||
final Breakpoint bp = mgr.setBreakpoint(breakpoint.getUri(), breakpoint.getLine());
|
||||
bp.setEnabled(breakpoint.isEnabled());
|
||||
bp.setLogMessage(breakpoint.getLogMessage());
|
||||
bp.setTraceMessage(breakpoint.getTraceMessage());
|
||||
bp.setCondition(breakpoint.getCondition());
|
||||
bp.setSuspend(breakpoint.isSuspend());
|
||||
}
|
||||
myBreakpointManager = mgr;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static XsltDebugProcess getInstance(ProcessHandler handler) {
|
||||
return handler.getUserData(KEY);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ExecutionConsole createConsole() {
|
||||
return myExecutionConsole;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ProcessHandler doGetProcessHandler() {
|
||||
return myProcessHandler;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public XDebuggerEditorsProvider getEditorsProvider() {
|
||||
return myEditorsProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startStepOver() {
|
||||
myDebuggerSession.stepOver();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startStepInto() {
|
||||
myDebuggerSession.stepInto();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startStepOut() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
if (myDebuggerSession != null) {
|
||||
myDebuggerSession.stop();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resume() {
|
||||
myDebuggerSession.resume();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runToPosition(@NotNull XSourcePosition position) {
|
||||
final PsiFile psiFile = PsiManager.getInstance(getSession().getProject()).findFile(position.getFile());
|
||||
assert psiFile != null;
|
||||
if (myDebuggerSession.canRunTo(psiFile, position.getOffset())) {
|
||||
myDebuggerSession.runTo(psiFile, position.getOffset());
|
||||
} else {
|
||||
StatusBar.Info.set("Not a valid position in file '" + psiFile.getName() + "'", psiFile.getProject());
|
||||
final Debugger c = myDebuggerSession.getClient();
|
||||
getSession().positionReached(new MySuspendContext(myDebuggerSession, c.getCurrentFrame(), c.getSourceFrame()));
|
||||
}
|
||||
}
|
||||
|
||||
private static class MySuspendContext extends XSuspendContext {
|
||||
private final XsltDebuggerSession myDebuggerSession;
|
||||
private final Debugger.StyleFrame myStyleFrame;
|
||||
private final Debugger.SourceFrame mySourceFrame;
|
||||
|
||||
public MySuspendContext(XsltDebuggerSession debuggerSession, Debugger.StyleFrame styleFrame, Debugger.SourceFrame sourceFrame) {
|
||||
myDebuggerSession = debuggerSession;
|
||||
myStyleFrame = styleFrame;
|
||||
mySourceFrame = sourceFrame;
|
||||
}
|
||||
|
||||
@Override
|
||||
public XExecutionStack getActiveExecutionStack() {
|
||||
return new XsltExecutionStack("XSLT Frames", myStyleFrame, myDebuggerSession);
|
||||
}
|
||||
|
||||
public XExecutionStack getSourceStack() {
|
||||
return new XsltExecutionStack("Source Frames", mySourceFrame, myDebuggerSession);
|
||||
}
|
||||
|
||||
@Override
|
||||
public XExecutionStack[] getExecutionStacks() {
|
||||
return new XExecutionStack[]{
|
||||
getActiveExecutionStack(),
|
||||
getSourceStack()
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
package org.intellij.plugins.xsltDebugger.impl;
|
||||
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiFileFactory;
|
||||
import com.intellij.util.LocalTimeCounter;
|
||||
import com.intellij.xdebugger.XSourcePosition;
|
||||
import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider;
|
||||
import org.intellij.lang.xpath.XPathFileType;
|
||||
import org.intellij.plugins.xsltDebugger.BreakpointContext;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.Debugger;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class XsltDebuggerEditorsProvider extends XDebuggerEditorsProvider {
|
||||
@NotNull
|
||||
@Override
|
||||
public FileType getFileType() {
|
||||
return XPathFileType.XPATH;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Document createDocument(@NotNull Project project, @NotNull String text, @Nullable XSourcePosition sourcePosition) {
|
||||
final PsiFile psiFile = PsiFileFactory.getInstance(project)
|
||||
.createFileFromText("XPathExpr.xpath", XPathFileType.XPATH, text, LocalTimeCounter.currentTime(), true);
|
||||
|
||||
if (sourcePosition instanceof XsltSourcePosition && ((XsltSourcePosition)sourcePosition).getLocation() instanceof Debugger.StyleFrame) {
|
||||
final Debugger.Locatable location = ((XsltSourcePosition)sourcePosition).getLocation();
|
||||
final EvalContextProvider context = new EvalContextProvider(((Debugger.StyleFrame)location).getVariables());
|
||||
context.attachTo(psiFile);
|
||||
} else {
|
||||
final PsiElement contextElement = XsltBreakpointHandler.findContextElement(project, sourcePosition);
|
||||
if (contextElement != null) {
|
||||
final BreakpointContext context = new BreakpointContext(contextElement);
|
||||
context.attachTo(psiFile);
|
||||
}
|
||||
}
|
||||
|
||||
final Document document = PsiDocumentManager.getInstance(project).getDocument(psiFile);
|
||||
assert document != null;
|
||||
return document;
|
||||
}
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
package org.intellij.plugins.xsltDebugger.impl;
|
||||
|
||||
import com.intellij.xdebugger.frame.XExecutionStack;
|
||||
import com.intellij.xdebugger.frame.XStackFrame;
|
||||
import org.intellij.plugins.xsltDebugger.XsltDebuggerSession;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.Debugger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class XsltExecutionStack extends XExecutionStack {
|
||||
private final XsltStackFrame myTopFrame;
|
||||
private final XsltDebuggerSession myDebuggerSession;
|
||||
|
||||
public XsltExecutionStack(String name, Debugger.Frame topFrame, XsltDebuggerSession debuggerSession) {
|
||||
super(name);
|
||||
myDebuggerSession = debuggerSession;
|
||||
myTopFrame = new XsltStackFrame(topFrame, myDebuggerSession);
|
||||
}
|
||||
|
||||
@Override
|
||||
public XStackFrame getTopFrame() {
|
||||
return myTopFrame;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void computeStackFrames(int firstFrameIndex, XStackFrameContainer container) {
|
||||
if (myDebuggerSession.getCurrentState() == Debugger.State.SUSPENDED) {
|
||||
Debugger.Frame frame = myTopFrame.getFrame();
|
||||
final List<XStackFrame> frames = new ArrayList<XStackFrame>();
|
||||
while (frame != null) {
|
||||
frame = frame.getPrevious();
|
||||
if (frame != null) {
|
||||
frames.add(new XsltStackFrame(frame, myDebuggerSession));
|
||||
}
|
||||
}
|
||||
if (firstFrameIndex <= frames.size()) {
|
||||
container.addStackFrames(frames.subList(firstFrameIndex - 1, frames.size()), true);
|
||||
} else {
|
||||
container.addStackFrames(Collections.<XStackFrame>emptyList(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
package org.intellij.plugins.xsltDebugger.impl;
|
||||
|
||||
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VfsUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.pom.Navigatable;
|
||||
import com.intellij.xdebugger.XSourcePosition;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.Debugger;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
public class XsltSourcePosition implements XSourcePosition {
|
||||
private final Debugger.Locatable myLocation;
|
||||
private final VirtualFile myFile;
|
||||
private final int myLine;
|
||||
|
||||
XsltSourcePosition(Debugger.Locatable location, VirtualFile file, int line) {
|
||||
myLocation = location;
|
||||
myFile = file;
|
||||
myLine = line;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static XSourcePosition create(Debugger.Locatable location) {
|
||||
final VirtualFile file;
|
||||
try {
|
||||
file = VfsUtil.findFileByURL(new URI(location.getURI()).toURL());
|
||||
} catch (Exception e) {
|
||||
// TODO log
|
||||
return null;
|
||||
}
|
||||
|
||||
final int line = location.getLineNumber() - 1;
|
||||
return line >= 0 ? new XsltSourcePosition(location, file, line) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLine() {
|
||||
return myLine;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOffset() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public VirtualFile getFile() {
|
||||
return myFile;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Navigatable createNavigatable(@NotNull Project project) {
|
||||
return new OpenFileDescriptor(project, getFile(), getLine(), 0);
|
||||
}
|
||||
|
||||
public Debugger.Locatable getLocation() {
|
||||
return myLocation;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,235 @@
|
||||
package org.intellij.plugins.xsltDebugger.impl;
|
||||
|
||||
import com.intellij.openapi.vfs.VfsUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.ui.SimpleColoredComponent;
|
||||
import com.intellij.ui.SimpleTextAttributes;
|
||||
import com.intellij.util.Icons;
|
||||
import com.intellij.xdebugger.XSourcePosition;
|
||||
import com.intellij.xdebugger.evaluation.XDebuggerEvaluator;
|
||||
import com.intellij.xdebugger.frame.*;
|
||||
import org.intellij.plugins.xsltDebugger.XsltDebuggerSession;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.Debugger;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.DebuggerStoppedException;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.Value;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
|
||||
public class XsltStackFrame extends XStackFrame {
|
||||
private final Debugger.Frame myFrame;
|
||||
private final XsltDebuggerSession myDebuggerSession;
|
||||
private XSourcePosition myPosition;
|
||||
|
||||
public XsltStackFrame(Debugger.Frame frame, XsltDebuggerSession debuggerSession) {
|
||||
myFrame = frame;
|
||||
myDebuggerSession = debuggerSession;
|
||||
myPosition = XsltSourcePosition.create(frame);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getEqualityObject() {
|
||||
return super.getEqualityObject();
|
||||
}
|
||||
|
||||
@Override
|
||||
public XDebuggerEvaluator getEvaluator() {
|
||||
return myFrame instanceof Debugger.StyleFrame ? new MyEvaluator((Debugger.StyleFrame)myFrame) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public XSourcePosition getSourcePosition() {
|
||||
return myPosition;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void customizePresentation(SimpleColoredComponent component) {
|
||||
if (myDebuggerSession.getCurrentState() == Debugger.State.SUSPENDED) {
|
||||
try {
|
||||
_customizePresentation(component);
|
||||
} catch (DebuggerStoppedException ignore) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void _customizePresentation(SimpleColoredComponent component) {
|
||||
final Debugger.Frame frame = myFrame;
|
||||
if (frame instanceof Debugger.StyleFrame) {
|
||||
component.append(((Debugger.StyleFrame)frame).getInstruction(), SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES);
|
||||
} else if (frame instanceof Debugger.SourceFrame) {
|
||||
component.append(((Debugger.SourceFrame)frame).getXPath(), SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES);
|
||||
}
|
||||
component.append(" ", SimpleTextAttributes.REGULAR_ATTRIBUTES);
|
||||
|
||||
try {
|
||||
final VirtualFile file = VfsUtil.findFileByURL(new URI(frame.getURI()).toURL());
|
||||
if (file != null) {
|
||||
component.append(file.getName(), SimpleTextAttributes.REGULAR_ATTRIBUTES);
|
||||
if (frame.getLineNumber() > 0) {
|
||||
component.append(":" + frame.getLineNumber(), SimpleTextAttributes.REGULAR_ATTRIBUTES);
|
||||
}
|
||||
|
||||
component.setToolTipText(file.getPresentableUrl());
|
||||
} else {
|
||||
component.append(frame.getURI() + ":" + frame.getLineNumber(), SimpleTextAttributes.REGULAR_ATTRIBUTES);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
component.append(frame.getURI() + ":" + frame.getLineNumber(), SimpleTextAttributes.REGULAR_ATTRIBUTES);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void computeChildren(@NotNull XCompositeNode node) {
|
||||
if (myFrame instanceof Debugger.StyleFrame) {
|
||||
final List<Debugger.Variable> variables = ((Debugger.StyleFrame)myFrame).getVariables();
|
||||
final XValueChildrenList list = new XValueChildrenList();
|
||||
for (final Debugger.Variable variable : variables) {
|
||||
list.add(variable.getName(), new MyValue(variable));
|
||||
}
|
||||
node.addChildren(list, true);
|
||||
} else {
|
||||
super.computeChildren(node);
|
||||
}
|
||||
}
|
||||
|
||||
public Debugger.Frame getFrame() {
|
||||
return myFrame;
|
||||
}
|
||||
|
||||
private static class MyValue extends XValue {
|
||||
private final Debugger.Variable myVariable;
|
||||
|
||||
public MyValue(Debugger.Variable variable) {
|
||||
myVariable = variable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void computePresentation(@NotNull XValueNode node) {
|
||||
final Debugger.Variable.Kind kind = myVariable.getKind();
|
||||
Icon icon = null;
|
||||
if (myVariable.isGlobal()) {
|
||||
if (kind == Debugger.Variable.Kind.VARIABLE) {
|
||||
icon = Icons.FIELD_ICON;
|
||||
} else {
|
||||
icon = Icons.PROPERTY_ICON;
|
||||
}
|
||||
} else if (kind == Debugger.Variable.Kind.VARIABLE) {
|
||||
icon = Icons.VARIABLE_ICON;
|
||||
} else if (kind == Debugger.Variable.Kind.PARAMETER) {
|
||||
icon = Icons.PARAMETER_ICON;
|
||||
}
|
||||
|
||||
final Value v = myVariable.getValue();
|
||||
if (v.getType() == Value.XPathType.STRING) {
|
||||
node.setPresentation(icon, v.getType().getName(), "'" + String.valueOf(v.getValue()) + "'", false);
|
||||
} else {
|
||||
final boolean hasChildren = myVariable.getValue().getValue() instanceof Value.NodeSet;
|
||||
node.setPresentation(icon, v.getType().getName(), String.valueOf(v.getValue()), hasChildren);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void computeChildren(@NotNull XCompositeNode node) {
|
||||
if (myVariable.getValue().getValue() instanceof Value.NodeSet) {
|
||||
final Value.NodeSet set = (Value.NodeSet)myVariable.getValue().getValue();
|
||||
final XValueChildrenList list = new XValueChildrenList();
|
||||
for (final Value.Node n : set.getNodes()) {
|
||||
list.add(n.myXPath, new NodeValue(n));
|
||||
}
|
||||
node.addChildren(list, false);
|
||||
}
|
||||
super.computeChildren(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEvaluationExpression() {
|
||||
return "$" + myVariable.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void computeSourcePosition(@NotNull XNavigatable navigatable) {
|
||||
navigatable.setSourcePosition(XsltSourcePosition.create(myVariable));
|
||||
}
|
||||
|
||||
static String clipValue(String stringValue) {
|
||||
return stringValue.length() < 100 ? stringValue : stringValue.substring(0, 100) + "...";
|
||||
}
|
||||
|
||||
private static class NodeValue extends XValue {
|
||||
private final Value.Node myNode;
|
||||
|
||||
public NodeValue(Value.Node n) {
|
||||
myNode = n;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void computeSourcePosition(@NotNull XNavigatable navigatable) {
|
||||
navigatable.setSourcePosition(XsltSourcePosition.create(myNode));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void computePresentation(@NotNull XValueNode node) {
|
||||
node.setPresentation(null, "node", myNode.myStringValue, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class MyEvaluator extends XDebuggerEvaluator {
|
||||
private final Debugger.StyleFrame myFrame;
|
||||
|
||||
public MyEvaluator(Debugger.StyleFrame frame) {
|
||||
myFrame = frame;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCodeFragmentEvaluationSupported() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evaluate(@NotNull String expression, XEvaluationCallback callback, @Nullable XSourcePosition expressionPosition) {
|
||||
try {
|
||||
final Value eval = myFrame.eval(expression);
|
||||
callback.evaluated(new MyValue(new ExpressionResult(eval)));
|
||||
} catch (Debugger.EvaluationException e) {
|
||||
callback.errorOccurred(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private static class ExpressionResult implements Debugger.Variable {
|
||||
private final Value myValue;
|
||||
|
||||
public ExpressionResult(Value value) {
|
||||
myValue = value;
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "ConstantConditions" })
|
||||
public String getURI() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public int getLineNumber() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
public boolean isGlobal() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public Kind getKind() {
|
||||
return Kind.EXPRESSION;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return "result";
|
||||
}
|
||||
|
||||
public Value getValue() {
|
||||
return myValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
package org.intellij.plugins.xsltDebugger.ui;
|
||||
|
||||
import com.intellij.diagnostic.logging.AdditionalTabComponent;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
/*
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: sweinreuter
|
||||
* Date: 08.03.11
|
||||
*/
|
||||
abstract class AbstractTabComponent extends AdditionalTabComponent {
|
||||
private final String myTabTitle;
|
||||
|
||||
public AbstractTabComponent(String tabTitle) {
|
||||
myTabTitle = tabTitle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTabTitle() {
|
||||
return myTabTitle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JComponent getSearchComponent() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getToolbarPlace() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JComponent getToolbarContextComponent() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isContentBuiltIn() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
}
|
||||
}
|
||||
+322
@@ -0,0 +1,322 @@
|
||||
/*
|
||||
* Copyright 2002-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.ui;
|
||||
|
||||
import com.intellij.ide.DataManager;
|
||||
import com.intellij.openapi.actionSystem.PlatformDataKeys;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.pom.Navigatable;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.containers.StringInterner;
|
||||
import org.intellij.plugins.xsltDebugger.XsltDebuggerSession;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.OutputEventQueue;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
import javax.swing.tree.DefaultTreeModel;
|
||||
import javax.swing.tree.TreeNode;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: sweinreuter
|
||||
* Date: 09.06.2007
|
||||
*/
|
||||
public class GeneratedStructureModel extends DefaultTreeModel {
|
||||
@NonNls
|
||||
private static final String PENDING = "...";
|
||||
|
||||
private static WeakReference<StringInterner> ourSharedInterner;
|
||||
|
||||
private final LinkedList<DefaultMutableTreeNode> myCurrentPath = new LinkedList<DefaultMutableTreeNode>();
|
||||
private final List<DefaultMutableTreeNode> myLastNodes = new LinkedList<DefaultMutableTreeNode>();
|
||||
|
||||
private final StringInterner myInterner = getInterner();
|
||||
|
||||
// we keep a shared string interner across all currently running xslt debugger instances. it should go away once
|
||||
// all instances (and their toolwindow contents) are gone. This should minimize the memory usage of the generated
|
||||
// structure tree.
|
||||
private static StringInterner getInterner() {
|
||||
StringInterner interner;
|
||||
if (ourSharedInterner == null || (interner = ourSharedInterner.get()) == null) {
|
||||
interner = new StringInterner();
|
||||
ourSharedInterner = new WeakReference<StringInterner>(interner);
|
||||
}
|
||||
return interner;
|
||||
}
|
||||
|
||||
private boolean myFilterWhitespace;
|
||||
private boolean myListenersDisabled;
|
||||
|
||||
public GeneratedStructureModel() {
|
||||
super(new MyRootNode());
|
||||
final DefaultMutableTreeNode root = (DefaultMutableTreeNode)getRoot();
|
||||
myCurrentPath.add(root);
|
||||
root.add(new DefaultMutableTreeNode(PENDING));
|
||||
}
|
||||
|
||||
public void update(final List<OutputEventQueue.NodeEvent> eventQueue) {
|
||||
if (!SwingUtilities.isEventDispatchThread()) {
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
updateImpl(eventQueue);
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
updateImpl(eventQueue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getChild(Object parent, int index) {
|
||||
if (!myFilterWhitespace) {
|
||||
return super.getChild(parent, index);
|
||||
}
|
||||
return getFilteredChildren((DefaultMutableTreeNode)parent, false).get(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getChildCount(Object parent) {
|
||||
if (!myFilterWhitespace) {
|
||||
return super.getChildCount(parent);
|
||||
}
|
||||
return getFilteredChildren((DefaultMutableTreeNode)parent, false).size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLeaf(Object node) {
|
||||
if (!myFilterWhitespace) {
|
||||
return super.isLeaf(node);
|
||||
}
|
||||
return super.isLeaf(node) || getFilteredChildren((DefaultMutableTreeNode)node, true).size() == 0;
|
||||
}
|
||||
|
||||
private static List getFilteredChildren(DefaultMutableTreeNode node, boolean checkOnly) {
|
||||
if (node.getChildCount() == 0) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
final List<DefaultMutableTreeNode> nodes = checkOnly ?
|
||||
new SmartList<DefaultMutableTreeNode>() :
|
||||
new ArrayList<DefaultMutableTreeNode>(node.getChildCount());
|
||||
|
||||
DefaultMutableTreeNode child = (DefaultMutableTreeNode)node.getFirstChild();
|
||||
while (child != null) {
|
||||
if (child instanceof StructureNode) {
|
||||
final OutputEventQueue.NodeEvent event = (OutputEventQueue.NodeEvent)child.getUserObject();
|
||||
if (event != null && event.getType() == OutputEventQueue.CHARACTERS) {
|
||||
if (event.getValue().trim().length() == 0) {
|
||||
child = child.getNextSibling();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nodes.add(child);
|
||||
if (checkOnly) return nodes;
|
||||
|
||||
child = child.getNextSibling();
|
||||
}
|
||||
return nodes;
|
||||
}
|
||||
|
||||
private void updateImpl(List<OutputEventQueue.NodeEvent> nodeEvents) {
|
||||
if (nodeEvents.size() > 0) {
|
||||
for (DefaultMutableTreeNode node : myLastNodes) {
|
||||
if (node instanceof StructureNode) {
|
||||
((StructureNode)node).refresh();
|
||||
}
|
||||
}
|
||||
myLastNodes.clear();
|
||||
}
|
||||
|
||||
for (OutputEventQueue.NodeEvent event : nodeEvents) {
|
||||
event = intern(event);
|
||||
|
||||
final DefaultMutableTreeNode node = myCurrentPath.getFirst();
|
||||
switch (event.getType()) {
|
||||
case OutputEventQueue.START_DOCUMENT:
|
||||
break;
|
||||
case OutputEventQueue.START_ELEMENT:
|
||||
final StructureNode child = new StructureNode(event);
|
||||
myLastNodes.add(child);
|
||||
|
||||
final int index = getChildCount(node) - 1;
|
||||
node.insert(child, node.getChildCount() - 1);
|
||||
child.add(new DefaultMutableTreeNode(PENDING));
|
||||
|
||||
myCurrentPath.addFirst(child);
|
||||
|
||||
nodesWereInserted(node, new int[]{ index });
|
||||
break;
|
||||
|
||||
case OutputEventQueue.END_ELEMENT:
|
||||
if (node instanceof MyRootNode) {
|
||||
// unknown xalan bug: start/end is sometimes unbalanced. should be fixed somewhere else...
|
||||
continue;
|
||||
}
|
||||
case OutputEventQueue.END_DOCUMENT:
|
||||
final DefaultMutableTreeNode c = myCurrentPath.removeFirst();
|
||||
final int childIndex = getChildCount(c) - 1;
|
||||
final int realChildIndex = c.getChildCount() - 1;
|
||||
if (realChildIndex >= 0) {
|
||||
final DefaultMutableTreeNode childNode = (DefaultMutableTreeNode)c.getChildAt(realChildIndex);
|
||||
assert childNode.getUserObject() == PENDING;
|
||||
c.remove(realChildIndex);
|
||||
nodesWereRemoved(c, new int[]{ childIndex }, new Object[]{ childNode });
|
||||
}
|
||||
break;
|
||||
|
||||
case OutputEventQueue.TRACE_POINT:
|
||||
case OutputEventQueue.ATTRIBUTE:
|
||||
case OutputEventQueue.CHARACTERS:
|
||||
case OutputEventQueue.COMMENT:
|
||||
case OutputEventQueue.PI:
|
||||
final StructureNode ch = new StructureNode(event);
|
||||
myLastNodes.add(ch);
|
||||
|
||||
final int i = getChildCount(node) - 1;
|
||||
node.insert(ch, node.getChildCount() - 1);
|
||||
nodesWereInserted(node, new int[]{ i });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private OutputEventQueue.NodeEvent intern(OutputEventQueue.NodeEvent event) {
|
||||
event.myURI = intern(event.myURI);
|
||||
event.myQName = intern(event.myQName);
|
||||
event.myValue = intern(event.myValue);
|
||||
return event;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private OutputEventQueue.NodeEvent.QName intern(OutputEventQueue.NodeEvent.QName name) {
|
||||
if (name == null) return null;
|
||||
name.myPrefix = intern(name.myPrefix);
|
||||
name.myLocalName = intern(name.myLocalName);
|
||||
name.myURI = intern(name.myURI);
|
||||
return name;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private String intern(String s) {
|
||||
if (s != null) {
|
||||
if (s.length() == 0) return s.intern();
|
||||
return myInterner.intern(s);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isFilterWhitespace() {
|
||||
return myFilterWhitespace;
|
||||
}
|
||||
|
||||
public void setFilterWhitespace(boolean b) {
|
||||
final boolean old = myFilterWhitespace;
|
||||
myFilterWhitespace = b;
|
||||
if (b != old) {
|
||||
nodeStructureChanged((TreeNode)getRoot());
|
||||
}
|
||||
}
|
||||
|
||||
public void finalUpdate(final List<OutputEventQueue.NodeEvent> events) {
|
||||
Runnable runnable = new Runnable() {
|
||||
public void run() {
|
||||
myListenersDisabled = true;
|
||||
try {
|
||||
updateImpl(events);
|
||||
} finally {
|
||||
myListenersDisabled = false;
|
||||
nodeStructureChanged((TreeNode)getRoot());
|
||||
}
|
||||
}
|
||||
};
|
||||
ApplicationManager.getApplication().invokeLater(runnable);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fireTreeNodesChanged(Object source, Object[] path, int[] childIndices, Object[] children) {
|
||||
if (myListenersDisabled) return;
|
||||
super.fireTreeNodesChanged(source, path, childIndices, children);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fireTreeNodesInserted(Object source, Object[] path, int[] childIndices, Object[] children) {
|
||||
if (myListenersDisabled) return;
|
||||
super.fireTreeNodesInserted(source, path, childIndices, children);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fireTreeNodesRemoved(Object source, Object[] path, int[] childIndices, Object[] children) {
|
||||
if (myListenersDisabled) return;
|
||||
super.fireTreeNodesRemoved(source, path, childIndices, children);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fireTreeStructureChanged(Object source, Object[] path, int[] childIndices, Object[] children) {
|
||||
if (myListenersDisabled) return;
|
||||
super.fireTreeStructureChanged(source, path, childIndices, children);
|
||||
}
|
||||
|
||||
private static class MyRootNode extends DefaultMutableTreeNode {
|
||||
public MyRootNode() {
|
||||
super("ROOT");
|
||||
}
|
||||
}
|
||||
|
||||
public static class StructureNode extends DefaultMutableTreeNode implements Navigatable {
|
||||
private boolean isNew = true;
|
||||
|
||||
public StructureNode(OutputEventQueue.NodeEvent event) {
|
||||
super(event);
|
||||
}
|
||||
|
||||
private void refresh() {
|
||||
isNew = false;
|
||||
}
|
||||
|
||||
public boolean isNew() {
|
||||
return isNew;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OutputEventQueue.NodeEvent getUserObject() {
|
||||
return (OutputEventQueue.NodeEvent)super.getUserObject();
|
||||
}
|
||||
|
||||
public void navigate(boolean requestFocus) {
|
||||
final OutputEventQueue.NodeEvent event = getUserObject();
|
||||
final Project project = (Project)DataManager.getInstance().getDataContext().getData(PlatformDataKeys.PROJECT.getName());
|
||||
XsltDebuggerSession.openLocation(project, event.getURI(), event.getLineNumber() - 1);
|
||||
}
|
||||
|
||||
public boolean canNavigate() {
|
||||
return getUserObject().getLineNumber() > 0;
|
||||
}
|
||||
|
||||
public boolean canNavigateToSource() {
|
||||
return canNavigate();
|
||||
}
|
||||
}
|
||||
}
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright 2002-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.ui;
|
||||
|
||||
import com.intellij.openapi.util.IconLoader;
|
||||
import com.intellij.ui.ColoredTreeCellRenderer;
|
||||
import com.intellij.ui.SimpleTextAttributes;
|
||||
import com.intellij.util.Icons;
|
||||
import com.intellij.xdebugger.ui.DebuggerIcons;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.OutputEventQueue;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: sweinreuter
|
||||
* Date: 09.06.2007
|
||||
*/
|
||||
class GeneratedStructureRenderer extends ColoredTreeCellRenderer {
|
||||
private static final Icon XML_COMMENT_ICON = IconLoader.getIcon("xmlComment.png");
|
||||
|
||||
public void customizeCellRenderer(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
|
||||
final DefaultMutableTreeNode node = (DefaultMutableTreeNode)value;
|
||||
final Object o = node.getUserObject();
|
||||
|
||||
if (o == null || "ROOT".equals(o)) {
|
||||
// invisible
|
||||
} else if (o instanceof String) {
|
||||
// "..." node
|
||||
append((String)o, SimpleTextAttributes.SYNTHETIC_ATTRIBUTES);
|
||||
setToolTipText("Element is not finished yet");
|
||||
} else if (o instanceof OutputEventQueue.NodeEvent) {
|
||||
final OutputEventQueue.NodeEvent event = (OutputEventQueue.NodeEvent)o;
|
||||
final OutputEventQueue.NodeEvent.QName qname = event.getQName();
|
||||
switch (event.getType()) {
|
||||
case OutputEventQueue.START_ELEMENT:
|
||||
setIcon(Icons.XML_TAG_ICON);
|
||||
append(qname.getQName(), SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES);
|
||||
if (qname.myURI != null && qname.myURI.length() > 0) {
|
||||
append(" {", SimpleTextAttributes.GRAYED_ATTRIBUTES);
|
||||
append(qname.myURI, SimpleTextAttributes.GRAYED_ATTRIBUTES);
|
||||
append("}", SimpleTextAttributes.GRAYED_ATTRIBUTES);
|
||||
}
|
||||
break;
|
||||
case OutputEventQueue.ATTRIBUTE:
|
||||
setIcon(Icons.ANNOTATION_TYPE_ICON);
|
||||
append(qname.getQName(), SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES);
|
||||
if (qname.myURI != null && qname.myURI.length() > 0) {
|
||||
append(" {" + qname.myURI + "}", SimpleTextAttributes.GRAYED_ATTRIBUTES);
|
||||
}
|
||||
append(" = \"", SimpleTextAttributes.REGULAR_ATTRIBUTES);
|
||||
append(event.getValue(), SimpleTextAttributes.REGULAR_ATTRIBUTES);
|
||||
append("\"", SimpleTextAttributes.REGULAR_ATTRIBUTES);
|
||||
break;
|
||||
case OutputEventQueue.CHARACTERS:
|
||||
append("#text ", SimpleTextAttributes.GRAYED_ATTRIBUTES);
|
||||
append(clipValue(event.getValue()), SimpleTextAttributes.REGULAR_ATTRIBUTES);
|
||||
break;
|
||||
case OutputEventQueue.COMMENT:
|
||||
setIcon(XML_COMMENT_ICON);
|
||||
append("#comment ", SimpleTextAttributes.GRAYED_ATTRIBUTES);
|
||||
append(event.getValue(), SimpleTextAttributes.REGULAR_ATTRIBUTES);
|
||||
break;
|
||||
case OutputEventQueue.PI:
|
||||
append("#processing-instruction ", SimpleTextAttributes.GRAYED_ATTRIBUTES);
|
||||
append(qname.myLocalName, SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES);
|
||||
append(" " + event.getValue(), SimpleTextAttributes.REGULAR_ATTRIBUTES);
|
||||
break;
|
||||
case OutputEventQueue.TRACE_POINT:
|
||||
setIcon(DebuggerIcons.ENABLED_BREAKPOINT_ICON);
|
||||
append("Tracepoint at line " + event.getLineNumber(), SimpleTextAttributes.GRAY_ATTRIBUTES);
|
||||
if (event.getValue() != null) {
|
||||
append(" " + event.getValue(), SimpleTextAttributes.REGULAR_ATTRIBUTES);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (node instanceof GeneratedStructureModel.StructureNode) {
|
||||
if (((GeneratedStructureModel.StructureNode)node).isNew()) {
|
||||
append(" *", SimpleTextAttributes.SYNTHETIC_ATTRIBUTES);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static String clipValue(String stringValue) {
|
||||
return stringValue.length() < 80 ? stringValue : stringValue.substring(0, 80) + "...";
|
||||
}
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
package org.intellij.plugins.xsltDebugger.ui;
|
||||
|
||||
import com.intellij.diagnostic.logging.AdditionalTabComponent;
|
||||
import com.intellij.openapi.actionSystem.ActionGroup;
|
||||
import com.intellij.openapi.actionSystem.DefaultActionGroup;
|
||||
import org.intellij.plugins.xsltDebugger.ui.actions.OpenOutputAction;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
public class OutputTabComponent extends AbstractTabComponent {
|
||||
private final DefaultActionGroup myOutputActions;
|
||||
private final AdditionalTabComponent myOutputConsole;
|
||||
|
||||
public OutputTabComponent(AdditionalTabComponent outputConsole) {
|
||||
super("Output");
|
||||
|
||||
myOutputConsole = outputConsole;
|
||||
final DefaultActionGroup outputActions = new DefaultActionGroup();
|
||||
outputActions.add(new OpenOutputAction(outputConsole));
|
||||
myOutputActions = outputActions;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JComponent getComponent() {
|
||||
return myOutputConsole;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JComponent getPreferredFocusableComponent() {
|
||||
return myOutputConsole.getPreferredFocusableComponent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionGroup getToolbarActions() {
|
||||
return myOutputActions;
|
||||
}
|
||||
}
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright 2002-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.ui;
|
||||
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.util.Alarm;
|
||||
import com.intellij.util.ui.tree.TreeModelAdapter;
|
||||
import com.intellij.util.ui.tree.TreeUtil;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.TreeModelEvent;
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
import javax.swing.tree.TreeNode;
|
||||
import javax.swing.tree.TreePath;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: sweinreuter
|
||||
* Date: 09.06.2007
|
||||
*/
|
||||
public class SmartStructureTracker extends TreeModelAdapter {
|
||||
private final JTree myEventTree;
|
||||
private final Alarm myAlarm;
|
||||
|
||||
public SmartStructureTracker(JTree eventTree, Disposable disposable) {
|
||||
myEventTree = eventTree;
|
||||
myAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD, disposable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void treeNodesInserted(TreeModelEvent e) {
|
||||
final TreePath path = e.getTreePath();
|
||||
final Object child = e.getChildren()[0];
|
||||
if (path != null && child != null) {
|
||||
myAlarm.cancelAllRequests();
|
||||
final Runnable runnable = new Runnable() {
|
||||
public void run() {
|
||||
myEventTree.expandPath(path);
|
||||
TreeUtil.showRowCentered(myEventTree, myEventTree.getRowForPath(TreeUtil.getPathFromRoot((TreeNode)child)), false);
|
||||
}
|
||||
};
|
||||
myAlarm.addRequest(runnable, 300);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void treeNodesRemoved(TreeModelEvent e) {
|
||||
final TreePath p = e.getTreePath();
|
||||
if (p != null) {
|
||||
if (p.getPathCount() > 1) {
|
||||
final Runnable runnable = new Runnable() {
|
||||
public void run() {
|
||||
DefaultMutableTreeNode last = (DefaultMutableTreeNode)p.getLastPathComponent();
|
||||
if (last.getChildCount() > 0) {
|
||||
DefaultMutableTreeNode next = (DefaultMutableTreeNode)last.getFirstChild();
|
||||
while (next != null) {
|
||||
boolean collapse = true;
|
||||
// final int count = next.getChildCount();
|
||||
// if (count > 0) {
|
||||
// for (int i = 0; i < count; i++) {
|
||||
// final DefaultMutableTreeNode child = (DefaultMutableTreeNode)next.getChildAt(i);
|
||||
// if (child instanceof GeneratedStructureModel.StructureNode) {
|
||||
// if (((GeneratedStructureModel.StructureNode)child).isNew()) {
|
||||
// collapse = false;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
if (collapse) {
|
||||
myEventTree.collapsePath(TreeUtil.getPathFromRoot(next));
|
||||
}
|
||||
next = next.getNextSibling();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
ApplicationManager.getApplication().invokeLater(runnable);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
package org.intellij.plugins.xsltDebugger.ui;
|
||||
|
||||
import com.intellij.execution.process.ProcessHandler;
|
||||
import com.intellij.ide.CommonActionsManager;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.actionSystem.ActionGroup;
|
||||
import com.intellij.openapi.actionSystem.DefaultActionGroup;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.ui.treeStructure.Tree;
|
||||
import org.intellij.plugins.xsltDebugger.ui.actions.HideWhitespaceAction;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
public class StructureTabComponent extends AbstractTabComponent {
|
||||
private static final Key<StructureTabComponent> KEY = Key.create("STRUCTURE");
|
||||
|
||||
private final DefaultActionGroup myToolbarActions;
|
||||
private final Tree myStructureTree;
|
||||
private final GeneratedStructureModel myEventModel;
|
||||
|
||||
private StructureTabComponent(Disposable disposable) {
|
||||
super("Structure");
|
||||
|
||||
myEventModel = new GeneratedStructureModel();
|
||||
myStructureTree = new StructureTree(myEventModel);
|
||||
myEventModel.addTreeModelListener(new SmartStructureTracker(myStructureTree, disposable));
|
||||
|
||||
final DefaultActionGroup structureActions = new DefaultActionGroup();
|
||||
final StructureTreeExpander expander = new StructureTreeExpander(myStructureTree);
|
||||
final CommonActionsManager actionsManager = CommonActionsManager.getInstance();
|
||||
structureActions.add(new HideWhitespaceAction(myStructureTree, myEventModel));
|
||||
structureActions.add(actionsManager.createExpandAllAction(expander, myStructureTree));
|
||||
structureActions.add(actionsManager.createCollapseAllAction(expander, myStructureTree));
|
||||
|
||||
myToolbarActions = structureActions;
|
||||
}
|
||||
|
||||
public GeneratedStructureModel getEventModel() {
|
||||
return myEventModel;
|
||||
}
|
||||
|
||||
public static StructureTabComponent create(ProcessHandler process, Disposable disposable) {
|
||||
final StructureTabComponent component = new StructureTabComponent(disposable);
|
||||
process.putUserData(KEY, component);
|
||||
return component;
|
||||
}
|
||||
|
||||
public static StructureTabComponent getInstance(ProcessHandler process) {
|
||||
return process.getUserData(KEY);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JComponent getComponent() {
|
||||
return myStructureTree;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JComponent getPreferredFocusableComponent() {
|
||||
return getComponent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionGroup getToolbarActions() {
|
||||
return myToolbarActions;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 2002-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.ui;
|
||||
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.pom.Navigatable;
|
||||
import com.intellij.ui.PopupHandler;
|
||||
import com.intellij.ui.treeStructure.Tree;
|
||||
import org.intellij.plugins.xsltDebugger.ui.actions.CopyValueAction;
|
||||
import org.intellij.plugins.xsltDebugger.ui.actions.NavigateAction;
|
||||
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
import javax.swing.tree.TreePath;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: sweinreuter
|
||||
* Date: 17.06.2007
|
||||
*/
|
||||
public class StructureTree extends Tree implements TypeSafeDataProvider {
|
||||
public StructureTree(GeneratedStructureModel model) {
|
||||
super(model);
|
||||
|
||||
setCellRenderer(new GeneratedStructureRenderer());
|
||||
setRootVisible(false);
|
||||
setShowsRootHandles(true);
|
||||
|
||||
final DefaultActionGroup structureContextActions = new DefaultActionGroup("StructureContext", true);
|
||||
structureContextActions.add(NavigateAction.getInstance());
|
||||
structureContextActions.add(new CopyValueAction(this));
|
||||
PopupHandler.installFollowingSelectionTreePopup(this, structureContextActions, "XSLT.Debugger.GeneratedStructure", ActionManager.getInstance());
|
||||
}
|
||||
|
||||
public void calcData(DataKey key, DataSink sink) {
|
||||
if (key.equals(PlatformDataKeys.NAVIGATABLE)) {
|
||||
final TreePath selection = getSelectionPath();
|
||||
if (selection != null) {
|
||||
final Object o = selection.getLastPathComponent();
|
||||
if (o instanceof Navigatable) {
|
||||
sink.put(PlatformDataKeys.NAVIGATABLE, (Navigatable)o);
|
||||
}
|
||||
}
|
||||
} else if (key.equals(CopyValueAction.SELECTED_NODE)) {
|
||||
final TreePath selection = getSelectionPath();
|
||||
if (selection != null) {
|
||||
final Object o = selection.getLastPathComponent();
|
||||
sink.put(CopyValueAction.SELECTED_NODE, (DefaultMutableTreeNode)o);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2002-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.ui;
|
||||
|
||||
import com.intellij.ide.TreeExpander;
|
||||
import com.intellij.util.ui.tree.TreeUtil;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: sweinreuter
|
||||
* Date: 28.11.2007
|
||||
*/
|
||||
public class StructureTreeExpander implements TreeExpander {
|
||||
private final JTree myTree;
|
||||
|
||||
public StructureTreeExpander(JTree tree) {
|
||||
myTree = tree;
|
||||
}
|
||||
|
||||
public void expandAll() {
|
||||
TreeUtil.expandAll(myTree);
|
||||
}
|
||||
|
||||
public boolean canExpand() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void collapseAll() {
|
||||
TreeUtil.collapseAll(myTree, 1);
|
||||
}
|
||||
|
||||
public boolean canCollapse() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright 2002-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.ui.actions;
|
||||
|
||||
import com.intellij.openapi.actionSystem.ActionManager;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.DataKey;
|
||||
import com.intellij.openapi.ide.CopyPasteManager;
|
||||
import org.intellij.plugins.xsltDebugger.rt.engine.OutputEventQueue;
|
||||
import org.intellij.plugins.xsltDebugger.ui.GeneratedStructureModel;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
import java.awt.datatransfer.StringSelection;
|
||||
|
||||
@SuppressWarnings({ "ComponentNotRegistered" })
|
||||
public class CopyValueAction extends AnAction {
|
||||
public static final DataKey<DefaultMutableTreeNode> SELECTED_NODE = DataKey.create("SELECTED_NODE");
|
||||
|
||||
public CopyValueAction(JComponent component) {
|
||||
final AnAction action = ActionManager.getInstance().getAction("$Copy");
|
||||
if (action != null) {
|
||||
copyFrom(action);
|
||||
registerCustomShortcutSet(getShortcutSet(), component);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(AnActionEvent e) {
|
||||
e.getPresentation().setEnabled(isEnabled(e));
|
||||
}
|
||||
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
final DefaultMutableTreeNode node = e.getData(SELECTED_NODE);
|
||||
if (node instanceof GeneratedStructureModel.StructureNode) {
|
||||
final GeneratedStructureModel.StructureNode structureNode = (GeneratedStructureModel.StructureNode)node;
|
||||
final OutputEventQueue.NodeEvent event = structureNode.getUserObject();
|
||||
setClipboardData(event.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
private static void setClipboardData(String value) {
|
||||
CopyPasteManager.getInstance().setContents(new StringSelection(value));
|
||||
}
|
||||
|
||||
protected static boolean isEnabled(AnActionEvent e) {
|
||||
final DefaultMutableTreeNode node = e.getData(SELECTED_NODE);
|
||||
if (node instanceof GeneratedStructureModel.StructureNode) {
|
||||
final GeneratedStructureModel.StructureNode structureNode = (GeneratedStructureModel.StructureNode)node;
|
||||
final OutputEventQueue.NodeEvent event = structureNode.getUserObject();
|
||||
return event != null && event.getValue() != null;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2002-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.ui.actions;
|
||||
|
||||
import com.intellij.ide.util.treeView.TreeState;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.ToggleAction;
|
||||
import com.intellij.openapi.util.IconLoader;
|
||||
import com.intellij.ui.treeStructure.Tree;
|
||||
import org.intellij.plugins.xsltDebugger.ui.GeneratedStructureModel;
|
||||
|
||||
@SuppressWarnings({ "ComponentNotRegistered" })
|
||||
public class HideWhitespaceAction extends ToggleAction {
|
||||
private final Tree myStructureTree;
|
||||
private final GeneratedStructureModel myEventModel;
|
||||
|
||||
public HideWhitespaceAction(Tree structureTree, GeneratedStructureModel eventModel) {
|
||||
super("Hide Whitespace Nodes");
|
||||
myStructureTree = structureTree;
|
||||
myEventModel = eventModel;
|
||||
|
||||
getTemplatePresentation().setIcon(IconLoader.getIcon("filterWhitespace.png"));
|
||||
}
|
||||
|
||||
public boolean isSelected(AnActionEvent e) {
|
||||
return myEventModel.isFilterWhitespace();
|
||||
}
|
||||
|
||||
public void setSelected(AnActionEvent e, boolean state) {
|
||||
final TreeState treeState = TreeState.createOn(myStructureTree);
|
||||
myEventModel.setFilterWhitespace(state);
|
||||
treeState.applyTo(myStructureTree);
|
||||
}
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2002-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.ui.actions;
|
||||
|
||||
import com.intellij.openapi.actionSystem.ActionManager;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.IdeActions;
|
||||
|
||||
public class NavigateAction {
|
||||
private NavigateAction() {
|
||||
}
|
||||
|
||||
public static AnAction getInstance() {
|
||||
return ActionManager.getInstance().getAction(IdeActions.ACTION_EDIT_SOURCE);
|
||||
}
|
||||
}
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 2002-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.ui.actions;
|
||||
|
||||
import com.intellij.diagnostic.logging.AdditionalTabComponent;
|
||||
import com.intellij.ide.DataManager;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.PlatformDataKeys;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager;
|
||||
import com.intellij.openapi.util.IconLoader;
|
||||
import com.intellij.openapi.vcs.vfs.VcsFileSystem;
|
||||
import com.intellij.openapi.vcs.vfs.VcsVirtualFile;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
@SuppressWarnings({ "ComponentNotRegistered" })
|
||||
public class OpenOutputAction extends AnAction {
|
||||
private final AdditionalTabComponent myConsole;
|
||||
|
||||
public OpenOutputAction(AdditionalTabComponent console) {
|
||||
super("Open in Editor");
|
||||
myConsole = console;
|
||||
getTemplatePresentation().setIcon(IconLoader.getIcon("/actions/export.png"));
|
||||
}
|
||||
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
final Editor editor = PlatformDataKeys.EDITOR.getData(DataManager.getInstance().getDataContext(myConsole.getComponent()));
|
||||
if (editor != null) {
|
||||
try {
|
||||
final byte[] content = editor.getDocument().getText().getBytes("UTF-8");
|
||||
final String extension = "xml"; // TODO: get from output type
|
||||
final VcsVirtualFile file = new VcsVirtualFile("XSLT Output." + extension, content, null, VcsFileSystem.getInstance()) {
|
||||
@Override
|
||||
public Charset getCharset() {
|
||||
return Charset.forName("UTF-8");
|
||||
}
|
||||
};
|
||||
FileEditorManager.getInstance(PlatformDataKeys.PROJECT.getData(e.getDataContext())).openFile(file, true);
|
||||
} catch (UnsupportedEncodingException e1) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void update(AnActionEvent e) {
|
||||
final Editor editor = PlatformDataKeys.EDITOR.getData(DataManager.getInstance().getDataContext(myConsole.getComponent()));
|
||||
e.getPresentation().setEnabled(editor != null && editor.getDocument().getTextLength() > 0);
|
||||
}
|
||||
}
|
||||
BIN
Binary file not shown.
|
After Width: | Height: | Size: 432 B |
Binary file not shown.
|
After Width: | Height: | Size: 472 B |
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module relativePaths="true" type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/dist" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/out" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="module" module-name="xpath" />
|
||||
<orderEntry type="module" module-name="xslt-debugger-rt" />
|
||||
<orderEntry type="module" module-name="lang-api" />
|
||||
<orderEntry type="module" module-name="lang-impl" />
|
||||
<orderEntry type="module" module-name="xdebugger-api" />
|
||||
<orderEntry type="module" module-name="xdebugger-impl" />
|
||||
<orderEntry type="module" module-name="xml-openapi" />
|
||||
<orderEntry type="module" module-name="compiler-impl" />
|
||||
<orderEntry type="module" module-name="openapi" />
|
||||
<orderEntry type="module" module-name="xml" />
|
||||
<orderEntry type="module" module-name="execution-openapi" />
|
||||
<orderEntry type="module" module-name="debugger-impl" />
|
||||
<orderEntry type="module" module-name="platform-impl" />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
Reference in New Issue
Block a user