From cba983b4bf09b063f43d0dba6ebff3f50f07628a Mon Sep 17 00:00:00 2001 From: Pierre Jeanjean Date: Tue, 12 May 2020 14:45:50 +0200 Subject: [PATCH 1/4] Initial version of the MEP K3 Engine implementation Signed-off-by: Didier Vojtisek Several improvements in the engine (including several new commands) Signed-off-by: Pierre Jeanjean Integration in the CI Signed-off-by: Didier Vojtisek --- .gitignore | 3 +- .project | 2 +- .../.classpath | 27 + .../.project | 29 + .../org.eclipse.core.resources.prefs | 4 + .../.settings/org.eclipse.jdt.core.prefs | 9 + .../org.eclipse.xtend.core.Xtend.prefs | 7 + .../lib_not_correctly_deployed/README.md | 1 + ...pse.emf.transaction_1.9.1.201805140824.jar | Bin 0 -> 173186 bytes .../pom.xml | 189 ++++ .../AbstractHeadlessExecutionContext.java | 90 ++ .../headless/FakeBundleContext.java | 193 ++++ .../headless/HeadlessDebuggerAddon.java | 38 + .../headless/HeadlessExecutionPlatform.java | 61 ++ .../headless/HeadlessExecutionWorkspace.java | 45 + ...sJavaEngineSequentialRunConfiguration.java | 111 +++ .../HeadlessPlainK3ExecutionEngine.java | 869 ++++++++++++++++++ .../javaengine/headless/StackFrame.java | 24 + .../headless/StopSimulationException.java | 5 + .../commands/ClearBreakpointsCommand.java | 7 + .../headless/commands/ContinueCommand.java | 7 + .../headless/commands/DoStepCommand.java | 9 + .../headless/commands/GetVariableCommand.java | 9 + .../commands/ListVariablesCommand.java | 7 + .../headless/commands/OutputEvent.java | 9 + .../headless/commands/SetVariableCommand.java | 5 + .../headless/commands/StepKind.java | 7 + .../headless/commands/StopCommand.java | 7 + .../headless/commands/StopCondition.java | 14 + .../headless/commands/StopEvent.java | 9 + .../headless/commands/StopReason.java | 8 + .../commands/ToggleBreakpointCommand.java | 9 + .../headless/mep/K3GemocMEPServerImpl.java | 268 ++++++ .../javaengine/headless/AppTest.java | 38 + java_engine/pomfirst/pom.xml | 74 ++ pomfirst/pom.xml | 108 +++ 36 files changed, 2300 insertions(+), 2 deletions(-) create mode 100644 java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/.classpath create mode 100644 java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/.project create mode 100644 java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/.settings/org.eclipse.core.resources.prefs create mode 100644 java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/.settings/org.eclipse.jdt.core.prefs create mode 100644 java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/.settings/org.eclipse.xtend.core.Xtend.prefs create mode 100644 java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/lib_not_correctly_deployed/README.md create mode 100644 java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/lib_not_correctly_deployed/org.eclipse.emf.transaction_1.9.1.201805140824.jar create mode 100644 java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/pom.xml create mode 100644 java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/AbstractHeadlessExecutionContext.java create mode 100644 java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/FakeBundleContext.java create mode 100644 java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/HeadlessDebuggerAddon.java create mode 100644 java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/HeadlessExecutionPlatform.java create mode 100644 java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/HeadlessExecutionWorkspace.java create mode 100644 java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/HeadlessJavaEngineSequentialRunConfiguration.java create mode 100644 java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/HeadlessPlainK3ExecutionEngine.java create mode 100644 java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/StackFrame.java create mode 100644 java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/StopSimulationException.java create mode 100644 java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/commands/ClearBreakpointsCommand.java create mode 100644 java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/commands/ContinueCommand.java create mode 100644 java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/commands/DoStepCommand.java create mode 100644 java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/commands/GetVariableCommand.java create mode 100644 java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/commands/ListVariablesCommand.java create mode 100644 java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/commands/OutputEvent.java create mode 100644 java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/commands/SetVariableCommand.java create mode 100644 java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/commands/StepKind.java create mode 100644 java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/commands/StopCommand.java create mode 100644 java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/commands/StopCondition.java create mode 100644 java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/commands/StopEvent.java create mode 100644 java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/commands/StopReason.java create mode 100644 java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/commands/ToggleBreakpointCommand.java create mode 100644 java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/mep/K3GemocMEPServerImpl.java create mode 100644 java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/test/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/AppTest.java create mode 100644 java_engine/pomfirst/pom.xml create mode 100644 pomfirst/pom.xml diff --git a/.gitignore b/.gitignore index aeca2a8..3d736e3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ bin/ -**/xtend-gen/ \ No newline at end of file +**/xtend-gen/ +**/target/ \ No newline at end of file diff --git a/.project b/.project index c7d5d0a..9390447 100644 --- a/.project +++ b/.project @@ -1,6 +1,6 @@ - org.eclipse.gemoc.execution.sequential.java.root + gemoc-studio-execution-java diff --git a/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/.classpath b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/.classpath new file mode 100644 index 0000000..5e8a55f --- /dev/null +++ b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/.classpath @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/.project b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/.project new file mode 100644 index 0000000..40d382a --- /dev/null +++ b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/.project @@ -0,0 +1,29 @@ + + + org.eclipse.gemoc.execution.sequential.javaengine.headless + + + + + + org.eclipse.xtext.ui.shared.xtextBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.xtext.ui.shared.xtextNature + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + + diff --git a/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/.settings/org.eclipse.core.resources.prefs b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000..f9fe345 --- /dev/null +++ b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,4 @@ +eclipse.preferences.version=1 +encoding//src/main/java=UTF-8 +encoding//src/test/java=UTF-8 +encoding/=UTF-8 diff --git a/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/.settings/org.eclipse.jdt.core.prefs b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..4e4a3ad --- /dev/null +++ b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,9 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.release=disabled +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/.settings/org.eclipse.xtend.core.Xtend.prefs b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/.settings/org.eclipse.xtend.core.Xtend.prefs new file mode 100644 index 0000000..9682a4c --- /dev/null +++ b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/.settings/org.eclipse.xtend.core.Xtend.prefs @@ -0,0 +1,7 @@ +//outlet.DEFAULT_OUTPUT.sourceFolder.src/main/java.directory=xtend-gen +//outlet.DEFAULT_OUTPUT.sourceFolder.src/test/java.directory=src/test/generated-sources/xtend +BuilderConfiguration.is_project_specific=true +eclipse.preferences.version=1 +outlet.DEFAULT_OUTPUT.hideLocalSyntheticVariables=true +outlet.DEFAULT_OUTPUT.installDslAsPrimarySource=false +outlet.DEFAULT_OUTPUT.userOutputPerSourceFolder=true diff --git a/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/lib_not_correctly_deployed/README.md b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/lib_not_correctly_deployed/README.md new file mode 100644 index 0000000..b23224f --- /dev/null +++ b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/lib_not_correctly_deployed/README.md @@ -0,0 +1 @@ +these libs are currently not available in maven central we use a local version waiting for a better solution \ No newline at end of file diff --git a/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/lib_not_correctly_deployed/org.eclipse.emf.transaction_1.9.1.201805140824.jar b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/lib_not_correctly_deployed/org.eclipse.emf.transaction_1.9.1.201805140824.jar new file mode 100644 index 0000000000000000000000000000000000000000..99968c2ede4e6f547370c85d0e6a84729f81958a GIT binary patch literal 173186 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 V&<=}Aj$49%*2CAF!2iK + 4.0.0 + org.eclipse.gemoc.execution.sequential.javaengine + org.eclipse.gemoc.execution.sequential.javaengine.headless + + + org.eclipse.gemoc.execution.sequential.javaengine + org.eclipse.gemoc.execution.sequential.javaengine.pomfirst + 1.0.0-SNAPSHOT + + + + UTF-8 + 1.8 + 1.8 + 2.14.0 + + + + + junit + junit + 3.8.1 + test + + + org.eclipse.emf + org.eclipse.emf.transaction + 1.9.1.201805140824 + system + ${basedir}/lib_not_correctly_deployed/org.eclipse.emf.transaction_1.9.1.201805140824.jar + + + + org.eclipse.xtext + org.eclipse.xtext + ${xtend.version} + + + org.eclipse.xtext + org.eclipse.xtext.ide + ${xtend.version} + + + org.eclipse.emf + org.eclipse.emf.mwe.utils + 1.5.1 + + + + org.eclipse.gemoc.executionframework + org.eclipse.gemoc.executionframework.mep + ${project.version} + + + + + org.eclipse.gemoc.execution.sequential.java + org.eclipse.gemoc.execution.sequential.javaengine + 4.0.0-SNAPSHOT + + + fr.inria.diverse.k3.al + fr.inria.diverse.k3.al.annotationprocessor + 3.2.3-SNAPSHOT + + + org.eclipse.gemoc.trace.commons + org.eclipse.gemoc.trace.commons.model + 3.0.1-SNAPSHOT + + + org.eclipse.gemoc.trace.commons + org.eclipse.gemoc.trace.commons + 3.0.1-SNAPSHOT + + + org.eclipse.gemoc.modeldebugging.executionframework + org.eclipse.gemoc.executionframework.debugger + 4.0.0-SNAPSHOT + + + org.eclipse.gemoc.modeldebugging.executionframework + org.eclipse.gemoc.executionframework.engine + 4.0.0-SNAPSHOT + + + + + + + org.eclipse.emf + org.eclipse.emf.edit + 2.16.0 + + + + org.eclipse.gemoc.commons + org.eclipse.gemoc.commons.eclipse + 3.0.0-SNAPSHOT + + + org.eclipse.gemoc.commons + org.eclipse.gemoc.commons.utils + 1.0.0-SNAPSHOT + + + org.eclipse.gemoc.commons + org.eclipse.gemoc.commons.eclipse.pde + 3.0.0-SNAPSHOT + + + + org.eclipse.gemoc.commons + org.eclipse.gemoc.commons.eclipse.messagingsystem.api + 3.0.0-SNAPSHOT + + + org.eclipse.gemoc.modeldebugging.framework.commons + org.eclipse.gemoc.xdsmlframework.api + 4.0.0-SNAPSHOT + + + org.eclipse.gemoc.modeldebugging.framework.commons + org.eclipse.gemoc.xdsmlframework.commons + 4.0.0-SNAPSHOT + + + org.eclipse.gemoc.trace.commons + org.eclipse.gemoc.trace.gemoc.api + 3.0.1-SNAPSHOT + + + DSLDebugger + org.eclipse.gemoc.dsl.debug.ide + 3.0.1-SNAPSHOT + + + DSLDebugger + org.eclipse.gemoc.dsl.debug + 3.0.1-SNAPSHOT + + + DSLDebugger + org.eclipse.gemoc.dsl.debug.edit + 3.0.1-SNAPSHOT + + + + org.eclipse.platform + org.eclipse.debug.core + 3.12.0 + + + + org.slf4j + slf4j-api + 1.7.25 + + + + + nexus-eclipse-gemoc + Nexus Eclipse GEMOC + + true + + + true + + https://repo.eclipse.org/content/groups/gemoc/ + + + >maven.inria.fr + Maven Inria + + true + + + true + + http://maven.inria.fr/artifactory/public/ + + + diff --git a/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/AbstractHeadlessExecutionContext.java b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/AbstractHeadlessExecutionContext.java new file mode 100644 index 0000000..1a59037 --- /dev/null +++ b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/AbstractHeadlessExecutionContext.java @@ -0,0 +1,90 @@ +package org.eclipse.gemoc.execution.sequential.javaengine.headless; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.gemoc.executionframework.engine.commons.DslHelper; +import org.eclipse.gemoc.executionframework.engine.commons.EngineContextException; +import org.eclipse.gemoc.executionframework.engine.core.ExecutionWorkspace; +import org.eclipse.gemoc.trace.commons.model.trace.MSEModel; +import org.eclipse.gemoc.xdsmlframework.api.core.ExecutionMode; +import org.eclipse.gemoc.xdsmlframework.api.core.IExecutionContext; +import org.eclipse.gemoc.xdsmlframework.api.core.IExecutionPlatform; +import org.eclipse.gemoc.xdsmlframework.api.core.IExecutionWorkspace; +import org.eclipse.gemoc.xdsmlframework.api.core.IRunConfiguration; +import org.eclipse.gemoc.xdsmlframework.api.extensions.languages.LanguageDefinitionExtension; +import org.osgi.framework.Bundle; + +public abstract class AbstractHeadlessExecutionContext implements IExecutionContext { + + protected R _runConfiguration; + + protected HeadlessExecutionPlatform _executionPlatform; + + protected L _languageDefinition; + + protected Resource _resourceModel; + + protected ExecutionMode _executionMode; + + protected Bundle _dslBundle; + + protected IExecutionWorkspace _executionWorkspace; + + + public AbstractHeadlessExecutionContext(R runConfiguration, ExecutionMode executionMode, L languageDefinitionExtension, IExecutionWorkspace executionWorkspace, HeadlessExecutionPlatform executionPlatform) throws EngineContextException { + _runConfiguration = runConfiguration; + _executionMode = executionMode; + _executionWorkspace = executionWorkspace; + _languageDefinition = languageDefinitionExtension; + //_dslBundle = DslHelper.getDslBundle(_runConfiguration.getLanguageName()); + _executionPlatform = executionPlatform; + } + + @Override + public void dispose() { + _executionPlatform.dispose(); + } + + @Override + public IExecutionWorkspace getWorkspace() { + return _executionWorkspace; + } + + @Override + public Resource getResourceModel() { + return _resourceModel; + } + + @Override + public ExecutionMode getExecutionMode() { + return _executionMode; + } + + @Override + public MSEModel getMSEModel() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Bundle getDslBundle() { + return _dslBundle; + } + + @Override + public L getLanguageDefinitionExtension() { + return _languageDefinition; + } + + @Override + public HeadlessExecutionPlatform getExecutionPlatform() { + return _executionPlatform; + } + + @Override + public R getRunConfiguration() { + return _runConfiguration; + } + + +} diff --git a/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/FakeBundleContext.java b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/FakeBundleContext.java new file mode 100644 index 0000000..5f24623 --- /dev/null +++ b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/FakeBundleContext.java @@ -0,0 +1,193 @@ +package org.eclipse.gemoc.execution.sequential.javaengine.headless; + +import java.io.File; +import java.io.InputStream; +import java.util.Collection; +import java.util.Dictionary; + +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.BundleException; +import org.osgi.framework.BundleListener; +import org.osgi.framework.Filter; +import org.osgi.framework.FrameworkListener; +import org.osgi.framework.InvalidSyntaxException; +import org.osgi.framework.ServiceFactory; +import org.osgi.framework.ServiceListener; +import org.osgi.framework.ServiceObjects; +import org.osgi.framework.ServiceReference; +import org.osgi.framework.ServiceRegistration; + +public class FakeBundleContext implements BundleContext { + + @Override + public String getProperty(String key) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Bundle getBundle() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Bundle installBundle(String location, InputStream input) throws BundleException { + // TODO Auto-generated method stub + return null; + } + + @Override + public Bundle installBundle(String location) throws BundleException { + // TODO Auto-generated method stub + return null; + } + + @Override + public Bundle getBundle(long id) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Bundle[] getBundles() { + // TODO Auto-generated method stub + return null; + } + + @Override + public void addServiceListener(ServiceListener listener, String filter) throws InvalidSyntaxException { + // TODO Auto-generated method stub + + } + + @Override + public void addServiceListener(ServiceListener listener) { + // TODO Auto-generated method stub + + } + + @Override + public void removeServiceListener(ServiceListener listener) { + // TODO Auto-generated method stub + + } + + @Override + public void addBundleListener(BundleListener listener) { + // TODO Auto-generated method stub + + } + + @Override + public void removeBundleListener(BundleListener listener) { + // TODO Auto-generated method stub + + } + + @Override + public void addFrameworkListener(FrameworkListener listener) { + // TODO Auto-generated method stub + + } + + @Override + public void removeFrameworkListener(FrameworkListener listener) { + // TODO Auto-generated method stub + + } + + @Override + public ServiceRegistration registerService(String[] clazzes, Object service, Dictionary properties) { + // TODO Auto-generated method stub + return null; + } + + @Override + public ServiceRegistration registerService(String clazz, Object service, Dictionary properties) { + // TODO Auto-generated method stub + return null; + } + + @Override + public ServiceRegistration registerService(Class clazz, S service, Dictionary properties) { + // TODO Auto-generated method stub + return null; + } + + @Override + public ServiceRegistration registerService(Class clazz, ServiceFactory factory, + Dictionary properties) { + // TODO Auto-generated method stub + return null; + } + + @Override + public ServiceReference[] getServiceReferences(String clazz, String filter) throws InvalidSyntaxException { + // TODO Auto-generated method stub + return null; + } + + @Override + public ServiceReference[] getAllServiceReferences(String clazz, String filter) throws InvalidSyntaxException { + // TODO Auto-generated method stub + return null; + } + + @Override + public ServiceReference getServiceReference(String clazz) { + // TODO Auto-generated method stub + return null; + } + + @Override + public ServiceReference getServiceReference(Class clazz) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Collection> getServiceReferences(Class clazz, String filter) + throws InvalidSyntaxException { + // TODO Auto-generated method stub + return null; + } + + @Override + public S getService(ServiceReference reference) { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean ungetService(ServiceReference reference) { + // TODO Auto-generated method stub + return false; + } + + @Override + public ServiceObjects getServiceObjects(ServiceReference reference) { + // TODO Auto-generated method stub + return null; + } + + @Override + public File getDataFile(String filename) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Filter createFilter(String filter) throws InvalidSyntaxException { + // TODO Auto-generated method stub + return null; + } + + @Override + public Bundle getBundle(String location) { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/HeadlessDebuggerAddon.java b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/HeadlessDebuggerAddon.java new file mode 100644 index 0000000..1739b50 --- /dev/null +++ b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/HeadlessDebuggerAddon.java @@ -0,0 +1,38 @@ +package org.eclipse.gemoc.execution.sequential.javaengine.headless; + +import org.eclipse.gemoc.trace.commons.model.trace.Step; +import org.eclipse.gemoc.xdsmlframework.api.core.IExecutionEngine; +import org.eclipse.gemoc.xdsmlframework.api.engine_addon.IEngineAddon; + +public class HeadlessDebuggerAddon implements IEngineAddon { + + @Override + public void engineStopped(IExecutionEngine engine) { + // TODO Auto-generated method stub + IEngineAddon.super.engineStopped(engine); + } + + @Override + public void aboutToExecuteStep(IExecutionEngine engine, Step stepToExecute) { + // TODO Auto-generated method stub + IEngineAddon.super.aboutToExecuteStep(engine, stepToExecute); + + /* + val ToPushPop stackModification = new ToPushPop(step, true); + toPushPop.add(stackModification); + val boolean shallcontinue = control(threadName, step); + if (!shallcontinue) { + throw new EngineStoppedException("Debug thread has stopped."); + } + */ + } + + @Override + public void stepExecuted(IExecutionEngine engine, Step stepExecuted) { + // TODO Auto-generated method stub + IEngineAddon.super.stepExecuted(engine, stepExecuted); + } + + + +} diff --git a/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/HeadlessExecutionPlatform.java b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/HeadlessExecutionPlatform.java new file mode 100644 index 0000000..dbc7c01 --- /dev/null +++ b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/HeadlessExecutionPlatform.java @@ -0,0 +1,61 @@ +package org.eclipse.gemoc.execution.sequential.javaengine.headless; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import org.eclipse.gemoc.xdsmlframework.api.core.IExecutionPlatform; +import org.eclipse.gemoc.xdsmlframework.api.core.IModelLoader; +import org.eclipse.gemoc.xdsmlframework.api.engine_addon.EngineAddonSortingRule.EngineEvent; +import org.eclipse.gemoc.xdsmlframework.api.engine_addon.IEngineAddon; + +public class HeadlessExecutionPlatform implements IExecutionPlatform { + + + protected Collection _addons = new ArrayList(); + + @Override + public void dispose() { + // TODO Auto-generated method stub + + } + + @Override + public IModelLoader getModelLoader() { + // TODO Auto-generated method stub + return null; + } + + private Object _addonLock = new Object(); + + @Override + public void addEngineAddon(IEngineAddon addon) { + synchronized (_addonLock) { + _addons.add(addon); + } + } + + @Override + public void removeEngineAddon(IEngineAddon addon) { + synchronized (_addonLock) { + _addons.remove(addon); + } + } + + + @Override + public Iterable getEngineAddons() { + synchronized (_addonLock) { + return Collections.unmodifiableCollection(new ArrayList(_addons)); + } + } + + @Override + public List getSortedEngineAddons(EngineEvent engineEvent) { + synchronized (_addonLock) { + return Collections.unmodifiableList(new ArrayList(_addons)); + } + } + +} diff --git a/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/HeadlessExecutionWorkspace.java b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/HeadlessExecutionWorkspace.java new file mode 100644 index 0000000..03ac424 --- /dev/null +++ b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/HeadlessExecutionWorkspace.java @@ -0,0 +1,45 @@ +package org.eclipse.gemoc.execution.sequential.javaengine.headless; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.gemoc.xdsmlframework.api.core.IExecutionWorkspace; + +public class HeadlessExecutionWorkspace implements IExecutionWorkspace { + + @Override + public IPath getProjectPath() { + // TODO Auto-generated method stub + return null; + } + + @Override + public IPath getModelPath() { + // TODO Auto-generated method stub + return null; + } + + @Override + public IPath getMoCPath() { + // TODO Auto-generated method stub + return null; + } + + @Override + public IPath getMSEModelPath() { + // TODO Auto-generated method stub + return null; + } + + @Override + public IPath getExecutionPath() { + // TODO Auto-generated method stub + return null; + } + + @Override + public void copyFileToExecutionFolder(IPath filePath) throws CoreException { + // TODO Auto-generated method stub + + } + +} diff --git a/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/HeadlessJavaEngineSequentialRunConfiguration.java b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/HeadlessJavaEngineSequentialRunConfiguration.java new file mode 100644 index 0000000..bbd39c1 --- /dev/null +++ b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/HeadlessJavaEngineSequentialRunConfiguration.java @@ -0,0 +1,111 @@ +package org.eclipse.gemoc.execution.sequential.javaengine.headless; + +import java.util.Collection; + +import org.eclipse.emf.common.util.URI; +import org.eclipse.gemoc.executionframework.engine.commons.sequential.ISequentialRunConfiguration; +import org.eclipse.gemoc.xdsmlframework.api.extensions.engine_addon.EngineAddonSpecificationExtension; + +public class HeadlessJavaEngineSequentialRunConfiguration implements ISequentialRunConfiguration { + + URI modelURI; + String languageName; + String modelEntryPoint; + String methodEntryPoint; + String initializationMethod; + String initializationMethodArgs; + public HeadlessJavaEngineSequentialRunConfiguration(URI modelURI, String languageName, String modelEntryPoint, + String methodEntryPoint, String initializationMethod, String initializationMethodArgs) { + this.modelURI = modelURI; + this.languageName = languageName; + this.modelEntryPoint = modelEntryPoint; + this.methodEntryPoint = methodEntryPoint; + this.initializationMethod = initializationMethod; + this.initializationMethodArgs = initializationMethodArgs; + } + + @Override + public int getAnimationDelay() { + return 0; + } + + @Override + public URI getAnimatorURI() { + return null; + } + + @Override + public boolean getBreakStart() { + return false; + } + + @Override + public String getDebugModelID() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Collection getEngineAddonExtensions() { + return null; + } + + @Override + public URI getExecutedModelAsMelangeURI() { + // TODO Auto-generated method stub + return null; + } + + @Override + public URI getExecutedModelURI() { + return modelURI; + } + + @Override + public String getLanguageName() { + return this.languageName; + } + + @Override + public String getMelangeQuery() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getExecutionEntryPoint() { + return this.methodEntryPoint; + } + + @Override + public String getModelEntryPoint() { + return this.modelEntryPoint; + } + + @Override + public String getModelInitializationMethod() { + return this.initializationMethod; + } + + @Override + public String getModelInitializationArguments() { + return this.initializationMethodArgs; + } + + + public String getAttribute(String attributeName, String defaultValue) { + // there is no addon in this mode, so return the default value + return defaultValue; + } + + public Integer getAttribute(String attributeName, Integer defaultValue) { + // there is no addon in this mode, so return the default value + return defaultValue; + } + + public Boolean getAttribute(String attributeName, Boolean defaultValue) { + // there is no addon in this mode, so return the default value + return defaultValue; + } + +} diff --git a/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/HeadlessPlainK3ExecutionEngine.java b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/HeadlessPlainK3ExecutionEngine.java new file mode 100644 index 0000000..570e49a --- /dev/null +++ b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/HeadlessPlainK3ExecutionEngine.java @@ -0,0 +1,869 @@ +package org.eclipse.gemoc.execution.sequential.javaengine.headless; + + + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.PrintStream; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.ServerSocket; +import java.net.Socket; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.ResourceBundle; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.Semaphore; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IExtensionRegistry; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.RegistryFactory; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.spi.IRegistryProvider; +import org.eclipse.core.runtime.spi.RegistryStrategy; +import org.eclipse.emf.common.util.BasicEList; +import org.eclipse.emf.common.util.EList; +import org.eclipse.emf.common.util.TreeIterator; +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.resource.ResourceSet; +import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; +import org.eclipse.emf.transaction.TransactionalEditingDomain; +import org.eclipse.emf.transaction.impl.InternalTransactionalEditingDomain; +import org.eclipse.gemoc.commons.utils.ModelAwarePrintStream; +import org.eclipse.gemoc.execution.sequential.javaengine.headless.commands.ClearBreakpointsCommand; +import org.eclipse.gemoc.execution.sequential.javaengine.headless.commands.ContinueCommand; +import org.eclipse.gemoc.execution.sequential.javaengine.headless.commands.DoStepCommand; +import org.eclipse.gemoc.execution.sequential.javaengine.headless.commands.GetVariableCommand; +import org.eclipse.gemoc.execution.sequential.javaengine.headless.commands.ListVariablesCommand; +import org.eclipse.gemoc.execution.sequential.javaengine.headless.commands.OutputEvent; +import org.eclipse.gemoc.execution.sequential.javaengine.headless.commands.StepKind; +import org.eclipse.gemoc.execution.sequential.javaengine.headless.commands.StopCommand; +import org.eclipse.gemoc.execution.sequential.javaengine.headless.commands.StopCondition; +import org.eclipse.gemoc.execution.sequential.javaengine.headless.commands.StopEvent; +import org.eclipse.gemoc.execution.sequential.javaengine.headless.commands.StopReason; +import org.eclipse.gemoc.execution.sequential.javaengine.headless.commands.ToggleBreakpointCommand; +import org.eclipse.gemoc.executionframework.debugger.DefaultDynamicPartAccessor; +import org.eclipse.gemoc.executionframework.debugger.IDynamicPartAccessor; +import org.eclipse.gemoc.executionframework.debugger.MutableField; +import org.eclipse.gemoc.executionframework.engine.commons.GenericModelExecutionContext; +import org.eclipse.gemoc.executionframework.engine.commons.K3DslHelper; +import org.eclipse.gemoc.executionframework.engine.commons.sequential.ISequentialRunConfiguration; +import org.eclipse.gemoc.executionframework.engine.core.AbstractCommandBasedSequentialExecutionEngine; +import org.eclipse.gemoc.executionframework.engine.core.EngineStoppedException; +import org.eclipse.gemoc.xdsmlframework.api.extensions.languages.LanguageDefinitionExtension; +import org.eclipse.jdt.core.IPackageFragmentRoot; +import org.eclipse.jdt.core.IType; +import org.eclipse.jdt.core.search.IJavaSearchConstants; +import org.eclipse.jdt.core.search.IJavaSearchScope; +import org.eclipse.jdt.core.search.SearchEngine; +import org.eclipse.jdt.core.search.SearchMatch; +import org.eclipse.jdt.core.search.SearchParticipant; +import org.eclipse.jdt.core.search.SearchPattern; +import org.eclipse.jdt.core.search.SearchRequestor; +import org.eclipse.xtext.nodemodel.ICompositeNode; +import org.eclipse.xtext.nodemodel.util.NodeModelUtils; +import org.osgi.framework.Bundle; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.util.concurrent.AtomicDouble; + +import fr.inria.diverse.k3.al.annotationprocessor.stepmanager.IStepManager; +import fr.inria.diverse.k3.al.annotationprocessor.stepmanager.StepCommand; +import fr.inria.diverse.k3.al.annotationprocessor.stepmanager.StepManagerRegistry; + + +/** + * Implementation of the GEMOC Execution engine dedicated to run Kermeta 3 + * operational semantic + * + * @author Didier Vojtisek + * + */ +public class HeadlessPlainK3ExecutionEngine< L extends LanguageDefinitionExtension> extends AbstractCommandBasedSequentialExecutionEngine, ISequentialRunConfiguration> implements IStepManager { +//public class HeadlessPlainK3ExecutionEngine< L extends LanguageDefinitionExtension> extends AbstractSequentialExecutionEngine, ISequentialRunConfiguration> implements IStepManager { + + + private static final Logger LOGGER = LoggerFactory.getLogger("HeadlessPlainK3ExecutionEngine"); + + private Method initializeMethod; + private List initializeMethodParameters; + private Method entryPointMethod; + private List entryPointMethodParameters; + private Class entryPointClass; + + private EObject root; + private IDynamicPartAccessor partAccessor; + private Map variables; + private Map breakpoints; + + private ByteArrayOutputStream outputStream; + + @Override + public String engineKindName() { + return "GEMOC Kermeta HEADLESS Sequential Engine"; + } + + /** + * Constructs a PlainK3 execution engine using an entry point (~ a main + * operation) The entrypoint will register itself as a StepManager into the K3 + * step manager registry, and unregister itself at the end. As a StepManager, + * the PlainK3ExecutionEngine will receive callbacks through its "executeStep" + * operation. + */ + @Override + protected void prepareEntryPoint(AbstractHeadlessExecutionContext executionContext) { + outputStream = new ByteArrayOutputStream() { + @Override + public synchronized void write(int b) { + write(new byte[] {(byte)b}, 0, 1); + } + + @Override + public synchronized void write(byte[] b, int off, int len) { + OutputEvent outputEvent = new OutputEvent(); + outputEvent.output = new String(Arrays.copyOfRange(b, off, len)); + try { + cout.writeObject(outputEvent); + } catch (IOException e) { + e.printStackTrace(); + } + } + }; + + /* + * Get info from the RunConfiguration + */ + String entryPoint = executionContext.getRunConfiguration().getExecutionEntryPoint(); + String mainModelElementURI = executionContext.getRunConfiguration().getModelEntryPoint(); + + /* + * Find the entry point in the workspace + */ + final String prefix = "public static void "; + int startName = prefix.length(); + int endName = entryPoint.lastIndexOf("("); + String methodFullName = entryPoint.substring(startName, endName); + + String aspectClassName = methodFullName.substring(0, methodFullName.lastIndexOf(".")); + String methodName = methodFullName.substring(methodFullName.lastIndexOf(".") + 1); + + + // try to fake osgi start + fakeOSGIStart(); + + + /* Bundle bundle = findBundle(executionContext, aspectClassName); + if (bundle == null) + throw new RuntimeException("Could not find bundle for language \"" + + executionContext.getRunConfiguration().getLanguageName() + "\""); +*/ + // search the class + try { + entryPointClass = Thread.currentThread().getContextClassLoader().loadClass(aspectClassName); + } catch (ClassNotFoundException e) { + //String bundleName = bundle.getHeaders().get("Bundle-Name"); + e.printStackTrace(); + throw new RuntimeException( + "Could not find class " + executionContext.getRunConfiguration().getExecutionEntryPoint() + ); + } + + // search the method + this.entryPointMethodParameters = new ArrayList<>(); + root = executionContext.getResourceModel().getEObject(mainModelElementURI); + entryPointMethodParameters.add(root); + + partAccessor = new DefaultDynamicPartAccessor(); + variables = new HashMap<>(); + breakpoints = new HashMap<>(); + + try { + this.entryPointMethod = K3DslHelper.findMethod(entryPointClass, root, methodName); + } catch (Exception e) { + String msg = "There is no \"" + methodName + "\" method in " + entryPointClass.getName() + + " with first parameter able to handle " + entryPointMethodParameters.get(0).toString(); + msg += " from " + ((EObject) entryPointMethodParameters.get(0)).eClass().getEPackage().getNsURI(); + LOGGER.error(msg, e); + throw new RuntimeException("Could not find method main with correct parameters."); + } + } + + protected void prepareInitializeModel( + AbstractHeadlessExecutionContext executionContext) { + //protected void prepareInitializeModel(GenericModelExecutionContext executionContext) { + + // try to get the initializeModelRunnable + String modelInitializationMethodQName = executionContext.getRunConfiguration().getModelInitializationMethod(); + if (!modelInitializationMethodQName.isEmpty()) { + // the current system supposes that the modelInitialization method + // is in the same class as the entry point + String modelInitializationMethodName = modelInitializationMethodQName + .substring(modelInitializationMethodQName.lastIndexOf(".") + 1); + boolean isListArgs = false; + boolean isEListArgs = false; + boolean isFound = false; + try { + Class[] modelInitializationParamType = new Class[] { + entryPointMethodParameters.get(0).getClass().getInterfaces()[0], String[].class }; + initializeMethod = entryPointClass.getMethod(modelInitializationMethodName, + modelInitializationParamType); + isListArgs = false; // this is a java array + isFound = true; + } catch (Exception e) { + + } + if (!isFound) { + try { + Class[] modelInitializationParamType = new Class[] { + entryPointMethodParameters.get(0).getClass().getInterfaces()[0], List.class }; + initializeMethod = entryPointClass.getMethod(modelInitializationMethodName, + modelInitializationParamType); + isListArgs = true; // this is a List + isFound = true; + } catch (Exception e) { + + } + } + if (!isFound) { + try { + Class[] modelInitializationParamType = new Class[] { + entryPointMethodParameters.get(0).getClass().getInterfaces()[0], EList.class }; + this.initializeMethod = entryPointClass.getMethod(modelInitializationMethodName, + modelInitializationParamType); + isEListArgs = true; // this is an EList + } catch (Exception e) { + String msg = "There is no \"" + modelInitializationMethodName + "\" method in " + + entryPointClass.getName() + " with first parameter able to handle " + + entryPointMethodParameters.get(0).toString(); + msg += " and String[] or List or EList args as second parameter"; + msg += " from " + ((EObject) entryPointMethodParameters.get(0)).eClass().getEPackage().getNsURI(); + LOGGER.error(msg, e); + // ((EObject)parameters.get(0)).eClass().getEPackage().getNsURI() + throw new RuntimeException( + "Could not find method " + modelInitializationMethodName + " with correct parameters."); + } + } + final boolean finalIsListArgs = isListArgs; + final boolean finalIsEListArgs = isEListArgs; + this.initializeMethodParameters = new ArrayList<>(); + initializeMethodParameters.add(entryPointMethodParameters.get(0)); + if (finalIsListArgs) { + final ArrayList modelInitializationListParameters = new ArrayList<>(); + for (String s : executionContext.getRunConfiguration().getModelInitializationArguments() + .split("\\r?\\n")) { + modelInitializationListParameters.add(s); + } + initializeMethodParameters.add(modelInitializationListParameters); + } else if (finalIsEListArgs) { + final EList modelInitializationListParameters = new BasicEList<>(); + for (String s : executionContext.getRunConfiguration().getModelInitializationArguments() + .split("\\r?\\n")) { + modelInitializationListParameters.add(s); + } + initializeMethodParameters.add(modelInitializationListParameters); + } else { + initializeMethodParameters + .add(executionContext.getRunConfiguration().getModelInitializationArguments().split("\\r?\\n")); + } + } + } + + + public void fakeOSGIStart() { + + + + // If there isn't already a registry... + // + IExtensionRegistry registry = RegistryFactory.getRegistry(); + if (registry == null) + { + // Create a new registry. + // + final IExtensionRegistry newRegistry = + RegistryFactory.createRegistry + (new RegistryStrategy(null, null) + { + @Override + public void log(IStatus status) + { + switch (status.getSeverity()) { + case Status.ERROR: + LOGGER.error(status.toString()); + break; + case Status.WARNING: + LOGGER.warn(status.toString()); + break; + + default: + LOGGER.info(status.toString()); + break; + + } + } + + @Override + public String translate(String key, ResourceBundle resources) + { + try + { + // The org.eclipse.core.resources bundle has keys that aren't translated, so avoid exception propagation. + // + return super.translate(key, resources); + } + catch (Throwable throwable) + { + return key; + } + } + }, + null, + null); + + // Make the new registry the default. + // + try + { + RegistryFactory.setDefaultRegistryProvider + (new IRegistryProvider() + { + public IExtensionRegistry getRegistry() + { + return newRegistry; + } + }); + } + catch (CoreException e) + { + LOGGER.error(e.getMessage(), e); + } + + registry = newRegistry; + } + + + org.eclipse.gemoc.executionframework.engine.Activator activator = new org.eclipse.gemoc.executionframework.engine.Activator(); + try { + activator.start(new FakeBundleContext()); + } catch (Exception e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } + } + + /** + * Invoke the initialize method + */ + private void callInitializeModel() { + try { + initializeMethod.invoke(null, initializeMethodParameters.toArray()); + } catch (EngineStoppedException stopExeception) { + // not really an error, simply forward the stop exception + throw stopExeception; + } catch (java.lang.reflect.InvocationTargetException ite) { + // not really an error, simply forward the stop exception + if (ite.getCause() instanceof EngineStoppedException) { + throw (EngineStoppedException) ite.getCause(); + } else { + throw new RuntimeException(ite); + } + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + protected void initializeModel() { + if (initializeMethod != null) { + StepManagerRegistry.getInstance().registerManager(HeadlessPlainK3ExecutionEngine.this); + try { + final boolean isStepMethod = initializeMethod + .isAnnotationPresent(fr.inria.diverse.k3.al.annotationprocessor.Step.class); + startDoStepSemaphore = new Semaphore(0); + simulationEnded = false; + stopReceived = false; + continueSimulation = false; + stepKind = StepKind.STEP_IN; + stepCaller = null; + if (!isStepMethod) { + finishDoStepSemaphore = new Semaphore(-1); + fr.inria.diverse.k3.al.annotationprocessor.stepmanager.StepCommand command = new fr.inria.diverse.k3.al.annotationprocessor.stepmanager.StepCommand() { + @Override + public void execute() { + callInitializeModel(); + } + }; + fr.inria.diverse.k3.al.annotationprocessor.stepmanager.IStepManager stepManager = HeadlessPlainK3ExecutionEngine.this; + stepManager.executeStep(entryPointMethodParameters.get(0), command, entryPointClass.getName(), + initializeMethod.getName()); + } else { + // FinishDoStep needs to be at -1 before the first step + finishDoStepSemaphore = new Semaphore(-2); + increment(startDoStepSemaphore); + callInitializeModel(); + } + } finally { + StepManagerRegistry.getInstance().unregisterManager(HeadlessPlainK3ExecutionEngine.this); + } + } + } + + @Override + protected void executeEntryPoint() { + StepManagerRegistry.getInstance().registerManager(HeadlessPlainK3ExecutionEngine.this); + try { + // since aspect's methods are static, first arg is null + //entryPointMethod.invoke(null, entryPointMethodParameters.get(0)); + simulate(); + } catch (EngineStoppedException stopExeception) { + // not really an error, simply forward the stop exception + throw stopExeception; + } catch (java.lang.reflect.InvocationTargetException ite) { + // not really an error, simply forward the stop exception + if (ite.getCause() instanceof EngineStoppedException) { + throw (EngineStoppedException) ite.getCause(); + } else { + throw new RuntimeException(ite); + } + } catch (Exception e) { + throw new RuntimeException(e); + } finally { + StepManagerRegistry.getInstance().unregisterManager(HeadlessPlainK3ExecutionEngine.this); + if (serverSocket != null) { + try { + serverSocket.close(); + } catch (IOException e) { + LOGGER.error(e.getMessage(), e); + } + } + } + } + + volatile StepKind stepKind; + volatile EObject stepCaller; + + @Override + /* + * This is the operation called from K3 code. We use this callback to pass the + * command to the generic executeOperation operation. (non-Javadoc) + * + * @see fr.inria.diverse.k3.al.annotationprocessor.stepmanager.IStepManager# + * executeStep(java.lang.Object, + * fr.inria.diverse.k3.al.annotationprocessor.stepmanager.StepCommand, + * java.lang.String) + */ + public void executeStep(Object caller, final StepCommand command, String className, String methodName) { + if (continueSimulation) { + EObject eObj = (EObject) caller; + ICompositeNode node = NodeModelUtils.getNode(eObj); + if (node != null && breakpoints.containsKey(node.getStartLine())) { + continueSimulation = false; + updateVariables(); + sendStopEvent(StopReason.REACHED_BREAKPOINT); + increment(finishDoStepSemaphore); + decrement(startDoStepSemaphore); + stepCaller = eObj; + } + } else { // Execution is paused + EObject eObj = (EObject) caller; + EObject debugObj = eObj; + String debugString = ""; + while (debugObj != null && baseStream != null) { + baseStream.println(debugString + debugObj.toString()); + debugString += " "; + debugObj = debugObj.eContainer(); + } + switch(stepKind) { + case STEP_IN: + // Break at each step + increment(finishDoStepSemaphore); // give control back to the caller. + //wait for stuff to be done in the server before to continue + decrement(startDoStepSemaphore); //waiting for the caller to do something + stepCaller = eObj; + break; + + case NEXT: + // Only break if not child + boolean foundNext = false; + EObject containerNext = eObj.eContainer(); + while (containerNext != null && !foundNext) { + if (containerNext == stepCaller) { + foundNext = true; + } + containerNext = containerNext.eContainer(); + } + if (!foundNext) { + increment(finishDoStepSemaphore); // give control back to the caller. + //wait for stuff to be done in the server before to continue + decrement(startDoStepSemaphore); //waiting for the caller to do something + stepCaller = eObj; + } + break; + + case STEP_OUT: + // Only break if not child nor sibling + boolean foundStepOut = false; + EObject containerStepOut = eObj.eContainer(); + if (containerStepOut != stepCaller.eContainer()) { + while (containerStepOut != null && !foundStepOut) { + if (containerStepOut == stepCaller) { + foundStepOut = true; + } + containerStepOut = containerStepOut.eContainer(); + } + } + if (!foundStepOut) { + increment(finishDoStepSemaphore); // give control back to the caller. + //wait for stuff to be done in the server before to continue + decrement(startDoStepSemaphore); //waiting for the caller to do something + stepCaller = eObj; + } + break; + } + } + + if (stopReceived) { + throw new StopSimulationException(); + } + + command.execute(); + +// executeOperation(caller, className, methodName, new Runnable() { +// @Override +// public void run() { +// command.execute(); +// } +// }); + } + + + @Override + /* + * This is the operation used to act as a StepManager in K3. We return true if + * we have the same editing domain as the object. (non-Javadoc) + * + * @see fr.inria.diverse.k3.al.annotationprocessor.stepmanager.IStepManager# + * canHandle (java.lang.Object) + */ + public boolean canHandle(Object caller) { + if (caller instanceof EObject) { + EObject eObj = (EObject) caller; + org.eclipse.emf.transaction.TransactionalEditingDomain editingDomain = getEditingDomain(eObj); + return editingDomain == this.editingDomain; + + } + return false; + } + + /** + * Return a bundle containing 'aspectClassName'. + * + * Return null if not found. + */ + private Bundle findBundle(final GenericModelExecutionContext executionContext, String aspectClassName) { + + // Look using JavaWorkspaceScope as this is safer and will look in + // dependencies + IType mainIType = getITypeMainByWorkspaceScope(aspectClassName); + + Bundle bundle = null; + String bundleName = null; + if (mainIType != null) { + IPackageFragmentRoot packageFragmentRoot = (IPackageFragmentRoot) mainIType.getPackageFragment() + .getParent(); + + bundleName = packageFragmentRoot.getPath().removeLastSegments(1).lastSegment().toString(); + if (bundleName != null) { + + // We try to look into an already loaded bundle + bundle = Platform.getBundle(bundleName); + } + } else { + // the main isn't visible directly from the workspace, try another + // method + bundle = _executionContext.getDslBundle(); + } + + return bundle; + } + + /** + * search the bundle that contains the Main class. The search is done in the + * workspace scope (ie. if it is defined in the current workspace it will find + * it + * + * @return the name of the bundle containing the Main class or null if not found + */ + private IType getITypeMainByWorkspaceScope(String className) { + SearchPattern pattern = SearchPattern.createPattern(className, IJavaSearchConstants.CLASS, + IJavaSearchConstants.DECLARATIONS, SearchPattern.R_EXACT_MATCH); + IJavaSearchScope scope = SearchEngine.createWorkspaceScope(); + + final List binaryType = new ArrayList(); + + SearchRequestor requestor = new SearchRequestor() { + @Override + public void acceptSearchMatch(SearchMatch match) throws CoreException { + binaryType.add((IType) match.getElement()); + } + }; + SearchEngine engine = new SearchEngine(); + + try { + engine.search(pattern, new SearchParticipant[] { SearchEngine.getDefaultSearchParticipant() }, scope, + requestor, null); + } catch (CoreException e1) { + throw new RuntimeException("Error while searching the bundle: " + e1.getMessage()); + // return new Status(IStatus.ERROR, Activator.PLUGIN_ID, ); + } + + return binaryType.isEmpty() ? null : binaryType.get(0); + } + + private static TransactionalEditingDomain getEditingDomain(EObject o) { + return getEditingDomain(o.eResource().getResourceSet()); + } + + private static InternalTransactionalEditingDomain getEditingDomain(ResourceSet rs) { + TransactionalEditingDomain edomain = org.eclipse.emf.transaction.TransactionalEditingDomain.Factory.INSTANCE + .getEditingDomain(rs); + if (edomain instanceof InternalTransactionalEditingDomain) + return (InternalTransactionalEditingDomain) edomain; + else + return null; + } + + /** + * Load the model for the given URI + * + * @param modelURI + * to load + * @return the loaded resource + */ + public static Resource loadModel(URI modelURI) { + Resource resource = null; + ResourceSet resourceSet; + resourceSet = new ResourceSetImpl(); + resource = resourceSet.createResource(modelURI); + try { + resource.load(null); + } catch (IOException e) { + // chut + } + return resource; + } + + // + // Simulation Server + + + + // semaphore for locking doStep + Semaphore startDoStepSemaphore; + Semaphore finishDoStepSemaphore; + volatile boolean simulationEnded; + volatile boolean continueSimulation; + volatile boolean stopReceived; + + private void decrement(Semaphore sem) { + try { + sem.acquire(); + } catch (InterruptedException e) { + LOGGER.error(e.getMessage(), e); + } + } + + private void increment(Semaphore sem) { + sem.release(); + } + + AtomicDouble lastknownTime = new AtomicDouble(-1.0); + double timeBeforeDoStep = -1; + + private StopCondition lastStopcondition = null; + + public static final int GEMOC_PORT = 39635; + // socket for communicating with the simulation thread + ServerSocket serverSocket = null; + + ObjectOutputStream cout = null; + + protected void simulate() throws Exception { + //used to retrieve exceptions from the solverThread + BlockingQueue exceptionQueue = new ArrayBlockingQueue<>(1); + + updateVariables(); + + Thread solverThread = launchEntryPointInThread(exceptionQueue); + + solverThread.start(); + + serverSocket = new ServerSocket(GEMOC_PORT); + + Socket clientSocket = serverSocket.accept(); + + // OutputStream needs to be created before InputStream or the client will deadlock + cout = new ObjectOutputStream(clientSocket.getOutputStream()); + ObjectInputStream cin = new ObjectInputStream(clientSocket.getInputStream()); + + Object clientCommand; + do { + clientCommand = cin.readObject(); + System.out.println("Command received: "+clientCommand); + if (clientCommand instanceof DoStepCommand) { + timeBeforeDoStep = lastknownTime.doubleValue(); + System.out.println("DoStep starts @"+timeBeforeDoStep); + //currentPredicate = ((DoStepCommand) clientCommand).predicate; + //StopCondition stopCond = this.doStep(currentPredicate); + stepKind = ((DoStepCommand) clientCommand).stepKind; + StopCondition stopCond = this.doStep(); + //System.out.println("DoStep stops @"+stopCond.timeValue+" due to "+stopCond.stopReason); + System.out.println("DoStep stops due to "+stopCond.stopReason); + cout.writeObject(stopCond); + } else if (clientCommand instanceof ListVariablesCommand) { + cout.writeObject(new ArrayList(this.variables.keySet())); + } else if (clientCommand instanceof GetVariableCommand) { + String varQN = ((GetVariableCommand) clientCommand).variableQualifiedName; + Object varValue= this.variables.get(varQN); + cout.writeObject(varValue.toString()); + } else if (clientCommand instanceof StopCommand) { + stopReceived = true; + increment(startDoStepSemaphore); + decrement(finishDoStepSemaphore); + } else if (clientCommand instanceof ClearBreakpointsCommand) { + breakpoints.clear(); + } else if (clientCommand instanceof ToggleBreakpointCommand) { + int breakpointLine = ((ToggleBreakpointCommand) clientCommand).line; + if (breakpoints.containsKey(breakpointLine)) { + breakpoints.put(breakpointLine, !breakpoints.get(breakpointLine)); + } else { + breakpoints.put(breakpointLine, true); + } + } else if (clientCommand instanceof ContinueCommand) { + continueSimulation = true; + increment(startDoStepSemaphore); + decrement(finishDoStepSemaphore); + } + /* + if(clientCommand instanceof SetVariableCommand) { + String varQN = ((SetVariableCommand) clientCommand).variableQualifiedName; + Object newValue = ((SetVariableCommand) clientCommand).newValue; + Boolean res = this.setVariable(varQN, newValue); + cout.writeObject(res); + }*/ + System.out.println("wait for a new command."); + } while(!simulationEnded); + solverThread.join(); + if (stopReceived) { + cout.writeObject(Boolean.TRUE); + } + serverSocket.close(); + + if (exceptionQueue.isEmpty()) { + return; + } else { + throw exceptionQueue.remove(); + } + } + + PrintStream baseStream; + ModelAwarePrintStream printStream; + Thread simulationThread; + + public Thread launchEntryPointInThread(BlockingQueue exceptionQueue) { + baseStream = System.out; + printStream = new ModelAwarePrintStream(outputStream, baseStream); + + Thread simulationThread = new Thread( () -> + // since aspect's methods are static, first arg is null + { + + simulationEnded = false; + try { + this.entryPointMethod.invoke(null, entryPointMethodParameters.get(0)); + } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { + if (e.getCause() instanceof StopSimulationException) { + baseStream.println("Simulation stopped"); + } else { + exceptionQueue.offer(e); + } + } + if (continueSimulation) { + sendStopEvent(StopReason.REACHED_SIMULATION_END); + } + updateVariables(); + simulationEnded = true; + printStream.close(); + System.setOut(baseStream); + increment(finishDoStepSemaphore); + } + ); + printStream.registerModelExecutionThread(simulationThread); + System.setOut(printStream); + return simulationThread; + } + + public void sendStopEvent(StopReason stopReason) { + StopEvent stopEvent = new StopEvent(); + stopEvent.stopReason = stopReason; + try { + cout.writeObject(stopEvent); + } catch (IOException e) { + e.printStackTrace(); + } + } + + //public StopCondition doStep(CoordinationPredicate predicate) { + public StopCondition doStep() { + increment(startDoStepSemaphore); + decrement(finishDoStepSemaphore); + + updateVariables(); + + if (simulationEnded) { + lastStopcondition = new StopCondition(StopReason.REACHED_SIMULATION_END); + } else { + lastStopcondition = new StopCondition(StopReason.REACHED_NEXT_LOGICAL_STEP); + } + return lastStopcondition; + } + + private void updateVariables() { + for (MutableField mf : partAccessor.extractMutableField(root)) { + variables.put(mf.getName(), mf.getValue()); + } + } + + public List getStackTrace() { + List stackTrace = new ArrayList<>(); + + EObject eObj = stepCaller; + while (eObj != null) { + StackFrame frame = new StackFrame(); + frame.setName(eObj.toString()); + ICompositeNode node = NodeModelUtils.getNode(eObj); + frame.setLine(node.getStartLine()); + stackTrace.add(0, frame); + eObj = eObj.eContainer(); + } + + return stackTrace; + } + + public String getSourceContent() { + ICompositeNode node = NodeModelUtils.getNode(root); + return node.getText(); + } + +} diff --git a/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/StackFrame.java b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/StackFrame.java new file mode 100644 index 0000000..8a9957e --- /dev/null +++ b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/StackFrame.java @@ -0,0 +1,24 @@ +package org.eclipse.gemoc.execution.sequential.javaengine.headless; + +public class StackFrame { + + private String name; + private int line; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getLine() { + return line; + } + + public void setLine(int line) { + this.line = line; + } + +} diff --git a/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/StopSimulationException.java b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/StopSimulationException.java new file mode 100644 index 0000000..0cb2f53 --- /dev/null +++ b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/StopSimulationException.java @@ -0,0 +1,5 @@ +package org.eclipse.gemoc.execution.sequential.javaengine.headless; + +public class StopSimulationException extends RuntimeException { + +} diff --git a/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/commands/ClearBreakpointsCommand.java b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/commands/ClearBreakpointsCommand.java new file mode 100644 index 0000000..c86356e --- /dev/null +++ b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/commands/ClearBreakpointsCommand.java @@ -0,0 +1,7 @@ +package org.eclipse.gemoc.execution.sequential.javaengine.headless.commands; + +import java.io.Serializable; + +public class ClearBreakpointsCommand implements Serializable { + +} diff --git a/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/commands/ContinueCommand.java b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/commands/ContinueCommand.java new file mode 100644 index 0000000..121e24f --- /dev/null +++ b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/commands/ContinueCommand.java @@ -0,0 +1,7 @@ +package org.eclipse.gemoc.execution.sequential.javaengine.headless.commands; + +import java.io.Serializable; + +public class ContinueCommand implements Serializable { + +} diff --git a/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/commands/DoStepCommand.java b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/commands/DoStepCommand.java new file mode 100644 index 0000000..c1df695 --- /dev/null +++ b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/commands/DoStepCommand.java @@ -0,0 +1,9 @@ +package org.eclipse.gemoc.execution.sequential.javaengine.headless.commands; + +import java.io.Serializable; + +public class DoStepCommand implements Serializable { + + public StepKind stepKind; + +} diff --git a/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/commands/GetVariableCommand.java b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/commands/GetVariableCommand.java new file mode 100644 index 0000000..2bfd8b7 --- /dev/null +++ b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/commands/GetVariableCommand.java @@ -0,0 +1,9 @@ +package org.eclipse.gemoc.execution.sequential.javaengine.headless.commands; + +import java.io.Serializable; + +public class GetVariableCommand implements Serializable { + + public String variableQualifiedName; + +} diff --git a/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/commands/ListVariablesCommand.java b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/commands/ListVariablesCommand.java new file mode 100644 index 0000000..c643e92 --- /dev/null +++ b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/commands/ListVariablesCommand.java @@ -0,0 +1,7 @@ +package org.eclipse.gemoc.execution.sequential.javaengine.headless.commands; + +import java.io.Serializable; + +public class ListVariablesCommand implements Serializable { + +} diff --git a/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/commands/OutputEvent.java b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/commands/OutputEvent.java new file mode 100644 index 0000000..df64b2d --- /dev/null +++ b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/commands/OutputEvent.java @@ -0,0 +1,9 @@ +package org.eclipse.gemoc.execution.sequential.javaengine.headless.commands; + +import java.io.Serializable; + +public class OutputEvent implements Serializable { + + public String output; + +} diff --git a/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/commands/SetVariableCommand.java b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/commands/SetVariableCommand.java new file mode 100644 index 0000000..cb0e475 --- /dev/null +++ b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/commands/SetVariableCommand.java @@ -0,0 +1,5 @@ +package org.eclipse.gemoc.execution.sequential.javaengine.headless.commands; + +public class SetVariableCommand { + +} diff --git a/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/commands/StepKind.java b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/commands/StepKind.java new file mode 100644 index 0000000..5de0ea2 --- /dev/null +++ b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/commands/StepKind.java @@ -0,0 +1,7 @@ +package org.eclipse.gemoc.execution.sequential.javaengine.headless.commands; + +public enum StepKind { + NEXT, + STEP_IN, + STEP_OUT +}; diff --git a/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/commands/StopCommand.java b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/commands/StopCommand.java new file mode 100644 index 0000000..d19aaf5 --- /dev/null +++ b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/commands/StopCommand.java @@ -0,0 +1,7 @@ +package org.eclipse.gemoc.execution.sequential.javaengine.headless.commands; + +import java.io.Serializable; + +public class StopCommand implements Serializable { + +} diff --git a/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/commands/StopCondition.java b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/commands/StopCondition.java new file mode 100644 index 0000000..fd5a67f --- /dev/null +++ b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/commands/StopCondition.java @@ -0,0 +1,14 @@ +package org.eclipse.gemoc.execution.sequential.javaengine.headless.commands; + +import java.io.Serializable; + +public class StopCondition implements Serializable { + + public StopReason stopReason; + + public StopCondition(StopReason stopReason) { + super(); + this.stopReason = stopReason; + } + +} diff --git a/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/commands/StopEvent.java b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/commands/StopEvent.java new file mode 100644 index 0000000..ecd4009 --- /dev/null +++ b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/commands/StopEvent.java @@ -0,0 +1,9 @@ +package org.eclipse.gemoc.execution.sequential.javaengine.headless.commands; + +import java.io.Serializable; + +public class StopEvent implements Serializable { + + public StopReason stopReason; + +} diff --git a/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/commands/StopReason.java b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/commands/StopReason.java new file mode 100644 index 0000000..9233a0f --- /dev/null +++ b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/commands/StopReason.java @@ -0,0 +1,8 @@ +package org.eclipse.gemoc.execution.sequential.javaengine.headless.commands; + +public enum StopReason { + REACHED_BREAKPOINT, + REACHED_NEXT_LOGICAL_STEP, + REACHED_SIMULATION_END, + TIME +} diff --git a/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/commands/ToggleBreakpointCommand.java b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/commands/ToggleBreakpointCommand.java new file mode 100644 index 0000000..e6a6d99 --- /dev/null +++ b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/commands/ToggleBreakpointCommand.java @@ -0,0 +1,9 @@ +package org.eclipse.gemoc.execution.sequential.javaengine.headless.commands; + +import java.io.Serializable; + +public class ToggleBreakpointCommand implements Serializable { + + public int line; + +} diff --git a/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/mep/K3GemocMEPServerImpl.java b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/mep/K3GemocMEPServerImpl.java new file mode 100644 index 0000000..a4a5c59 --- /dev/null +++ b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/mep/K3GemocMEPServerImpl.java @@ -0,0 +1,268 @@ +package org.eclipse.gemoc.execution.sequential.javaengine.headless.mep; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.net.ConnectException; +import java.net.Socket; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Semaphore; + +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.gemoc.execution.sequential.javaengine.headless.AbstractHeadlessExecutionContext; +import org.eclipse.gemoc.execution.sequential.javaengine.headless.HeadlessJavaEngineSequentialRunConfiguration; +import org.eclipse.gemoc.execution.sequential.javaengine.headless.HeadlessPlainK3ExecutionEngine; +import org.eclipse.gemoc.execution.sequential.javaengine.headless.commands.ClearBreakpointsCommand; +import org.eclipse.gemoc.execution.sequential.javaengine.headless.commands.ContinueCommand; +import org.eclipse.gemoc.execution.sequential.javaengine.headless.commands.DoStepCommand; +import org.eclipse.gemoc.execution.sequential.javaengine.headless.commands.GetVariableCommand; +import org.eclipse.gemoc.execution.sequential.javaengine.headless.commands.ListVariablesCommand; +import org.eclipse.gemoc.execution.sequential.javaengine.headless.commands.OutputEvent; +import org.eclipse.gemoc.execution.sequential.javaengine.headless.commands.StepKind; +import org.eclipse.gemoc.execution.sequential.javaengine.headless.commands.StopCommand; +import org.eclipse.gemoc.execution.sequential.javaengine.headless.commands.StopCondition; +import org.eclipse.gemoc.execution.sequential.javaengine.headless.commands.StopEvent; +import org.eclipse.gemoc.execution.sequential.javaengine.headless.commands.StopReason; +import org.eclipse.gemoc.execution.sequential.javaengine.headless.commands.ToggleBreakpointCommand; +import org.eclipse.gemoc.executionframework.engine.commons.EngineContextException; +import org.eclipse.gemoc.executionframework.engine.commons.sequential.ISequentialRunConfiguration; +import org.eclipse.gemoc.executionframework.mep.launch.GemocMEPServerImpl; +import org.eclipse.gemoc.xdsmlframework.api.extensions.languages.LanguageDefinitionExtension; +import org.eclipse.lsp4j.debug.StackFrame; +import org.eclipse.lsp4j.debug.StoppedEventArguments; +import org.eclipse.lsp4j.debug.TerminatedEventArguments; +import org.eclipse.lsp4j.debug.Variable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public abstract class K3GemocMEPServerImpl extends GemocMEPServerImpl { + + private static final Logger LOGGER = LoggerFactory.getLogger("K3GemocMEPServerImpl"); + + protected T languageDefinition; + protected ISequentialRunConfiguration runConfiguration; + + Socket gemocServer = null; + ObjectInputStream gemocServerOutput = null; + ObjectOutputStream gemocServerInput = null; + List serverOutputBuffer = null; + Semaphore serverOutputBufferSem = null; + + + HeadlessPlainK3ExecutionEngine currentExecutionEngine; + + @Override + public void launchGemocEngine(Resource resourceModel, String modelEntryPoint, String methodEntryPoint, String initializationMethod, String initializationMethodArgs) { + try { + LOGGER.info("START launchGemocEngine()"); + HeadlessPlainK3ExecutionEngine executionEngine = new HeadlessPlainK3ExecutionEngine(); + + runConfiguration = new HeadlessJavaEngineSequentialRunConfiguration(resourceModel.getURI(), languageDefinition.getName(), + modelEntryPoint, methodEntryPoint, initializationMethod, initializationMethodArgs); + + AbstractHeadlessExecutionContext executioncontext = newExecutionContext(resourceModel); + + //HeadlessDebuggerAddon debuggerAddon = new HeadlessDebuggerAddon(); + + + //executioncontext.getExecutionPlatform().addEngineAddon(debuggerAddon); + executioncontext.initializeResourceModel(); + executionEngine.initialize(executioncontext); + + executionEngine.start(); + currentExecutionEngine = executionEngine; + + boolean connected = false; + // Retry until server is available + while (!connected) { + try { + gemocServer = new Socket("localhost", HeadlessPlainK3ExecutionEngine.GEMOC_PORT); + connected = true; + } catch (ConnectException e) { + System.out.println("Could not connect to GEMOC server, retrying..."); + Thread.sleep(1000); + } + } + gemocServerOutput = new ObjectInputStream(gemocServer.getInputStream()); + gemocServerInput = new ObjectOutputStream(gemocServer.getOutputStream()); + + new Thread(new Runnable() { + @Override + public void run() { + Object readData; + serverOutputBuffer = new ArrayList(); + serverOutputBufferSem = new Semaphore(0); + do { + try { + readData = gemocServerOutput.readObject(); + if (readData instanceof OutputEvent) { + sendOutput(((OutputEvent) readData).output); + } else if (readData instanceof StopEvent) { + manageStop(((StopEvent) readData).stopReason); + } else { + serverOutputBuffer.add(readData); + serverOutputBufferSem.release(); + } + } catch (ClassNotFoundException | IOException e) { + e.printStackTrace(); + break; + } + } while (readData != null); + } + }).start(); + //executionEngine.thread.join(); + } catch (Exception e) { + LOGGER.error(e.getMessage(), e); + } + } + + abstract protected AbstractHeadlessExecutionContext newExecutionContext(Resource resourceModel) throws EngineContextException; + + @Override + protected void internalNext() { + internalDoStep(StepKind.NEXT); + } + + @Override + protected void internalStepIn() { + internalDoStep(StepKind.STEP_IN); + } + + @Override + protected void internalStepOut() { + internalDoStep(StepKind.STEP_OUT); + } + + private void internalDoStep(StepKind stepKind) { + DoStepCommand command = new DoStepCommand(); + command.stepKind = stepKind; + try { + gemocServerInput.writeObject(command); + serverOutputBufferSem.acquire(); + Object output = serverOutputBuffer.remove(0); + manageStop(((StopCondition) output).stopReason); + } catch (IOException | InterruptedException e) { + e.printStackTrace(); + } + } + + protected void manageStop(StopReason stopReason) { + switch (stopReason) { + case REACHED_BREAKPOINT: + StoppedEventArguments stoppedArgsBreakpoint = new StoppedEventArguments(); + stoppedArgsBreakpoint.setReason("breakpoint"); + stoppedArgsBreakpoint.setDescription("Reached breakpoint"); + client.stopped(stoppedArgsBreakpoint); + break; + case REACHED_NEXT_LOGICAL_STEP: + StoppedEventArguments stoppedArgsStep = new StoppedEventArguments(); + stoppedArgsStep.setReason("step"); + stoppedArgsStep.setDescription("Reached new logical step"); + client.stopped(stoppedArgsStep); + break; + case REACHED_SIMULATION_END: + TerminatedEventArguments terminatedArgs = new TerminatedEventArguments(); + client.terminated(terminatedArgs); + simulationStarted = false; + break; + case TIME: + break; + default: + break; + } + } + + @Override + protected void internalTerminate() { + currentExecutionEngine.stop(); + StopCommand stopCommand = new StopCommand(); + try { + gemocServerInput.writeObject(stopCommand); + serverOutputBufferSem.acquire(); + serverOutputBuffer.remove(0); + } catch (IOException | InterruptedException e) { + e.printStackTrace(); + } + } + + @Override + protected Variable[] internalVariables() { + ListVariablesCommand listCommand = new ListVariablesCommand(); + try { + gemocServerInput.writeObject(listCommand); + serverOutputBufferSem.acquire(); + List variableNames = (ArrayList) serverOutputBuffer.remove(0); + Variable[] variables = new Variable[variableNames.size()]; + for (int i = 0; i < variables.length; i++) { + Variable variable = new Variable(); + variable.setName(variableNames.get(i)); + GetVariableCommand variableCommand = new GetVariableCommand(); + variableCommand.variableQualifiedName = variableNames.get(i); + gemocServerInput.writeObject(variableCommand); + serverOutputBufferSem.acquire(); + variable.setValue((String) serverOutputBuffer.remove(0)); + variables[i] = variable; + } + return variables; + } catch (IOException | InterruptedException e) { + e.printStackTrace(); + return new Variable[0]; + } + } + + @Override + protected StackFrame[] internalStackTrace() { + List gemocFrames = + currentExecutionEngine.getStackTrace(); + StackFrame[] mepFrames = new StackFrame[gemocFrames.size()]; + for (int i = 0; i < gemocFrames.size(); i++) { + StackFrame mepFrame = new StackFrame(); + mepFrame.setId((long) i); + mepFrame.setName(gemocFrames.get(i).getName()); + mepFrame.setLine((long) gemocFrames.get(i).getLine()); + mepFrame.setColumn(0L); + mepFrames[i] = mepFrame; + } + return mepFrames; + } + + + + @Override + protected String internalSource() { + return currentExecutionEngine.getSourceContent(); + } + + @Override + protected void internalClearBreakpoints() { + ClearBreakpointsCommand command = new ClearBreakpointsCommand(); + try { + gemocServerInput.writeObject(command); + } catch (IOException e) { + e.printStackTrace(); + } + } + + @Override + protected void internalToggleBreakpoint(int line) { + ToggleBreakpointCommand command = new ToggleBreakpointCommand(); + command.line = line; + try { + gemocServerInput.writeObject(command); + } catch (IOException e) { + e.printStackTrace(); + } + } + + @Override + protected void internalContinue() { + ContinueCommand command = new ContinueCommand(); + try { + gemocServerInput.writeObject(command); + } catch (IOException e) { + e.printStackTrace(); + } + } + +} diff --git a/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/test/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/AppTest.java b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/test/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/AppTest.java new file mode 100644 index 0000000..94810ae --- /dev/null +++ b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/test/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/AppTest.java @@ -0,0 +1,38 @@ +package org.eclipse.gemoc.execution.sequential.javaengine.headless; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +/** + * Unit test for simple App. + */ +public class AppTest + extends TestCase +{ + /** + * Create the test case + * + * @param testName name of the test case + */ + public AppTest( String testName ) + { + super( testName ); + } + + /** + * @return the suite of tests being tested + */ + public static Test suite() + { + return new TestSuite( AppTest.class ); + } + + /** + * Rigourous Test :-) + */ + public void testApp() + { + assertTrue( true ); + } +} diff --git a/java_engine/pomfirst/pom.xml b/java_engine/pomfirst/pom.xml new file mode 100644 index 0000000..5edace3 --- /dev/null +++ b/java_engine/pomfirst/pom.xml @@ -0,0 +1,74 @@ + + + 4.0.0 + + org.eclipse.gemoc.execution.sequential.javaengine + org.eclipse.gemoc.execution.sequential.javaengine.pomfirst + 1.0.0-SNAPSHOT + + + org.eclipse.gemoc + org.eclipse.gemoc.execution.sequential.java.pomfirst + 1.0.0-SNAPSHOT + ../../pomfirst/pom.xml + + + pom + + + org.eclipse.gemoc.execution.sequential.javaengine.headless + + + + + + + org.eclipse.xtend + xtend-maven-plugin + ${xtend.version} + + + + compile + xtend-install-debug-info + testCompile + xtend-test-install-debug-info + + + xtend-gen + + + + + + + + + org.eclipse.jdt + org.eclipse.jdt.core + 3.13.102 + + + org.eclipse.jdt + org.eclipse.jdt.compiler.apt + 1.3.110 + + + org.eclipse.jdt + org.eclipse.jdt.compiler.tool + 1.2.101 + + + org.eclipse.emf + org.eclipse.emf.codegen + 2.11.0 + + + + + + + \ No newline at end of file diff --git a/pomfirst/pom.xml b/pomfirst/pom.xml new file mode 100644 index 0000000..84f1040 --- /dev/null +++ b/pomfirst/pom.xml @@ -0,0 +1,108 @@ + + + 4.0.0 + + org.eclipse.gemoc + org.eclipse.gemoc.execution.sequential.java.pomfirst + 1.0.0-SNAPSHOT + + pom + + + 1.6.0 + 2.19.0 + UTF-8 + http://download.eclipse.org/releases/photon + https://download.eclipse.org/gemoc/updates/nightly + 1.8 + 1.8 + scm:git:https://github.com/eclipse/gemoc-studio-execution-java.git + UTF-8 + + + + + ../java_engine/pomfirst + + + + + + + org.eclipse.tycho + tycho-maven-plugin + ${tycho.version} + true + + + + org.eclipse.xtend + xtend-maven-plugin + ${xtend.version} + + + + compile + xtend-install-debug-info + testCompile + xtend-test-install-debug-info + + + xtend-gen + + + + + + + + + org.eclipse.jdt + org.eclipse.jdt.core + 3.13.102 + + + org.eclipse.jdt + org.eclipse.jdt.compiler.apt + 1.3.110 + + + org.eclipse.jdt + org.eclipse.jdt.compiler.tool + 1.2.101 + + + org.eclipse.emf + org.eclipse.emf.codegen + 2.11.0 + + + + + + + + + + nexus-eclipse-gemoc + Nexus Eclipse GEMOC + true + true + https://repo.eclipse.org/content/groups/gemoc/ + + + + eclipse-repo + ${eclipse-repo.url} + p2 + + + gemoc-repo + ${gemoc-repo.url} + p2 + + + \ No newline at end of file From babe270fe208bdeb48a1ae6d0fe5fecbfdf7341c Mon Sep 17 00:00:00 2001 From: Didier Vojtisek Date: Thu, 14 May 2020 10:20:30 +0200 Subject: [PATCH 2/4] pom cleanup Signed-off-by: Didier Vojtisek --- .../pom.xml | 4 +- java_engine/pomfirst/pom.xml | 18 +++- pomfirst/pom.xml | 101 ++---------------- 3 files changed, 27 insertions(+), 96 deletions(-) diff --git a/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/pom.xml b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/pom.xml index 9414813..b1ea76c 100644 --- a/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/pom.xml +++ b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/pom.xml @@ -15,7 +15,7 @@ UTF-8 1.8 1.8 - 2.14.0 + 2.19.0 @@ -175,7 +175,7 @@ https://repo.eclipse.org/content/groups/gemoc/ - >maven.inria.fr + >maven-inria-fr Maven Inria true diff --git a/java_engine/pomfirst/pom.xml b/java_engine/pomfirst/pom.xml index 5edace3..d44147b 100644 --- a/java_engine/pomfirst/pom.xml +++ b/java_engine/pomfirst/pom.xml @@ -9,15 +9,25 @@ org.eclipse.gemoc.execution.sequential.javaengine.pomfirst 1.0.0-SNAPSHOT - + pom + + + 2.19.0 + UTF-8 + http://download.eclipse.org/releases/photon + https://download.eclipse.org/gemoc/updates/nightly + 1.8 + 1.8 + scm:git:https://github.com/eclipse/gemoc-studio-execution-java.git + UTF-8 + + org.eclipse.gemoc.execution.sequential.javaengine.headless diff --git a/pomfirst/pom.xml b/pomfirst/pom.xml index 84f1040..258aeed 100644 --- a/pomfirst/pom.xml +++ b/pomfirst/pom.xml @@ -1,18 +1,17 @@ - + - 4.0.0 + 4.0.0 org.eclipse.gemoc - org.eclipse.gemoc.execution.sequential.java.pomfirst + org.eclipse.gemoc.execution.sequential.java.pomfirst 1.0.0-SNAPSHOT - - pom + + pom - 1.6.0 2.19.0 UTF-8 http://download.eclipse.org/releases/photon @@ -22,87 +21,9 @@ scm:git:https://github.com/eclipse/gemoc-studio-execution-java.git UTF-8 - - + - ../java_engine/pomfirst - - - - - - - org.eclipse.tycho - tycho-maven-plugin - ${tycho.version} - true - - - - org.eclipse.xtend - xtend-maven-plugin - ${xtend.version} - - - - compile - xtend-install-debug-info - testCompile - xtend-test-install-debug-info - - - xtend-gen - - - - - - - - - org.eclipse.jdt - org.eclipse.jdt.core - 3.13.102 - - - org.eclipse.jdt - org.eclipse.jdt.compiler.apt - 1.3.110 - - - org.eclipse.jdt - org.eclipse.jdt.compiler.tool - 1.2.101 - - - org.eclipse.emf - org.eclipse.emf.codegen - 2.11.0 - - - + ../java_engine/pomfirst + - - - - - - nexus-eclipse-gemoc - Nexus Eclipse GEMOC - true - true - https://repo.eclipse.org/content/groups/gemoc/ - - - - eclipse-repo - ${eclipse-repo.url} - p2 - - - gemoc-repo - ${gemoc-repo.url} - p2 - - \ No newline at end of file From b09d42dbf5a985c0f6442fd297cc2c22909512e1 Mon Sep 17 00:00:00 2001 From: Didier Vojtisek Date: Fri, 15 May 2020 15:02:53 +0200 Subject: [PATCH 3/4] create a set of "pomfirst" pom these pom are used to recreate a more reliable dependency tree of a subset of gemoc components when used from pure maven project Signed-off-by: Didier Vojtisek --- .../pomfirst/pom.xml | 91 +++++++++++++++++++ .../pom.xml | 44 ++++----- .../headless/mep/K3GemocMEPServerImpl.java | 2 +- pomfirst/pom.xml | 1 + 4 files changed, 113 insertions(+), 25 deletions(-) create mode 100644 java_engine/plugins/org.eclipse.gemoc.execution.sequential.javaengine/pomfirst/pom.xml diff --git a/java_engine/plugins/org.eclipse.gemoc.execution.sequential.javaengine/pomfirst/pom.xml b/java_engine/plugins/org.eclipse.gemoc.execution.sequential.javaengine/pomfirst/pom.xml new file mode 100644 index 0000000..cc14dfa --- /dev/null +++ b/java_engine/plugins/org.eclipse.gemoc.execution.sequential.javaengine/pomfirst/pom.xml @@ -0,0 +1,91 @@ + + + 4.0.0 + + org.eclipse.gemoc.pomfirst + org.eclipse.gemoc.execution.sequential.javaengine + 4.0.0-SNAPSHOT + + jar + + + scm:git:https://github.com/eclipse/gemoc-studio-modeldebugging.git + UTF-8 + + + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + unpack + prepare-package + + unpack + + + + + org.eclipse.gemoc.execution.sequential.java + ${project.artifactId} + ${project.version} + jar + true + ${project.build.directory}/classes + ** + + + + + + + + + + + + org.eclipse.gemoc.pomfirst + org.eclipse.gemoc.xdsmlframework.api + 4.0.0-SNAPSHOT + + + org.eclipse.gemoc.pomfirst + org.eclipse.gemoc.trace.commons.model + 3.0.1-SNAPSHOT + + + org.eclipse.gemoc.pomfirst + org.eclipse.gemoc.trace.commons + 3.0.1-SNAPSHOT + + + org.eclipse.gemoc.pomfirst + org.eclipse.gemoc.trace.gemoc.api + 3.0.1-SNAPSHOT + + + org.eclipse.gemoc.pomfirst + org.eclipse.gemoc.executionframework.engine + 4.0.0-SNAPSHOT + + + + + nexus-eclipse-gemoc + Nexus Eclipse GEMOC + + true + + + true + + https://repo.eclipse.org/content/groups/gemoc/ + + + \ No newline at end of file diff --git a/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/pom.xml b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/pom.xml index b1ea76c..cc27888 100644 --- a/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/pom.xml +++ b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/pom.xml @@ -57,7 +57,7 @@ - org.eclipse.gemoc.execution.sequential.java + org.eclipse.gemoc.pomfirst org.eclipse.gemoc.execution.sequential.javaengine 4.0.0-SNAPSHOT @@ -66,26 +66,22 @@ fr.inria.diverse.k3.al.annotationprocessor 3.2.3-SNAPSHOT + - org.eclipse.gemoc.trace.commons - org.eclipse.gemoc.trace.commons.model - 3.0.1-SNAPSHOT - - - org.eclipse.gemoc.trace.commons + org.eclipse.gemoc.pomfirst org.eclipse.gemoc.trace.commons 3.0.1-SNAPSHOT - org.eclipse.gemoc.modeldebugging.executionframework + org.eclipse.gemoc.pomfirst org.eclipse.gemoc.executionframework.debugger 4.0.0-SNAPSHOT - + - org.eclipse.gemoc.commons + org.eclipse.gemoc.pomfirst org.eclipse.gemoc.commons.utils 1.0.0-SNAPSHOT - org.eclipse.gemoc.commons + org.eclipse.gemoc.pomfirst org.eclipse.gemoc.commons.eclipse.pde 3.0.0-SNAPSHOT - org.eclipse.gemoc.commons + org.eclipse.gemoc.pomfirst org.eclipse.gemoc.commons.eclipse.messagingsystem.api 3.0.0-SNAPSHOT - + - org.eclipse.gemoc.modeldebugging.framework.commons + org.eclipse.gemoc.pomfirst org.eclipse.gemoc.xdsmlframework.commons 4.0.0-SNAPSHOT - + - DSLDebugger + org.eclipse.gemoc.pomfirst org.eclipse.gemoc.dsl.debug.ide 3.0.1-SNAPSHOT - DSLDebugger + org.eclipse.gemoc.pomfirst org.eclipse.gemoc.dsl.debug 3.0.1-SNAPSHOT - DSLDebugger + org.eclipse.gemoc.pomfirst org.eclipse.gemoc.dsl.debug.edit 3.0.1-SNAPSHOT diff --git a/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/mep/K3GemocMEPServerImpl.java b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/mep/K3GemocMEPServerImpl.java index a4a5c59..af8494f 100644 --- a/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/mep/K3GemocMEPServerImpl.java +++ b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/mep/K3GemocMEPServerImpl.java @@ -38,7 +38,7 @@ public abstract class K3GemocMEPServerImpl extends GemocMEPServerImpl { - private static final Logger LOGGER = LoggerFactory.getLogger("K3GemocMEPServerImpl"); + private static final Logger LOGGER = LoggerFactory.getLogger(K3GemocMEPServerImpl.class); protected T languageDefinition; protected ISequentialRunConfiguration runConfiguration; diff --git a/pomfirst/pom.xml b/pomfirst/pom.xml index 258aeed..e62caea 100644 --- a/pomfirst/pom.xml +++ b/pomfirst/pom.xml @@ -24,6 +24,7 @@ ../java_engine/pomfirst + ../java_engine/plugins/org.eclipse.gemoc.execution.sequential.javaengine/pomfirst \ No newline at end of file From 98866bf227a655e3d64f0b07fc9bcbc8224819c8 Mon Sep 17 00:00:00 2001 From: Didier Vojtisek Date: Tue, 2 Jun 2020 18:04:55 +0200 Subject: [PATCH 4/4] add jupyter notebook able to communicate with a K3 mep server Signed-off-by: Pierre Jeanjean --- python_client/.ipynb_checkpoints/.gitignore | 1 + python_client/MEPClient.ipynb | 224 ++++++++++++++++ python_client/README.md | 19 ++ python_client/environment.yml | 10 + .../k3_mep_client-checkpoint.py | 247 ++++++++++++++++++ .../__pycache__/k3_mep_client.cpython-37.pyc | Bin 0 -> 8406 bytes python_client/mep_client/k3_mep_client.py | 247 ++++++++++++++++++ python_client/requirements.txt | 1 + 8 files changed, 749 insertions(+) create mode 100644 python_client/.ipynb_checkpoints/.gitignore create mode 100644 python_client/MEPClient.ipynb create mode 100644 python_client/README.md create mode 100644 python_client/environment.yml create mode 100644 python_client/mep_client/.ipynb_checkpoints/k3_mep_client-checkpoint.py create mode 100644 python_client/mep_client/__pycache__/k3_mep_client.cpython-37.pyc create mode 100644 python_client/mep_client/k3_mep_client.py create mode 100644 python_client/requirements.txt diff --git a/python_client/.ipynb_checkpoints/.gitignore b/python_client/.ipynb_checkpoints/.gitignore new file mode 100644 index 0000000..3fa64c2 --- /dev/null +++ b/python_client/.ipynb_checkpoints/.gitignore @@ -0,0 +1 @@ +/MEPClient-checkpoint.ipynb diff --git a/python_client/MEPClient.ipynb b/python_client/MEPClient.ipynb new file mode 100644 index 0000000..08eec35 --- /dev/null +++ b/python_client/MEPClient.ipynb @@ -0,0 +1,224 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "%%capture\n", + "%pip install websockets==8.1" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "from mep_client.k3_mep_client import K3MepClient\n", + "\n", + "client = K3MepClient()" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "import time\n", + "\n", + "def update_variables():\n", + " variable_output_widget.clear_output()\n", + " with variable_output_widget:\n", + " print()\n", + " print()\n", + " print(\"Variables\")\n", + " print(\"―――――――――\")\n", + " client.variables()\n", + " \n", + "def update_stack():\n", + " stack_output_widget.clear_output()\n", + " with stack_output_widget:\n", + " print()\n", + " print()\n", + " print(\"Stack Trace\")\n", + " print(\"―――――――――――\")\n", + " client.stack_trace()\n", + " \n", + "def update_model():\n", + " model_output_widget.clear_output()\n", + " with model_output_widget:\n", + " print()\n", + " print()\n", + " print(\"Model\")\n", + " print(\"―――――\")\n", + " client.source(line_numbers=True)\n", + "\n", + "def connection_button_click(b):\n", + " with output_widget:\n", + " client.connect(host=host_widget.value, port=port_widget.value, endpoint=endpoint_widget.value)\n", + " client.initialize()\n", + "\n", + "def launch_button_click(b):\n", + " simulation_output_widget.clear_output()\n", + " with simulation_output_widget:\n", + " print()\n", + " print()\n", + " print(\"Simulation Output\")\n", + " print(\"―――――――――――――――――\")\n", + " client.launch(model_uri=model_uri_widget.value, model_entry_point=model_entrypoint_widget.value,\n", + " init_method=init_method_widget.value, init_args=init_args_widget.value, method_entry_point=method_entrypoint_widget.value)\n", + " update_model()\n", + " update_stack()\n", + " update_variables()\n", + " \n", + "def continue_button_click(b):\n", + " with simulation_output_widget:\n", + " client.continue_()\n", + " while client.simulation_running and not client.paused:\n", + " time.sleep(0.1) # Required to capture all outputs from thread\n", + " update_model()\n", + " update_stack()\n", + " update_variables()\n", + " \n", + "def next_button_click(b):\n", + " with simulation_output_widget:\n", + " client.next()\n", + " update_model()\n", + " update_stack()\n", + " update_variables()\n", + " \n", + "def step_in_button_click(b):\n", + " with simulation_output_widget:\n", + " client.step_in()\n", + " update_model()\n", + " update_stack()\n", + " update_variables()\n", + " \n", + "def step_out_button_click(b):\n", + " with simulation_output_widget:\n", + " client.step_out()\n", + " update_model()\n", + " update_stack()\n", + " update_variables()\n", + " \n", + "def terminate_button_click(b):\n", + " with output_widget:\n", + " client.terminate()\n", + "\n", + "def restart_button_click(b):\n", + " simulation_output_widget.clear_output()\n", + " with simulation_output_widget:\n", + " print()\n", + " print()\n", + " print(\"Simulation Output\")\n", + " print(\"―――――――――――――――――\")\n", + " client.restart()\n", + " update_model()\n", + " update_stack()\n", + " update_variables()\n", + " \n", + "def set_breakpoints_button_click(b):\n", + " with output_widget:\n", + " int_lines = []\n", + " lines = set_breakpoints_lines_widget.value.split()\n", + " for line in lines:\n", + " int_lines.append(int(line))\n", + " client.set_breakpoints(int_lines)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "4cdd61fd5bba4e60bf5de18ba396d368", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "VBox(children=(Accordion(children=(VBox(children=(Text(value='localhost', description='Host:'), IntText(value=…" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import ipywidgets\n", + "\n", + "host_widget = ipywidgets.Text(value='localhost', description='Host:')\n", + "port_widget = ipywidgets.IntText(value=8090, description='Port:')\n", + "endpoint_widget = ipywidgets.Text(value='mep/', description='Endpoint:')\n", + "connection_button = ipywidgets.Button(description='Connect')\n", + "connection_button.on_click(connection_button_click)\n", + "connection_widgets = ipywidgets.VBox([host_widget, port_widget, endpoint_widget, connection_button])\n", + "\n", + "model_uri_widget = ipywidgets.Text(value='', description='Model URI:', layout=ipywidgets.Layout(min_width='50%'), style={'description_width': '150px'})\n", + "model_entrypoint_widget = ipywidgets.Text(value='/', description='Model Entrypoint:', layout=ipywidgets.Layout(min_width='50%'), style={'description_width': '150px'})\n", + "init_method_widget = ipywidgets.Text(value='', description='Initialization Method:', layout=ipywidgets.Layout(min_width='50%'), style={'description_width': '150px'})\n", + "init_args_widget = ipywidgets.Text(value='', description='Initialization Arguments:', layout=ipywidgets.Layout(min_width='50%'), style={'description_width': '150px'})\n", + "method_entrypoint_widget = ipywidgets.Text(value='', description='Method Entrypoint:', layout=ipywidgets.Layout(min_width='50%'), style={'description_width': '150px'})\n", + "launch_button = ipywidgets.Button(description='Launch')\n", + "launch_button.on_click(launch_button_click)\n", + "launch_widgets = ipywidgets.VBox([model_uri_widget, model_entrypoint_widget, init_method_widget, method_entrypoint_widget, init_args_widget, launch_button])\n", + "\n", + "accordion = ipywidgets.Accordion(children=[connection_widgets, launch_widgets])\n", + "accordion.set_title(0, 'Connection Parameters')\n", + "accordion.set_title(1, 'Launch Configuration')\n", + "\n", + "output_widget = ipywidgets.Output()\n", + "model_output_widget = ipywidgets.Output()\n", + "simulation_output_widget = ipywidgets.Output()\n", + "stack_output_widget = ipywidgets.Output()\n", + "variable_output_widget = ipywidgets.Output()\n", + "\n", + "continue_button = ipywidgets.Button(description='▶', tooltip='Continue', layout=ipywidgets.Layout(width='50px'))\n", + "continue_button.on_click(continue_button_click)\n", + "next_button = ipywidgets.Button(description='➡', tooltip='Next', layout=ipywidgets.Layout(width='50px'))\n", + "next_button.on_click(next_button_click)\n", + "step_in_button = ipywidgets.Button(description='  ➡】', tooltip='Step In', layout=ipywidgets.Layout(width='50px'))\n", + "step_in_button.on_click(step_in_button_click)\n", + "step_out_button = ipywidgets.Button(description='【➡  ', tooltip='Step Out', layout=ipywidgets.Layout(width='50px'))\n", + "step_out_button.on_click(step_out_button_click)\n", + "terminate_button = ipywidgets.Button(description='⏹', tooltip='Terminate', layout=ipywidgets.Layout(width='50px'))\n", + "terminate_button.on_click(terminate_button_click)\n", + "restart_button = ipywidgets.Button(description='↻', tooltip='Restart', layout=ipywidgets.Layout(width='50px'))\n", + "restart_button.on_click(restart_button_click)\n", + "set_breakpoints_lines_widget = ipywidgets.Text(description='Breakpoints', placeholder='line1 line2 ...')\n", + "set_breakpoints_button = ipywidgets.Button(description='Set', tooltip='Set Breakpoints', layout=ipywidgets.Layout(width='50px'))\n", + "set_breakpoints_button.on_click(set_breakpoints_button_click)\n", + "debug_widgets = ipywidgets.VBox([ipywidgets.HBox([continue_button, next_button, step_in_button, step_out_button, terminate_button, restart_button]),\n", + " ipywidgets.HBox([set_breakpoints_lines_widget, set_breakpoints_button])])\n", + "\n", + "ipywidgets.VBox([accordion, output_widget, model_output_widget, simulation_output_widget, variable_output_widget, stack_output_widget, debug_widgets])" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.6" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/python_client/README.md b/python_client/README.md new file mode 100644 index 0000000..fea77f1 --- /dev/null +++ b/python_client/README.md @@ -0,0 +1,19 @@ +how to start jupyter client: + + +### Install Miniconda + +**This step is only necessary if you don't have conda installed**: +- download the Miniconda installer for your OS [here](https://docs.conda.io/en/latest/miniconda.html) +- run the installer following the instructions + [here](https://conda.io/projects/conda/en/latest/user-guide/install/index.html#regular-installation) + depending on your OS. + +### Create conda environment + +```sh +# Create a conda environment with the required packages for this notebook: +conda env create -f environment.yml +# Activate your conda environment +conda activate mep-client +``` diff --git a/python_client/environment.yml b/python_client/environment.yml new file mode 100644 index 0000000..cf30deb --- /dev/null +++ b/python_client/environment.yml @@ -0,0 +1,10 @@ +name: mep-client +channels: + - conda-forge +dependencies: + - python=3.7 + - jupyter + - jupyterlab + - notebook + - pip + - ipywidgets>=7.5 diff --git a/python_client/mep_client/.ipynb_checkpoints/k3_mep_client-checkpoint.py b/python_client/mep_client/.ipynb_checkpoints/k3_mep_client-checkpoint.py new file mode 100644 index 0000000..b25b894 --- /dev/null +++ b/python_client/mep_client/.ipynb_checkpoints/k3_mep_client-checkpoint.py @@ -0,0 +1,247 @@ +import asyncio +import json +import sys +import threading +import websockets + +class K3MepClient: + + def __init__(self): + self.host = "" + self.port = 0 + self.endpoint = "" + self.websocket = None + self.event_loop = None + self.event_loop_thread = None + self.json_responses = [] + self.response_semaphore = None + self.initialized = False + self.simulation_running = False + self.paused = False + + def connect(self, host="localhost", port=8090, endpoint=""): + self.host = host + self.port = port + self.endpoint = endpoint + self.event_loop = asyncio.new_event_loop() + self.event_loop_thread = threading.Thread( + target=lambda: self._start_event_loop()) + self.response_semaphore = threading.Semaphore(0) + self.event_loop_thread.start() + asyncio.run_coroutine_threadsafe(self._connect(), + self.event_loop) + self.response_semaphore.acquire() + + def _start_event_loop(self): + self.event_loop.run_forever() + + async def _connect(self): + uri = f'ws://{self.host}:{self.port}/{self.endpoint}' + print(f'Connecting to {uri}...') + self.websocket = await websockets.client.connect(uri) + print('Connected') + asyncio.ensure_future(self._response_handler()) + + def disconnect(self): + asyncio.run_coroutine_threadsafe(self._disconnect(), + self.event_loop) + self.event_loop.stop() + + async def _disconnect(self): + await self.websocket.close() + + def initialize(self): + request = {'type': 'request', 'command': 'initialize'} + asyncio.run_coroutine_threadsafe( + self._send_request(json.dumps(request)), + self.event_loop) + self.response_semaphore.acquire() + self.json_responses.pop() + + def launch(self, model_uri='', model_entry_point='/', + init_method='', init_args='', method_entry_point=''): + request = {'type': 'request', 'command': 'launch', + 'arguments': {'modelURI': model_uri, + 'modelEntryPoint': model_entry_point, + 'initializationMethod': init_method, + 'initializationArguments': init_args, + 'methodEntryPoint': method_entry_point}} + asyncio.run_coroutine_threadsafe( + self._send_request(json.dumps(request)), + self.event_loop) + self.response_semaphore.acquire() + response = self.json_responses.pop() + if response['success'] == False: + print(f'Error: {response["message"]}', file=sys.stderr) + else: + self.simulation_running = True + self.paused = True + + def continue_(self): + self.paused = False + request = {'type': 'request', 'command': 'continue'} + asyncio.run_coroutine_threadsafe( + self._send_request(json.dumps(request)), + self.event_loop) + self.response_semaphore.acquire() + response = self.json_responses.pop() + if response['success'] == False: + print(f'Error: {response["message"]}', file=sys.stderr) + + def next(self): + self.paused = False + request = {'type': 'request', 'command': 'next'} + asyncio.run_coroutine_threadsafe( + self._send_request(json.dumps(request)), + self.event_loop) + self.response_semaphore.acquire() + response = self.json_responses.pop() + if response['success'] == False: + print(f'Error: {response["message"]}', file=sys.stderr) + + def step_in(self): + self.paused = False + request = {'type': 'request', 'command': 'stepIn'} + asyncio.run_coroutine_threadsafe( + self._send_request(json.dumps(request)), + self.event_loop) + self.response_semaphore.acquire() + response = self.json_responses.pop() + if response['success'] == False: + print(f'Error: {response["message"]}', file=sys.stderr) + + def step_out(self): + self.paused = False + request = {'type': 'request', 'command': 'stepIn'} + asyncio.run_coroutine_threadsafe( + self._send_request(json.dumps(request)), + self.event_loop) + self.response_semaphore.acquire() + response = self.json_responses.pop() + if response['success'] == False: + print(f'Error: {response["message"]}', file=sys.stderr) + + def terminate(self): + request = {'type': 'request', 'command': 'terminate'} + asyncio.run_coroutine_threadsafe( + self._send_request(json.dumps(request)), + self.event_loop) + self.response_semaphore.acquire() + response = self.json_responses.pop() + if response['success'] == False: + print(f'Error: {response["message"]}', file=sys.stderr) + else: + self.simulation_running = False + self.paused = False + + def restart(self): + request = {'type': 'request', 'command': 'restart'} + asyncio.run_coroutine_threadsafe( + self._send_request(json.dumps(request)), + self.event_loop) + self.response_semaphore.acquire() + response = self.json_responses.pop() + if response['success'] == False: + print(f'Error: {response["message"]}', file=sys.stderr) + else: + self.simulation_running = True + self.paused = True + + def variables(self): + request = {'type': 'request', 'command': 'variables'} + asyncio.run_coroutine_threadsafe( + self._send_request(json.dumps(request)), + self.event_loop) + self.response_semaphore.acquire() + response = self.json_responses.pop() + if response['success'] == False: + print(f'Error: {response["message"]}', file=sys.stderr) + else: + for variable in response['body']['variables']: + print(f'{variable["name"]}: {variable["value"]}') + + def stack_trace(self): + request = {'type': 'request', 'command': 'stackTrace'} + asyncio.run_coroutine_threadsafe( + self._send_request(json.dumps(request)), + self.event_loop) + self.response_semaphore.acquire() + response = self.json_responses.pop() + if response['success'] == False: + print(f'Error: {response["message"]}', file=sys.stderr) + else: + indent = '' + for stackFrame in response['body']['stackFrames']: + print(f'{indent}{stackFrame["name"]} (line: {stackFrame["line"]})') + indent = f'{indent} ' + + def source(self, line_numbers=False): + request = {'type': 'request', 'command': 'source'} + asyncio.run_coroutine_threadsafe( + self._send_request(json.dumps(request)), + self.event_loop) + self.response_semaphore.acquire() + response = self.json_responses.pop() + if response['success'] == False: + print(f'Error: {response["message"]}', file=sys.stderr) + else: + source_content = response["body"]["content"] + if line_numbers: + source_content_splitted = source_content.split('\n') + adjust_index = len(str(len(source_content_splitted))) + for i in range(len(source_content_splitted)): + source_content_splitted[i] = str(i+1).rjust(adjust_index) + ' '\ + + source_content_splitted[i] + source_content = '\n'.join(source_content_splitted) + print(source_content) + + def set_breakpoints(self, lines): + request = {'type': 'request', 'command': 'setBreakpoints', + 'arguments': {'breakpoints': []}} + for line in lines: + request['arguments']['breakpoints'].append({'line': line}) + asyncio.run_coroutine_threadsafe( + self._send_request(json.dumps(request)), + self.event_loop) + self.response_semaphore.acquire() + response = self.json_responses.pop() + if response['success'] == False: + print(f'Error: {response["message"]}', file=sys.stderr) + + async def _send_request(self, request): + await self.websocket.send(request) + + def _manage_event(self, json_event): + if json_event['event'] == 'initialized': + self.initialized = True + elif json_event['event'] == 'output': + if json_event['body']['category'] == 'stdout': + print(json_event['body']['output'], end='') + else: + print('Error: Unknown output category: ' + + json_event['body']['category'], + file=sys.stderr) + elif json_event['event'] == 'stopped': + if json_event['body']['reason'] == 'step': + self.paused = True + elif json_event['body']['reason'] == 'breakpoint': + self.paused = True + else: + print('Error: Unknown stopped reason: ' + + json_event['body']['reason'], + file=sys.stderr) + elif json_event['event'] == 'terminated': + self.simulation_running = False + else: + print(f'Error: Unsupported event: {json_event["event"]}', + file=sys.stderr) + + async def _response_handler(self): + self.response_semaphore.release() + async for message in self.websocket: + json_message = json.loads(message) + if json_message['type'] == 'response': + self.json_responses.append(json_message) + self.response_semaphore.release() + elif json_message['type'] == 'event': + self._manage_event(json_message) diff --git a/python_client/mep_client/__pycache__/k3_mep_client.cpython-37.pyc b/python_client/mep_client/__pycache__/k3_mep_client.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e867c93fa9d29ed545522a6b2182c614a07e53c4 GIT binary patch literal 8406 zcmd5>O>7&-72erDE|))&XxXxyKgMaCFioT+PSe(P-Na6mxJ87tc94`sv!ysIi4?h{ zW|y`^P(XngY1$%}9&%{nf>d# zKZUfw@8S0%E%N*L{YYo{1H6oMmOsc(Bc0<9@vk5)@w5C4e*_~P=~RC3bX?1YgtyB!fp#}9b7(+DD&z3#7t zo%)s^N!P!INqMbKrz_{ic`w=&evQjwGwcMO@WXB=2>no&Mp-ZP+qLdyNBA<=2pUnN z)@t;9E=ysf-D}mN26gKNK_l3ZcDL3GeO_VG4E@&n?=>-t>D{`ryxD2{%lulW88t$G zd7}~0)2gj`8?6p1w$84HZLjTjm%F>sCI+l44lbi+l-)W@?~~F}cUL-|N7M1VEV1m)J_(+!g2QuO7}Z4NjYX-LU14GdZB<^(At#;lty+7H*Dl

