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/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/.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 0000000..99968c2 Binary files /dev/null and b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/lib_not_correctly_deployed/org.eclipse.emf.transaction_1.9.1.201805140824.jar differ 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 new file mode 100644 index 0000000..cc27888 --- /dev/null +++ b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/pom.xml @@ -0,0 +1,185 @@ + + 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.19.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.pomfirst + 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.pomfirst + org.eclipse.gemoc.trace.commons + 3.0.1-SNAPSHOT + + + org.eclipse.gemoc.pomfirst + org.eclipse.gemoc.executionframework.debugger + 4.0.0-SNAPSHOT + + + + + + + + org.eclipse.emf + org.eclipse.emf.edit + [2.16.0,3.0.0) + + + + + org.eclipse.gemoc.pomfirst + org.eclipse.gemoc.commons.utils + 1.0.0-SNAPSHOT + + + org.eclipse.gemoc.pomfirst + org.eclipse.gemoc.commons.eclipse.pde + 3.0.0-SNAPSHOT + + + + org.eclipse.gemoc.pomfirst + org.eclipse.gemoc.commons.eclipse.messagingsystem.api + 3.0.0-SNAPSHOT + + + + org.eclipse.gemoc.pomfirst + org.eclipse.gemoc.xdsmlframework.commons + 4.0.0-SNAPSHOT + + + + org.eclipse.gemoc.pomfirst + org.eclipse.gemoc.dsl.debug.ide + 3.0.1-SNAPSHOT + + + org.eclipse.gemoc.pomfirst + org.eclipse.gemoc.dsl.debug + 3.0.1-SNAPSHOT + + + org.eclipse.gemoc.pomfirst + 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..af8494f --- /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.class); + + 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..d44147b --- /dev/null +++ b/java_engine/pomfirst/pom.xml @@ -0,0 +1,84 @@ + + + 4.0.0 + + org.eclipse.gemoc.execution.sequential.javaengine + 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 + + + + + + + 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..e62caea --- /dev/null +++ b/pomfirst/pom.xml @@ -0,0 +1,30 @@ + + + 4.0.0 + + org.eclipse.gemoc + org.eclipse.gemoc.execution.sequential.java.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 + + + + ../java_engine/pomfirst + ../java_engine/plugins/org.eclipse.gemoc.execution.sequential.javaengine/pomfirst + + + \ No newline at end of file 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 0000000..e867c93 Binary files /dev/null and b/python_client/mep_client/__pycache__/k3_mep_client.cpython-37.pyc differ diff --git a/python_client/mep_client/k3_mep_client.py b/python_client/mep_client/k3_mep_client.py new file mode 100644 index 0000000..b25b894 --- /dev/null +++ b/python_client/mep_client/k3_mep_client.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/requirements.txt b/python_client/requirements.txt new file mode 100644 index 0000000..75ed27a --- /dev/null +++ b/python_client/requirements.txt @@ -0,0 +1 @@ +websockets==8.1