From 4b43cbce554a2669b2fe4102d3ebcae108fe9a8c Mon Sep 17 00:00:00 2001 From: konsoletyper Date: Wed, 30 Jul 2014 23:32:42 +0400 Subject: [PATCH] First attempt to create a TeaVM eclipse plugin --- teavm-chrome-rdp/pom.xml | 11 + .../org/teavm/chromerdp/ChromeRDPServer.java | 11 +- teavm-core/pom.xml | 13 ++ teavm-eclipse/.gitignore | 4 + teavm-eclipse/META-INF/MANIFEST.MF | 11 + teavm-eclipse/build.properties | 4 + teavm-eclipse/plugin.xml | 5 + .../eclipse/debugger/TeaVMDebugTarget.java | 199 ++++++++++++++++++ .../TeaVMLaunchConfigurationDelegate.java | 85 ++++++++ 9 files changed, 342 insertions(+), 1 deletion(-) create mode 100644 teavm-eclipse/.gitignore create mode 100644 teavm-eclipse/META-INF/MANIFEST.MF create mode 100644 teavm-eclipse/build.properties create mode 100644 teavm-eclipse/plugin.xml create mode 100644 teavm-eclipse/src/main/java/org/teavm/eclipse/debugger/TeaVMDebugTarget.java create mode 100644 teavm-eclipse/src/main/java/org/teavm/eclipse/debugger/TeaVMLaunchConfigurationDelegate.java diff --git a/teavm-chrome-rdp/pom.xml b/teavm-chrome-rdp/pom.xml index 580e21dc2..3d2c429be 100644 --- a/teavm-chrome-rdp/pom.xml +++ b/teavm-chrome-rdp/pom.xml @@ -83,6 +83,17 @@ org.apache.maven.plugins maven-javadoc-plugin + + org.apache.felix + maven-bundle-plugin + true + + + org.teavm.chromerdp + teavm-chrome-rdp + + + \ No newline at end of file diff --git a/teavm-chrome-rdp/src/main/java/org/teavm/chromerdp/ChromeRDPServer.java b/teavm-chrome-rdp/src/main/java/org/teavm/chromerdp/ChromeRDPServer.java index f368db5a5..1ce5060c3 100644 --- a/teavm-chrome-rdp/src/main/java/org/teavm/chromerdp/ChromeRDPServer.java +++ b/teavm-chrome-rdp/src/main/java/org/teavm/chromerdp/ChromeRDPServer.java @@ -33,6 +33,7 @@ import org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainer public class ChromeRDPServer { private int port = 2357; private ChromeRDPExchangeConsumer exchangeConsumer; + private Server server; public int getPort() { return port; @@ -51,7 +52,7 @@ public class ChromeRDPServer { } public void start() { - final Server server = new Server(); + server = new Server(); ServerConnector connector = new ServerConnector(server); connector.setPort(port); server.addConnector(connector); @@ -71,6 +72,14 @@ public class ChromeRDPServer { } } + public void stop() { + try { + server.stop(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + private class RPDEndpointConfig implements ServerEndpointConfig { private Map userProperties = new HashMap<>(); diff --git a/teavm-core/pom.xml b/teavm-core/pom.xml index f5add08f4..7729733b0 100644 --- a/teavm-core/pom.xml +++ b/teavm-core/pom.xml @@ -24,6 +24,8 @@ teavm-core + bundle + junit @@ -75,6 +77,17 @@ org.apache.maven.plugins maven-javadoc-plugin + + org.apache.felix + maven-bundle-plugin + true + + + org.teavm.* + teavm-core + + + diff --git a/teavm-eclipse/.gitignore b/teavm-eclipse/.gitignore new file mode 100644 index 000000000..4e247eee2 --- /dev/null +++ b/teavm-eclipse/.gitignore @@ -0,0 +1,4 @@ +/.settings +/target +/.classpath +/.project diff --git a/teavm-eclipse/META-INF/MANIFEST.MF b/teavm-eclipse/META-INF/MANIFEST.MF new file mode 100644 index 000000000..dd2fd6e7e --- /dev/null +++ b/teavm-eclipse/META-INF/MANIFEST.MF @@ -0,0 +1,11 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: TeaVM eclipse support +Bundle-SymbolicName: teavm-eclipse;singleton:=true +Bundle-Version: 0.2.0 +Bundle-RequiredExecutionEnvironment: JavaSE-1.7 +Require-Bundle: org.eclipse.debug.core;bundle-version="3.8.0", + org.eclipse.debug.ui;bundle-version="3.9.0", + org.eclipse.core.runtime;bundle-version="3.9.0", + org.eclipse.swt;bundle-version="3.102.0", + org.eclipse.jdt.debug;bundle-version="3.8.0" diff --git a/teavm-eclipse/build.properties b/teavm-eclipse/build.properties new file mode 100644 index 000000000..b506aa447 --- /dev/null +++ b/teavm-eclipse/build.properties @@ -0,0 +1,4 @@ +source.. = src/main/java/ +output.. = target/ +bin.includes = META-INF/,\ + . diff --git a/teavm-eclipse/plugin.xml b/teavm-eclipse/plugin.xml new file mode 100644 index 000000000..2bf043fd6 --- /dev/null +++ b/teavm-eclipse/plugin.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/teavm-eclipse/src/main/java/org/teavm/eclipse/debugger/TeaVMDebugTarget.java b/teavm-eclipse/src/main/java/org/teavm/eclipse/debugger/TeaVMDebugTarget.java new file mode 100644 index 000000000..72004b57d --- /dev/null +++ b/teavm-eclipse/src/main/java/org/teavm/eclipse/debugger/TeaVMDebugTarget.java @@ -0,0 +1,199 @@ +package org.teavm.eclipse.debugger; + +import org.eclipse.core.resources.IMarkerDelta; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.debug.core.DebugEvent; +import org.eclipse.debug.core.DebugException; +import org.eclipse.debug.core.DebugPlugin; +import org.eclipse.debug.core.ILaunch; +import org.eclipse.debug.core.model.IBreakpoint; +import org.eclipse.debug.core.model.IDebugTarget; +import org.eclipse.debug.core.model.ILineBreakpoint; +import org.eclipse.debug.core.model.IMemoryBlock; +import org.eclipse.debug.core.model.IProcess; +import org.eclipse.debug.core.model.IThread; +import org.eclipse.jdt.debug.core.IJavaLineBreakpoint; +import org.teavm.chromerdp.ChromeRDPServer; +import org.teavm.debugging.Breakpoint; +import org.teavm.debugging.Debugger; +import org.teavm.debugging.DebuggerListener; + +/** + * + * @author Alexey Andreev + */ +@SuppressWarnings("rawtypes") +public class TeaVMDebugTarget implements IDebugTarget { + private ILaunch launch; + private Debugger teavmDebugger; + private ChromeRDPServer server; + private boolean terminated; + + public TeaVMDebugTarget(ILaunch launch, Debugger teavmDebugger, ChromeRDPServer server) { + this.launch = launch; + this.teavmDebugger = teavmDebugger; + this.server = server; + teavmDebugger.addListener(new DebuggerListener() { + @Override + public void resumed() { + fireEvent(new DebugEvent(TeaVMDebugTarget.this, DebugEvent.RESUME)); + } + + @Override + public void paused() { + fireEvent(new DebugEvent(TeaVMDebugTarget.this, DebugEvent.SUSPEND)); + } + + @Override + public void detached() { + fireEvent(new DebugEvent(TeaVMDebugTarget.this, DebugEvent.CHANGE)); + } + + @Override + public void breakpointStatusChanged(Breakpoint breakpoint) { + } + + @Override + public void attached() { + fireEvent(new DebugEvent(TeaVMDebugTarget.this, DebugEvent.CHANGE)); + } + }); + } + + private void fireEvent(DebugEvent event) { + DebugPlugin.getDefault().fireDebugEventSet(new DebugEvent[] { event }); + } + + @Override + public boolean canTerminate() { + return true; + } + + @Override + public boolean isTerminated() { + return terminated; + } + + @Override + public void terminate() throws DebugException { + terminated = true; + server.stop(); + } + + @Override + public Object getAdapter(Class arg0) { + return null; + } + + @Override + public void breakpointAdded(IBreakpoint breakpoint) { + if (!(breakpoint instanceof ILineBreakpoint)) { + return; + } + IJavaLineBreakpoint lineBreakpoint = (IJavaLineBreakpoint)breakpoint; + try { + lineBreakpoint.setRegistered(true); + String fileName = lineBreakpoint.getTypeName().replace('.', '/') + ".java"; + teavmDebugger.createBreakpoint(fileName, lineBreakpoint.getLineNumber()); + } catch (CoreException e) { + throw new RuntimeException(e); + } + } + + @Override + public void breakpointChanged(IBreakpoint arg0, IMarkerDelta arg1) { + } + + @Override + public void breakpointRemoved(IBreakpoint arg0, IMarkerDelta arg1) { + } + + @Override + public boolean canResume() { + return true; + } + + @Override + public boolean canSuspend() { + return true; + } + + @Override + public boolean isSuspended() { + return teavmDebugger.isSuspended(); + } + + @Override + public void resume() throws DebugException { + teavmDebugger.resume(); + } + + @Override + public void suspend() throws DebugException { + teavmDebugger.suspend(); + } + + @Override + public IMemoryBlock getMemoryBlock(long arg0, long arg1) throws DebugException { + return null; + } + + @Override + public boolean supportsStorageRetrieval() { + return false; + } + + @Override + public IDebugTarget getDebugTarget() { + return this; + } + + @Override + public ILaunch getLaunch() { + return launch; + } + + @Override + public String getModelIdentifier() { + return ""; + } + + @Override + public boolean canDisconnect() { + return true; + } + + @Override + public void disconnect() throws DebugException { + } + + @Override + public boolean isDisconnected() { + return teavmDebugger.isAttached(); + } + + @Override + public String getName() throws DebugException { + return "TeaVM debugger"; + } + + @Override + public IProcess getProcess() { + return null; + } + + @Override + public IThread[] getThreads() throws DebugException { + return null; + } + + @Override + public boolean hasThreads() throws DebugException { + return false; + } + + @Override + public boolean supportsBreakpoint(IBreakpoint breakpoint) { + return breakpoint instanceof IJavaLineBreakpoint; + } +} diff --git a/teavm-eclipse/src/main/java/org/teavm/eclipse/debugger/TeaVMLaunchConfigurationDelegate.java b/teavm-eclipse/src/main/java/org/teavm/eclipse/debugger/TeaVMLaunchConfigurationDelegate.java new file mode 100644 index 000000000..44503fba5 --- /dev/null +++ b/teavm-eclipse/src/main/java/org/teavm/eclipse/debugger/TeaVMLaunchConfigurationDelegate.java @@ -0,0 +1,85 @@ +package org.teavm.eclipse.debugger; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.debug.core.ILaunch; +import org.eclipse.debug.core.ILaunchConfiguration; +import org.eclipse.debug.core.ILaunchManager; +import org.eclipse.debug.core.model.ILaunchConfigurationDelegate; +import org.eclipse.swt.widgets.Display; +import org.teavm.chromerdp.*; +import org.teavm.debugging.Debugger; +import org.teavm.debugging.URLDebugInformationProvider; + +/** + * + * @author Alexey Andreev + */ +public class TeaVMLaunchConfigurationDelegate implements ILaunchConfigurationDelegate { + @Override + public void launch(ILaunchConfiguration configuration, String mode, ILaunch launch, IProgressMonitor monitor) + throws CoreException { + if (!mode.equals(ILaunchManager.DEBUG_MODE)) { + throw new IllegalArgumentException("Only debug mode supported"); + } + int port = configuration.getAttribute("teavm-debugger-port", 2357); + ChromeRDPServer server = new ChromeRDPServer(); + server.setPort(port); + ChromeRDPDebugger jsDebugger = new ChromeRDPDebugger(); + server.setExchangeConsumer(new SynchronousMessageExchange(jsDebugger)); + Debugger debugger = new Debugger(jsDebugger, new URLDebugInformationProvider("")); + server.start(); + launch.addDebugTarget(new TeaVMDebugTarget(launch, debugger, server)); + monitor.done(); + } + + private static class SynchronousMessageExchange implements ChromeRDPExchangeConsumer, + ChromeRDPExchange { + private List listeners = new ArrayList<>(); + private ChromeRDPDebugger debugger; + private ChromeRDPExchange exchange; + + public SynchronousMessageExchange(ChromeRDPDebugger debugger) { + this.debugger = debugger; + } + + @Override + public void setExchange(ChromeRDPExchange exchange) { + this.exchange = exchange; + debugger.setExchange(this); + exchange.addListener(new ChromeRDPExchangeListener() { + @Override public void received(final String message) throws IOException { + Display.getCurrent().asyncExec(new Runnable() { + @Override public void run() { + try { + for (ChromeRDPExchangeListener listener : listeners) { + listener.received(message); + } + } catch (IOException e) { + // TODO: add logging + } + } + }); + } + }); + } + + @Override + public void send(String message) { + exchange.send(message); + } + + @Override + public void addListener(ChromeRDPExchangeListener listener) { + listeners.add(listener); + } + + @Override + public void removeListener(ChromeRDPExchangeListener listener) { + listeners.remove(listener); + } + } +}