fx z5l#Jl?WVoQB7>U)s2TVB4!&fQ|m{oXiG&($Z2jn^a=6=MKWc>I%|5ZmN4iX~!E{oW|5e zhR7m_Ecij#6TY|Ji;w`)snXf31-u0=>Ppbk=!r%Q=`kzI7y+l07OF#w-OFa#JPC7p zzb6PtIZ67GU~`FjmO&!O5**O?Nv;NMNlIyRC;WhXEj3*MJ)y~*#~WcXYAkj$j5^(; zL`mQQECqFQ{);tg6%QaKH814=z_{RPMzf61%UG8Bm>1*QCztS9~0@yt*)5 z`@GobwP7NJ)!DXcFdm>{2m+5d3nH^P65@t36ZYzLKMYs;nHPoVh;wC`X`@`*01l4nDy3P8f$z2r-Cf!g5dZ!y|9fgq<$f2&)wqiqAghL}ThgQ0+>_j1DhEB4r zvZSo{^ntEm!vLGLD93G-GYM?+%>s7_HVP=&)sXcD8>Ton$0}OL##){IaCJti@TJ=pF#*?VAMEvcNwLr6ZF%Xe;r+!32!0&{Czpukyw64`!Fi8qu+|Ed10;!!LozdhDSRCSIF!jAp7f|VdwJ{ndOhrT? zkW@s!`?5v!0?+OlI~O1(2!-dAn3ncT64U$Iz>EdN3&<6f&}MF0EaUgT zkg9dSdX#n};IQ74HK=JEkgtqq=tZ=?-(rH{Nsz<(jzU0X)}L~P)!O2oD|PaL=|^r# zD(=6dknTu*%Gc9B!`Cygo2HK!BQ@H`$4i7(v>zetJ^0t+&jWK<;JJOaXGO(mCMpgf zUi$CZJI_Y5qcZmHnY~Oj1OG9aIfO2vP$m5g1r?^8!T6IYqNWtcFECh)s12>bR187iIXz&I z=&3y;arBHuZHOqrz-S=e!nExZuWQky!#Kj;r#Xx!)B{k!9hf$6!(q&#taLo$4CFB8 zQin00D2Za|M;CE7u%$feu$o&N7bXJ&;+vR%OkSZJd6Y+=!NB%~`DaFJ3i<9%13WiP1A`NH$6MYA`hoHk8VxFgco)a{3$fZkPU z!-wehB6Uhhrw%K8qa$`z1PO1{35KYY0U`9uNx15@U@Pcc56W@R@~F?bauNg~kFNv7 za%ltn6n{jp*Y8SqjHdnr2gXWzl;aLK6y4O2<}3YEY3s1prQ156m(?QhONfvY}l<~woM%-%pf@c(D^pg9HReXl-_XK%lF+#1_)S}RHoFj%O;9aSl zq?o;^>xo`=9^uSNO1=WX|Dt@w>7QJ2$1=)Osmi7XMJYXCuUa6w^B@jQ`>L|!2B zA`x;D1-UTFOcoTA6Lj#2pAb<2T;h*f_5>>w5a;LxDKD~?Li(7aI|aAk7*58qKppU> zfC!feII^Ah8M}-a~^vLWD*>>XW$Qj2Ur(EDv=b