diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..70afca2 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,40 @@ +--- +name: Bug report +about: Create a report to help us improve the following components of the GEMOC Studio: java engine, java_xdsml (K3) (if you know that the issue is relative to another component, consider opening the issue on one of the other GEMOC github repositories) +title: '' +labels: bug +assignees: '' + +--- + +## Bug description + + + + +## Expected behavior + + + + +## How to reproduce + +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +## Additional context + + + +- **GEMOC Studio version**: +- **Java version**: +- **OS**: + +## Screenshot + + + + diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..f918bc2 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,22 @@ +--- +name: Feature request +about: Suggest an idea to improve the following components of the GEMOC Studio: java engine, java_xdsml (K3) (if you know that the issue is relative to another component, consider opening the issue on one of the other GEMOC github repositories) +title: '' +labels: enhancement +assignees: '' + +--- + +## Motivation + + + + +## Proposed Solution + + + + +## Proposed Implementation + + \ No newline at end of file diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..ecfe4a0 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,25 @@ + +## Description + + + + +Does X + +## Changes + + + + - + +## Contribution to issues + +Contribute to # +Closes # + +## Companion Pull Requests + + + + + - PR # diff --git a/.gitignore b/.gitignore index aeca2a8..d201c50 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,5 @@ bin/ -**/xtend-gen/ \ No newline at end of file +**/xtend-gen/ +*/*.class +**/target/ +**/.settings diff --git a/.grenrc.yml b/.grenrc.yml new file mode 100644 index 0000000..7dd1c06 --- /dev/null +++ b/.grenrc.yml @@ -0,0 +1,23 @@ +--- + dataSource: "prs" + prefix: "v" + ignoreLabels: + - "duplicate" + - "invalid" + - "question" + - "to do" + - "wontfix" + ignoreIssuesWith: + - "duplicate" + - "invalid" + - "question" + - "wontfix" + "groupBy": { + "Enhancements:": ["enhancement"], + "Bug Fixes:": ["bug"], + "Refactorings": ["refactoring"], + "Version upgrades": ["bump"], + "Release Engineering": ["releng"] + } + onlyMilestones: false + changelogFilename: "CHANGELOG.md" diff --git a/.mvn/extensions.xml b/.mvn/extensions.xml index 5724f5e..c8b79d9 100644 --- a/.mvn/extensions.xml +++ b/.mvn/extensions.xml @@ -3,6 +3,6 @@ org.eclipse.tycho.extras tycho-pomless - 1.5.1 + 1.7.0 \ No newline at end of file diff --git a/.project b/.project index c7d5d0a..e53bcff 100644 --- a/.project +++ b/.project @@ -1,11 +1,17 @@ - org.eclipse.gemoc.execution.sequential.java.root + gemoc-studio-execution-java + + org.eclipse.m2e.core.maven2Builder + + + + org.eclipse.m2e.core.maven2Nature diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..355a23d --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,23 @@ +# Changelog + +## v3.2.0 (16/06/2020) + +#### Enhancements: + +- [**enhancement**] ValidationRule added to languageComponent in plugin [#10](https://github.com/eclipse/gemoc-studio-execution-java/pull/10) +- [**enhancement**] Metaprogramming approach name changed to FullyQualifiedName [#8](https://github.com/eclipse/gemoc-studio-execution-java/pull/8) +- [**enhancement**] Metaprog plugin modified to fit new extension point description + added LanguageComponent [#9](https://github.com/eclipse/gemoc-studio-execution-java/pull/9) +- [**enhancement**] Validator removed from plugin.xml [#12](https://github.com/eclipse/gemoc-studio-execution-java/pull/12) +- [**enhancement**] Validation plug-in for the Kermeta3 meta-programming approach in GEMOC Studio [#5](https://github.com/eclipse/gemoc-studio-execution-java/pull/5) + +#### Bug Fixes: + +- [**bug**] Fix windows specific issue on the K3 project creation wizard [#3](https://github.com/eclipse/gemoc-studio-execution-java/pull/3) + +#### Refactorings + +- [**refactoring**] Kermeta3Rule moved to the gemoc-modeldebugging [#6](https://github.com/eclipse/gemoc-studio-execution-java/pull/6) + +#### Release Engineering + +- [**releng**] Deploy GEMOC artefacts to maven repository (repo.eclipse.org) [#4](https://github.com/eclipse/gemoc-studio-execution-java/pull/4) diff --git a/README.md b/README.md new file mode 100644 index 0000000..e0f1458 --- /dev/null +++ b/README.md @@ -0,0 +1,20 @@ +------------- +This repository is part of a serie of repositories related to [GEMOC Studio](http://eclipse.org/gemoc) : +- https://github.com/eclipse/gemoc-studio +- https://github.com/eclipse/gemoc-studio-modeldebugging +- https://github.com/eclipse/gemoc-studio-execution-ale +- https://github.com/eclipse/gemoc-studio-execution-java +- https://github.com/eclipse/gemoc-studio-execution-moccml +- https://github.com/eclipse/gemoc-studio-moccml +------------- + + + +JAVA engine for GEMOC +==================== + +The repository includes the component related to ___java_execution___. Its contains an implementation of the GEMOC framework using a sequential java engine (based on xtend+k3). + +# Development +- Continuous integration on [Eclipse CI](https://ci.eclipse.org/gemoc/job/gemoc-studio/) +- [Instructions for building](https://github.com/eclipse/gemoc-studio/tree/master/dev_support/full_compilation) diff --git a/java_engine/plugins/org.eclipse.gemoc.execution.sequential.javaengine.ui/.project b/java_engine/plugins/org.eclipse.gemoc.execution.sequential.javaengine.ui/.project index 940f6ba..7533254 100644 --- a/java_engine/plugins/org.eclipse.gemoc.execution.sequential.javaengine.ui/.project +++ b/java_engine/plugins/org.eclipse.gemoc.execution.sequential.javaengine.ui/.project @@ -25,8 +25,14 @@ + + org.eclipse.m2e.core.maven2Builder + + + + org.eclipse.m2e.core.maven2Nature org.eclipse.jdt.core.javanature org.eclipse.pde.PluginNature org.eclipse.xtext.ui.shared.xtextNature diff --git a/java_engine/plugins/org.eclipse.gemoc.execution.sequential.javaengine.ui/src/org/eclipse/gemoc/execution/sequential/javaengine/ui/launcher/Launcher.java b/java_engine/plugins/org.eclipse.gemoc.execution.sequential.javaengine.ui/src/org/eclipse/gemoc/execution/sequential/javaengine/ui/launcher/Launcher.java index 5043d1e..9ddea77 100644 --- a/java_engine/plugins/org.eclipse.gemoc.execution.sequential.javaengine.ui/src/org/eclipse/gemoc/execution/sequential/javaengine/ui/launcher/Launcher.java +++ b/java_engine/plugins/org.eclipse.gemoc.execution.sequential.javaengine.ui/src/org/eclipse/gemoc/execution/sequential/javaengine/ui/launcher/Launcher.java @@ -18,15 +18,18 @@ import org.eclipse.gemoc.commons.eclipse.ui.ViewHelper; import org.eclipse.gemoc.execution.sequential.javaengine.PlainK3ExecutionEngine; import org.eclipse.gemoc.execution.sequential.javaengine.ui.Activator; +import org.eclipse.gemoc.executionframework.engine.commons.DefaultExecutionPlatform; import org.eclipse.gemoc.executionframework.engine.commons.EngineContextException; import org.eclipse.gemoc.executionframework.engine.commons.GenericModelExecutionContext; +import org.eclipse.gemoc.executionframework.engine.commons.sequential.ISequentialModelExecutionContext; import org.eclipse.gemoc.executionframework.engine.commons.sequential.ISequentialRunConfiguration; +import org.eclipse.gemoc.executionframework.engine.commons.sequential.SequentialModelExecutionContext; import org.eclipse.gemoc.executionframework.engine.commons.sequential.SequentialRunConfiguration; import org.eclipse.gemoc.executionframework.engine.ui.launcher.AbstractSequentialGemocLauncher; import org.eclipse.gemoc.executionframework.ui.views.engine.EnginesStatusView; import org.eclipse.gemoc.xdsmlframework.api.core.ExecutionMode; -public class Launcher extends AbstractSequentialGemocLauncher, ISequentialRunConfiguration> { +public class Launcher extends AbstractSequentialGemocLauncher { public final static String TYPE_ID = Activator.PLUGIN_ID + ".launcher"; @@ -35,8 +38,7 @@ protected PlainK3ExecutionEngine createExecutionEngine(ISequentialRunConfigurati ExecutionMode executionMode) throws CoreException, EngineContextException { // create and initialize engine PlainK3ExecutionEngine executionEngine = new PlainK3ExecutionEngine(); - GenericModelExecutionContext executioncontext = new GenericModelExecutionContext( - runConfiguration, executionMode); + SequentialModelExecutionContext executioncontext = new SequentialModelExecutionContext(runConfiguration, executionMode); executioncontext.getExecutionPlatform().getModelLoader().setProgressMonitor(this.launchProgressMonitor); executioncontext.initializeResourceModel(); executionEngine.initialize(executioncontext); diff --git a/java_engine/plugins/org.eclipse.gemoc.execution.sequential.javaengine/.project b/java_engine/plugins/org.eclipse.gemoc.execution.sequential.javaengine/.project index 0c10230..f1bc942 100644 --- a/java_engine/plugins/org.eclipse.gemoc.execution.sequential.javaengine/.project +++ b/java_engine/plugins/org.eclipse.gemoc.execution.sequential.javaengine/.project @@ -25,8 +25,14 @@ + + org.eclipse.m2e.core.maven2Builder + + + + org.eclipse.m2e.core.maven2Nature org.eclipse.pde.PluginNature org.eclipse.jdt.core.javanature net.sf.eclipsecs.core.CheckstyleNature 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/plugins/org.eclipse.gemoc.execution.sequential.javaengine/src/org/eclipse/gemoc/execution/sequential/javaengine/PlainK3ExecutionEngine.java b/java_engine/plugins/org.eclipse.gemoc.execution.sequential.javaengine/src/org/eclipse/gemoc/execution/sequential/javaengine/PlainK3ExecutionEngine.java index 0cfb77b..04dfc58 100644 --- a/java_engine/plugins/org.eclipse.gemoc.execution.sequential.javaengine/src/org/eclipse/gemoc/execution/sequential/javaengine/PlainK3ExecutionEngine.java +++ b/java_engine/plugins/org.eclipse.gemoc.execution.sequential.javaengine/src/org/eclipse/gemoc/execution/sequential/javaengine/PlainK3ExecutionEngine.java @@ -26,8 +26,8 @@ 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.executionframework.engine.commons.GenericModelExecutionContext; import org.eclipse.gemoc.executionframework.engine.commons.K3DslHelper; +import org.eclipse.gemoc.executionframework.engine.commons.sequential.ISequentialModelExecutionContext; 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; @@ -54,7 +54,7 @@ * @author Didier Vojtisek * */ -public class PlainK3ExecutionEngine extends AbstractCommandBasedSequentialExecutionEngine, ISequentialRunConfiguration> +public class PlainK3ExecutionEngine extends AbstractCommandBasedSequentialExecutionEngine, ISequentialRunConfiguration> implements IStepManager { private Method initializeMethod; @@ -76,7 +76,7 @@ public String engineKindName() { * operation. */ @Override - protected void prepareEntryPoint(GenericModelExecutionContext executionContext) { + protected void prepareEntryPoint(ISequentialModelExecutionContext executionContext) { /* * Get info from the RunConfiguration */ @@ -94,12 +94,31 @@ protected void prepareEntryPoint(GenericModelExecutionContext findEntryPointClass(String aspectClassName) { + ISequentialModelExecutionContext executionContext = getExecutionContext(); Bundle bundle = findBundle(executionContext, aspectClassName); if (bundle == null) throw new RuntimeException("Could not find bundle for language \"" + executionContext.getRunConfiguration().getLanguageName() + "\""); - // search the class + Class entryPointClass; try { entryPointClass = bundle.loadClass(aspectClassName); } catch (ClassNotFoundException e) { @@ -109,28 +128,21 @@ protected void prepareEntryPoint(GenericModelExecutionContext(); - EObject root = executionContext.getResourceModel().getEObject(mainModelElementURI); + return entryPointClass; + } + + protected List findEntryPointMethodeParameters(EObject root) { + List entryPointMethodParameters = new ArrayList<>(); if (root instanceof EObjectAdapter) { entryPointMethodParameters.add(((EObjectAdapter) root).getAdaptee()); } else { entryPointMethodParameters.add(root); } - 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(); - Activator.error(msg, e); - throw new RuntimeException("Could not find method main with correct parameters."); - } + return entryPointMethodParameters; } @Override - protected void prepareInitializeModel(GenericModelExecutionContext executionContext) { + protected void prepareInitializeModel(ISequentialModelExecutionContext executionContext) { // try to get the initializeModelRunnable String modelInitializationMethodQName = executionContext.getRunConfiguration().getModelInitializationMethod(); @@ -320,7 +332,7 @@ public boolean canHandle(Object caller) { * * Return null if not found. */ - private Bundle findBundle(final GenericModelExecutionContext executionContext, String aspectClassName) { + private Bundle findBundle(final ISequentialModelExecutionContext executionContext, String aspectClassName) { // Look using JavaWorkspaceScope as this is safer and will look in // dependencies @@ -338,7 +350,8 @@ private Bundle findBundle(final GenericModelExecutionContext + + pomfirst + + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.m2e.core.maven2Nature + + diff --git a/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless.mep/.classpath b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless.mep/.classpath new file mode 100644 index 0000000..b919c55 --- /dev/null +++ b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless.mep/.classpath @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless.mep/.project b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless.mep/.project new file mode 100644 index 0000000..9e257bf --- /dev/null +++ b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless.mep/.project @@ -0,0 +1,40 @@ + + + org.eclipse.gemoc.execution.sequential.javaengine.headless.mep + + + + + + org.eclipse.xtext.ui.shared.xtextBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.xtext.ui.shared.xtextNature + org.eclipse.m2e.core.maven2Nature + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless.mep/.settings/org.eclipse.core.resources.prefs b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless.mep/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000..99f26c0 --- /dev/null +++ b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless.mep/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless.mep/.settings/org.eclipse.jdt.core.prefs b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless.mep/.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.mep/.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.mep/.settings/org.eclipse.m2e.core.prefs b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless.mep/.settings/org.eclipse.m2e.core.prefs new file mode 100644 index 0000000..f897a7f --- /dev/null +++ b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless.mep/.settings/org.eclipse.m2e.core.prefs @@ -0,0 +1,4 @@ +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 diff --git a/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless.mep/.settings/org.eclipse.xtend.core.Xtend.prefs b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless.mep/.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.mep/.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.mep/build.properties b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless.mep/build.properties new file mode 100644 index 0000000..34d2e4d --- /dev/null +++ b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless.mep/build.properties @@ -0,0 +1,4 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + . diff --git a/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless.mep/lib_not_correctly_deployed/org.eclipse.emf.transaction_1.9.1.201805140824.jar b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless.mep/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.mep/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.mep/pom.xml b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless.mep/pom.xml new file mode 100644 index 0000000..99fe491 --- /dev/null +++ b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless.mep/pom.xml @@ -0,0 +1,95 @@ + + 4.0.0 + org.eclipse.gemoc.execution.sequential.javaengine + org.eclipse.gemoc.execution.sequential.javaengine.headless.mep + + + 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 + + + + + org.eclipse.gemoc.executionframework + org.eclipse.gemoc.executionframework.mep + 1.0.0-SNAPSHOT + + + org.eclipse.gemoc.modeldebugging.framework.commons + org.eclipse.gemoc.xdsmlframework.api + 4.0.0-SNAPSHOT + + + org.eclipse.gemoc.pomfirst + org.eclipse.gemoc.executionframework.engine + 4.0.0-SNAPSHOT + + + org.eclipse.gemoc.execution.sequential.javaengine + org.eclipse.gemoc.execution.sequential.javaengine.headless + 1.0.0-SNAPSHOT + + + org.eclipse.gemoc.pomfirst + org.eclipse.gemoc.xdsmlframework.commons + 4.0.0-SNAPSHOT + + + 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 + + + fr.inria.diverse.k3.al + fr.inria.diverse.k3.al.annotationprocessor + 3.2.3-SNAPSHOT + + + + org.eclipse.gemoc.executionframework + org.eclipse.gemoc.executionframework.engine.headless + 1.0.0-SNAPSHOT + + + org.slf4j + slf4j-api + 1.7.30 + + + + + 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/ + + + \ No newline at end of file diff --git a/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless.mep/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/mep/HeadlessPlainK3ExecutionEngineMEP.java b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless.mep/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/mep/HeadlessPlainK3ExecutionEngineMEP.java new file mode 100644 index 0000000..130f010 --- /dev/null +++ b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless.mep/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/mep/HeadlessPlainK3ExecutionEngineMEP.java @@ -0,0 +1,298 @@ +package org.eclipse.gemoc.execution.sequential.javaengine.headless.mep; + +import java.io.EOFException; +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.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.StackFrame; +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.engine.headless.AbstractHeadlessExecutionContext; +import org.eclipse.gemoc.executionframework.engine.headless.HeadlessExecutionPlatform; +import org.eclipse.gemoc.executionframework.engine.headless.HeadlessExecutionWorkspace; +import org.eclipse.gemoc.executionframework.engine.headless.HeadlessJavaEngineSequentialRunConfiguration; +import org.eclipse.gemoc.executionframework.mep.engine.IMEPEngine; +import org.eclipse.gemoc.executionframework.mep.engine.IMEPEventListener; +import org.eclipse.gemoc.executionframework.mep.events.StoppedReason; +import org.eclipse.gemoc.executionframework.mep.launch.MEPLauncherParameters; +import org.eclipse.gemoc.executionframework.mep.types.SourceBreakpoint; +import org.eclipse.gemoc.executionframework.mep.types.Variable; +import org.eclipse.gemoc.xdsmlframework.api.core.ExecutionMode; +import org.eclipse.gemoc.xdsmlframework.api.extensions.languages.LanguageDefinitionExtension; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class HeadlessPlainK3ExecutionEngineMEP extends HeadlessPlainK3ExecutionEngine implements IMEPEngine { + private static final Logger LOGGER = LoggerFactory.getLogger("HeadlessPlainK3ExecutionEngineMEP"); + + Socket gemocServer = null; + ObjectInputStream gemocServerOutput = null; + ObjectOutputStream gemocServerInput = null; + List serverOutputBuffer = null; + Semaphore serverOutputBufferSem = null; + L languageDefinition = null; + ISequentialRunConfiguration runConfiguration = null; + + public HeadlessPlainK3ExecutionEngineMEP(L languageDefinition) { + this.languageDefinition = languageDefinition; + } + + @Override + public void internalLaunchEngine(MEPLauncherParameters launchParameters) { + Resource resourceModel = launchParameters.resourceModel; + String modelEntryPoint = launchParameters.modelEntryPoint; + String methodEntryPoint = launchParameters.methodEntryPoint; + String initializationMethod = launchParameters.initializationMethod; + String initializationMethodArgs = launchParameters.initializationMethodArgs; + + try { + LOGGER.info("START launchGemocEngine()"); + + 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(); + this.initialize(executioncontext); + + this.start(); + + 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()); + + final IMEPEngine currentEngine = this; + + 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) { + for (IMEPEventListener eventListener : mepEventListeners) { + eventListener.outputReceived(new org.eclipse.gemoc.executionframework.mep.events.Output(currentEngine, + ((OutputEvent) readData).output)); + } + } else if (readData instanceof StopEvent) { + for (IMEPEventListener eventListener : mepEventListeners) { + + eventListener.stopReceived(new org.eclipse.gemoc.executionframework.mep.events.Stopped(currentEngine, + engineToMepStopReason(((StopEvent) readData).stopReason))); + } + } else { + serverOutputBuffer.add(readData); + serverOutputBufferSem.release(); + } + } catch (EOFException e) { + readData = null; + } catch (ClassNotFoundException | IOException e) { + e.printStackTrace(); + break; + } + } while (readData != null); + } + }).start(); + } catch (Exception e) { + LOGGER.error(e.getMessage(), e); + } + } + + protected AbstractHeadlessExecutionContext newExecutionContext(Resource resourceModel) throws EngineContextException { + return new AbstractHeadlessExecutionContext( + runConfiguration, + ExecutionMode.Run, + languageDefinition, + new HeadlessExecutionWorkspace(), + new HeadlessExecutionPlatform()){ + @Override + public void initializeResourceModel() { + _resourceModel = resourceModel; + } + }; + } + + private StoppedReason engineToMepStopReason(StopReason engineStopReason) { + StoppedReason mepStoppedReason = null; + switch (engineStopReason) { + case REACHED_BREAKPOINT: + mepStoppedReason = StoppedReason.REACHED_BREAKPOINT; + break; + case REACHED_NEXT_LOGICAL_STEP: + mepStoppedReason = StoppedReason.REACHED_NEXT_LOGICAL_STEP; + break; + case REACHED_SIMULATION_END: + mepStoppedReason = StoppedReason.REACHED_SIMULATION_END; + break; + } + return mepStoppedReason; + } + + @Override + public void internalNext() { + internalDoStep(StepKind.NEXT); + } + + @Override + public void internalStepIn() { + internalDoStep(StepKind.STEP_IN); + } + + @Override + public 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); + for (IMEPEventListener eventListener : mepEventListeners) { + eventListener.stopReceived(new org.eclipse.gemoc.executionframework.mep.events.Stopped(this, + engineToMepStopReason(((StopCondition) output).stopReason))); + } + } catch (IOException | InterruptedException e) { + e.printStackTrace(); + } + } + + @Override + public void internalSetBreakpoints(SourceBreakpoint[] breakpoints) { + ClearBreakpointsCommand clearCommand = new ClearBreakpointsCommand(); + ToggleBreakpointCommand toggleCommand; + try { + gemocServerInput.writeObject(clearCommand); + for (SourceBreakpoint bp : breakpoints) { + toggleCommand = new ToggleBreakpointCommand(); + toggleCommand.line = (int) bp.getLine(); + gemocServerInput.writeObject(toggleCommand); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + @Override + public void internalTerminate() { + this.stop(); + StopCommand stopCommand = new StopCommand(); + try { + gemocServerInput.writeObject(stopCommand); + serverOutputBufferSem.acquire(); + serverOutputBuffer.remove(0); + gemocServer.close(); + } catch (IOException | InterruptedException e) { + e.printStackTrace(); + } + } + + @Override + public void internalContinue() { + ContinueCommand command = new ContinueCommand(); + try { + gemocServerInput.writeObject(command); + } catch (IOException e) { + e.printStackTrace(); + } + } + + @Override + public 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++) { + String name = variableNames.get(i); + GetVariableCommand variableCommand = new GetVariableCommand(); + variableCommand.variableQualifiedName = variableNames.get(i); + gemocServerInput.writeObject(variableCommand); + serverOutputBufferSem.acquire(); + String value = (String) serverOutputBuffer.remove(0); + variables[i] = new Variable(name, value); + } + return variables; + } catch (IOException | InterruptedException e) { + e.printStackTrace(); + return new Variable[0]; + } + } + + @Override + public org.eclipse.gemoc.executionframework.mep.types.StackFrame[] internalStackTrace() { + List gemocFrames = + this.getStackTrace(); + org.eclipse.gemoc.executionframework.mep.types.StackFrame[] mepFrames = + new org.eclipse.gemoc.executionframework.mep.types.StackFrame[gemocFrames.size()]; + for (int i = 0; i < gemocFrames.size(); i++) { + mepFrames[i] = new org.eclipse.gemoc.executionframework.mep.types.StackFrame((long) i, + gemocFrames.get(i).getName(), (long) gemocFrames.get(i).getLine(), 0L); + } + return mepFrames; + } + + @Override + public String internalSource() { + return this.getSourceContent(); + } + + private List mepEventListeners = new ArrayList<>(); + + @Override + public void addMEPEventListener(IMEPEventListener listener) { + this.mepEventListeners.add(listener); + } + + @Override + public void removeMEPEventListener(IMEPEventListener listener) { + this.mepEventListeners.remove(listener); + } + + @Override + public void removeAllMEPEventListeners() { + this.mepEventListeners.clear(); + } +} 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..5c91839 --- /dev/null +++ b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/pom.xml @@ -0,0 +1,189 @@ + + 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.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.executionframework.engine + 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 + + + org.eclipse.gemoc.executionframework + org.eclipse.gemoc.executionframework.engine.headless + 1.0.0-SNAPSHOT + + + + + 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/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/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..233994e --- /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,779 @@ +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.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.StackFrame; +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.executionframework.engine.headless.AbstractHeadlessExecutionContext; +import org.eclipse.gemoc.executionframework.engine.headless.FakeOSGI; +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 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 + FakeOSGI.start(); + + + /* 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")); + } + } + } + + /** + * 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; + } + + // 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); + } + System.out.println("wait for a new command."); + } while(!simulationEnded); + + solverThread.join(); + + if (stopReceived) { + cout.writeObject(Boolean.TRUE); + } + clientSocket.close(); + 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/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/StackFrame.java b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/commands/StackFrame.java new file mode 100644 index 0000000..81da0a3 --- /dev/null +++ b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.headless/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/headless/commands/StackFrame.java @@ -0,0 +1,24 @@ +package org.eclipse.gemoc.execution.sequential.javaengine.headless.commands; + +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/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..999bfd5 --- /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,9 @@ +package org.eclipse.gemoc.execution.sequential.javaengine.headless.commands; + +import java.io.Serializable; + +public enum StopReason implements Serializable { + REACHED_BREAKPOINT, + REACHED_NEXT_LOGICAL_STEP, + REACHED_SIMULATION_END; +} 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/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/org.eclipse.gemoc.execution.sequential.javaengine.mep/.classpath b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.mep/.classpath new file mode 100644 index 0000000..f88bdce --- /dev/null +++ b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.mep/.classpath @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.mep/.project b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.mep/.project new file mode 100644 index 0000000..d757669 --- /dev/null +++ b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.mep/.project @@ -0,0 +1,40 @@ + + + org.eclipse.gemoc.execution.sequential.javaengine.mep + + + + + + org.eclipse.xtext.ui.shared.xtextBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.xtext.ui.shared.xtextNature + org.eclipse.m2e.core.maven2Nature + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.mep/.settings/org.eclipse.core.resources.prefs b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.mep/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000..e9441bb --- /dev/null +++ b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.mep/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,3 @@ +eclipse.preferences.version=1 +encoding//src/main/java=UTF-8 +encoding/=UTF-8 diff --git a/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.mep/.settings/org.eclipse.jdt.core.prefs b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.mep/.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.mep/.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.mep/.settings/org.eclipse.m2e.core.prefs b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.mep/.settings/org.eclipse.m2e.core.prefs new file mode 100644 index 0000000..f897a7f --- /dev/null +++ b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.mep/.settings/org.eclipse.m2e.core.prefs @@ -0,0 +1,4 @@ +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 diff --git a/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.mep/.settings/org.eclipse.xtend.core.Xtend.prefs b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.mep/.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.mep/.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.mep/build.properties b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.mep/build.properties new file mode 100644 index 0000000..34d2e4d --- /dev/null +++ b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.mep/build.properties @@ -0,0 +1,4 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + . diff --git a/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.mep/lib_not_correctly_deployed/org.eclipse.emf.compare_3.5.2.201805161152.jar b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.mep/lib_not_correctly_deployed/org.eclipse.emf.compare_3.5.2.201805161152.jar new file mode 100644 index 0000000..3384a5c Binary files /dev/null and b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.mep/lib_not_correctly_deployed/org.eclipse.emf.compare_3.5.2.201805161152.jar differ diff --git a/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.mep/lib_not_correctly_deployed/org.eclipse.emf.transaction_1.9.1.201805140824.jar b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.mep/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.mep/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.mep/pom.xml b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.mep/pom.xml new file mode 100644 index 0000000..56f4472 --- /dev/null +++ b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.mep/pom.xml @@ -0,0 +1,124 @@ + + 4.0.0 + org.eclipse.gemoc.execution.sequential.javaengine + org.eclipse.gemoc.execution.sequential.javaengine.mep + + + 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 + + + + + org.eclipse.gemoc.pomfirst + org.eclipse.gemoc.commons.utils + 1.0.0-SNAPSHOT + + + org.eclipse.gemoc.executionframework + org.eclipse.gemoc.executionframework.mep + 1.0.0-SNAPSHOT + + + DSLDebugger + org.eclipse.gemoc.dsl.debug.ide + 3.0.1-SNAPSHOT + + + org.eclipse.gemoc.modeldebugging.framework.commons + org.eclipse.gemoc.xdsmlframework.api + 4.0.0-SNAPSHOT + + + org.eclipse.gemoc.pomfirst + org.eclipse.gemoc.executionframework.engine + 4.0.0-SNAPSHOT + + + org.eclipse.gemoc.pomfirst + org.eclipse.gemoc.executionframework.debugger + 4.0.0-SNAPSHOT + + + org.eclipse.gemoc.pomfirst + org.eclipse.gemoc.execution.sequential.javaengine + 4.0.0-SNAPSHOT + + + org.eclipse.emf + org.eclipse.emf.compare + 3.5.2.201805161152 + system + ${basedir}/lib_not_correctly_deployed/org.eclipse.emf.compare_3.5.2.201805161152.jar + + + 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 + + + fr.inria.diverse.k3.al + fr.inria.diverse.k3.al.annotationprocessor + 3.2.3-SNAPSHOT + + + org.eclipse.gemoc.executionframework + org.eclipse.gemoc.executionframework.engine.headless + 1.0.0-SNAPSHOT + + + org.eclipse.gemoc.multidimensional_trace_management + org.eclipse.gemoc.trace.gemoc + 3.0.1-SNAPSHOT + + + org.emfjson + emfjson-jackson + 1.3.0 + + + + + com.fasterxml.jackson.core + jackson-core + 2.12.1 + + + + + + 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/ + + + \ No newline at end of file diff --git a/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.mep/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/mep/HeadlessDebugEventHandler.java b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.mep/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/mep/HeadlessDebugEventHandler.java new file mode 100644 index 0000000..3acf9e7 --- /dev/null +++ b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.mep/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/mep/HeadlessDebugEventHandler.java @@ -0,0 +1,37 @@ +package org.eclipse.gemoc.execution.sequential.javaengine.mep; + +import java.util.concurrent.Semaphore; + +import org.eclipse.gemoc.dsl.debug.ide.event.IDSLDebugEvent; +import org.eclipse.gemoc.dsl.debug.ide.event.IDSLDebugEventProcessor; +import org.eclipse.gemoc.dsl.debug.ide.event.debugger.BreakpointReply; +import org.eclipse.gemoc.dsl.debug.ide.event.debugger.SetCurrentInstructionReply; +import org.eclipse.gemoc.dsl.debug.ide.event.debugger.SpawnRunningThreadReply; +import org.eclipse.gemoc.dsl.debug.ide.event.debugger.TerminatedReply; + +public class HeadlessDebugEventHandler implements IDSLDebugEventProcessor { + + private volatile Semaphore breakReached; + + public HeadlessDebugEventHandler() { + this.breakReached = new Semaphore(0); + } + + @Override + public Object handleEvent(IDSLDebugEvent event) { + if (event instanceof BreakpointReply || event instanceof TerminatedReply) { + breakReached.release(); + } + System.err.println(" Debug event: " + event.toString()); + return null; + } + + public void waitBreakReached() throws InterruptedException { + this.breakReached.acquire(); + } + + public void clearPermits() { + this.breakReached.drainPermits(); + } + +} diff --git a/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.mep/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/mep/HeadlessGenericSequentialModelDebugger.java b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.mep/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/mep/HeadlessGenericSequentialModelDebugger.java new file mode 100644 index 0000000..f0b515b --- /dev/null +++ b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.mep/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/mep/HeadlessGenericSequentialModelDebugger.java @@ -0,0 +1,24 @@ +package org.eclipse.gemoc.execution.sequential.javaengine.mep; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.gemoc.dsl.debug.ide.event.IDSLDebugEventProcessor; +import org.eclipse.gemoc.executionframework.debugger.GenericSequentialModelDebugger; +import org.eclipse.gemoc.xdsmlframework.api.core.IExecutionEngine; + +public class HeadlessGenericSequentialModelDebugger extends GenericSequentialModelDebugger implements IHeadlessGemocDebugger { + + public HeadlessGenericSequentialModelDebugger(IDSLDebugEventProcessor target, IExecutionEngine engine) { + super(target, engine); + } + + @Override + public String getThreadName() { + return threadName; + } + + @Override + public EObject getCurrentInstruction() { + return currentInstructions.get(threadName); + } + +} diff --git a/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.mep/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/mep/HeadlessOmniscientGenericSequentialModelDebugger.java b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.mep/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/mep/HeadlessOmniscientGenericSequentialModelDebugger.java new file mode 100644 index 0000000..cbbb3c1 --- /dev/null +++ b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.mep/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/mep/HeadlessOmniscientGenericSequentialModelDebugger.java @@ -0,0 +1,47 @@ +package org.eclipse.gemoc.execution.sequential.javaengine.mep; + +import java.util.Set; +import java.util.function.Supplier; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.gemoc.dsl.debug.ide.event.IDSLDebugEventProcessor; +import org.eclipse.gemoc.executionframework.debugger.Activator; +import org.eclipse.gemoc.executionframework.debugger.OmniscientGenericSequentialModelDebugger; +import org.eclipse.gemoc.trace.gemoc.api.IMultiDimensionalTraceAddon; +import org.eclipse.gemoc.trace.gemoc.api.ITraceViewNotifier; +import org.eclipse.gemoc.xdsmlframework.api.core.IExecutionEngine; + +public class HeadlessOmniscientGenericSequentialModelDebugger extends OmniscientGenericSequentialModelDebugger implements IHeadlessGemocDebugger { + + public HeadlessOmniscientGenericSequentialModelDebugger(IDSLDebugEventProcessor target, IExecutionEngine engine) { + super(target, engine); + } + + @Override + public String getThreadName() { + return threadName; + } + + @Override + public EObject getCurrentInstruction() { + return currentInstructions.get(threadName); + } + + @Override + public void engineStarted(final IExecutionEngine executionEngine) { + final Activator activator = Activator.getDefault(); + final Supplier _function = () -> { + return this; + }; + activator.setDebuggerSupplier(_function); + super.engineStarted(executionEngine); + final Set traceAddons = executionEngine.getAddonsTypedBy(IMultiDimensionalTraceAddon.class); + final IMultiDimensionalTraceAddon traceAddon = traceAddons.iterator().next(); + this.traceExplorer = traceAddon.getTraceExplorer(); + final ITraceViewNotifier.TraceViewCommand _function_1 = () -> { + this.update(); + }; + this.traceExplorer.registerCommand(this, _function_1); + } + +} diff --git a/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.mep/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/mep/IHeadlessGemocDebugger.java b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.mep/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/mep/IHeadlessGemocDebugger.java new file mode 100644 index 0000000..f2771ba --- /dev/null +++ b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.mep/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/mep/IHeadlessGemocDebugger.java @@ -0,0 +1,27 @@ +package org.eclipse.gemoc.execution.sequential.javaengine.mep; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.gemoc.dsl.debug.ide.event.IDSLDebugEvent; +import org.eclipse.gemoc.executionframework.debugger.IGemocDebugger; + +public interface IHeadlessGemocDebugger extends IGemocDebugger { + + String getThreadName(); + + EObject getCurrentInstruction(); + + void stepReturn(String threadName); + + Object handleEvent(IDSLDebugEvent event); + + void stepOver(String threadName); + + void stepInto(String threadName); + + boolean isTerminated(); + + void terminate(); + + void resume(); + +} diff --git a/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.mep/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/mep/PlainK3ExecutionEngineMEP.java b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.mep/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/mep/PlainK3ExecutionEngineMEP.java new file mode 100644 index 0000000..7949b3d --- /dev/null +++ b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.mep/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/mep/PlainK3ExecutionEngineMEP.java @@ -0,0 +1,312 @@ +package org.eclipse.gemoc.execution.sequential.javaengine.mep; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.function.BiPredicate; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.gemoc.commons.utils.ModelAwarePrintStream; +import org.eclipse.gemoc.dsl.debug.ide.event.model.StartRequest; +import org.eclipse.gemoc.execution.sequential.javaengine.PlainK3ExecutionEngine; +import org.eclipse.gemoc.executionframework.engine.headless.AbstractSequentialHeadlessExecutionContext; +import org.eclipse.gemoc.executionframework.engine.headless.HeadlessExecutionPlatform; +import org.eclipse.gemoc.executionframework.engine.headless.HeadlessExecutionWorkspace; +import org.eclipse.gemoc.executionframework.engine.headless.HeadlessJavaEngineSequentialRunConfiguration; +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.EngineContextException; +import org.eclipse.gemoc.executionframework.engine.commons.sequential.ISequentialRunConfiguration; +import org.eclipse.gemoc.executionframework.engine.headless.FakeOSGI; +import org.eclipse.gemoc.executionframework.mep.engine.IMEPEngine; +import org.eclipse.gemoc.executionframework.mep.engine.IMEPEventListener; +import org.eclipse.gemoc.executionframework.mep.events.Output; +import org.eclipse.gemoc.executionframework.mep.events.Stopped; +import org.eclipse.gemoc.executionframework.mep.events.StoppedReason; +import org.eclipse.gemoc.executionframework.mep.launch.MEPLauncherParameters; +import org.eclipse.gemoc.executionframework.mep.types.SourceBreakpoint; +import org.eclipse.gemoc.executionframework.mep.types.StackFrame; +import org.eclipse.gemoc.executionframework.mep.types.Variable; +import org.eclipse.gemoc.trace.commons.model.trace.Step; +import org.eclipse.gemoc.trace.gemoc.traceaddon.GenericTraceEngineAddon; +import org.eclipse.gemoc.xdsmlframework.api.core.ExecutionMode; +import org.eclipse.gemoc.xdsmlframework.api.core.IExecutionEngine; +import org.eclipse.gemoc.xdsmlframework.api.extensions.languages.LanguageDefinitionExtension; +import org.eclipse.xtext.nodemodel.ICompositeNode; +import org.eclipse.xtext.nodemodel.util.NodeModelUtils; + + +public class PlainK3ExecutionEngineMEP extends PlainK3ExecutionEngine implements IMEPEngine { + + ISequentialRunConfiguration runConfiguration = null; + L languageDefinition; + IHeadlessGemocDebugger modelDebugger = null; + HeadlessDebugEventHandler debugEventHandler = null; + AbstractSequentialHeadlessExecutionContext executionContext = null; + IDynamicPartAccessor partAccessor = null; + + private PrintStream baseStream; + private ModelAwarePrintStream modelPrintStream; + + public PlainK3ExecutionEngineMEP(L languageDefinition) { + this.languageDefinition = languageDefinition; + } + + @Override + public IHeadlessGemocDebugger getDebugger() { + return this.modelDebugger; + } + + @Override + protected Class findEntryPointClass(String aspectClassName) { + Class entryPointClass; + try { + entryPointClass = Thread.currentThread().getContextClassLoader().loadClass(aspectClassName); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + throw new RuntimeException( + "Could not find class " + getExecutionContext().getRunConfiguration().getExecutionEntryPoint() + ); + } + return entryPointClass; + } + + @Override + protected List findEntryPointMethodeParameters(EObject root) { + List entryPointMethodParameters = new ArrayList<>(); + entryPointMethodParameters.add(root); + return entryPointMethodParameters; + } + + private GenericTraceEngineAddon traceAddon; + public void setTraceAddon(GenericTraceEngineAddon traceAddon) { + this.traceAddon = traceAddon; + } + @Override + public void internalLaunchEngine(MEPLauncherParameters launchParameters) { + Resource resourceModel = launchParameters.resourceModel; + String languageName = launchParameters.languageName; + String modelEntryPoint = launchParameters.modelEntryPoint; + String methodEntryPoint = launchParameters.methodEntryPoint; + String initializationMethod = launchParameters.initializationMethod; + String initializationMethodArgs = launchParameters.initializationMethodArgs; + + runConfiguration = new HeadlessJavaEngineSequentialRunConfiguration(resourceModel.getURI(), languageName, + modelEntryPoint, methodEntryPoint, initializationMethod, initializationMethodArgs); + + try { + executionContext = newExecutionContext(resourceModel); + executionContext.initializeResourceModel(); + + FakeOSGI.start(); + org.eclipse.emf.transaction.TransactionalEditingDomain.Factory.INSTANCE.createEditingDomain(resourceModel.getResourceSet()); + + this.initialize(executionContext); + + debugEventHandler = new HeadlessDebugEventHandler(); + if (traceAddon != null) { + executionContext.getExecutionPlatform().addEngineAddon(traceAddon); + modelDebugger = new HeadlessOmniscientGenericSequentialModelDebugger(debugEventHandler, this); + } else { + modelDebugger = new HeadlessGenericSequentialModelDebugger(debugEventHandler, this); + } + + executionContext.getExecutionPlatform().addEngineAddon(modelDebugger); + partAccessor = new DefaultDynamicPartAccessor(); + + // break on start + modelDebugger.addPredicateBreak(new BiPredicate, Step>() { + @Override + public boolean test(IExecutionEngine t, Step u) { + return true; + } + }); + + modelDebugger.handleEvent(new StartRequest()); + } catch (EngineContextException e) { + e.printStackTrace(); + } + } + + @Override + protected void notifyEngineAboutToStart() { + super.notifyEngineAboutToStart(); + + final IMEPEngine engine = this; + ByteArrayOutputStream modelOutputStream = 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) { + Output outputEvent = new Output(engine, new String(Arrays.copyOfRange(b, off, len))); + notifyListeners(outputEvent); + } + }; + baseStream = System.out; + modelPrintStream = new ModelAwarePrintStream(modelOutputStream, baseStream); + modelPrintStream.registerModelExecutionThread(thread); + System.setOut(modelPrintStream); + } + + protected AbstractSequentialHeadlessExecutionContext newExecutionContext(Resource resourceModel) throws EngineContextException { + return new AbstractSequentialHeadlessExecutionContext( + runConfiguration, + ExecutionMode.Run, + languageDefinition, + new HeadlessExecutionWorkspace(), + new HeadlessExecutionPlatform()){ + @Override + public void initializeResourceModel() { + _resourceModel = resourceModel; + } + }; + } + + @Override + public void internalNext() { + modelDebugger.stepOver(modelDebugger.getThreadName()); + manageAfterStep(); + } + + @Override + public void internalStepIn() { + modelDebugger.stepInto(modelDebugger.getThreadName()); + manageAfterStep(); + } + + @Override + public void internalStepOut() { + modelDebugger.stepReturn(modelDebugger.getThreadName()); + manageAfterStep(); + } + + private void manageAfterStep() { + if (modelDebugger.isTerminated()) { + System.setOut(baseStream); + notifyListeners(new Stopped(this, StoppedReason.REACHED_SIMULATION_END)); + } else { + notifyListeners(new Stopped(this, StoppedReason.REACHED_NEXT_LOGICAL_STEP)); + } + } + + @Override + public void internalSetBreakpoints(SourceBreakpoint[] breakpoints) { + // TODO Clear existing breakpoints + for (SourceBreakpoint bp : breakpoints) { + modelDebugger.addPredicateBreakpoint(new BiPredicate, Step>() { + @Override + public boolean test(IExecutionEngine t, Step u) { + return NodeModelUtils.getNode(u.getMseoccurrence().getMse().getCaller()).getStartLine() == bp.getLine(); + } + }); + } + } + + @Override + public void internalTerminate() { + System.setOut(baseStream); + modelDebugger.terminate(); + } + + @Override + public void internalContinue() { + final PlainK3ExecutionEngine engine = this; + new Thread(new Runnable() { + @Override + public void run() { + try { + debugEventHandler.waitBreakReached(); + if (modelDebugger.isTerminated()) { + System.setOut(baseStream); + notifyListeners(new Stopped(engine, StoppedReason.REACHED_SIMULATION_END)); + } else { + notifyListeners(new Stopped(engine, StoppedReason.REACHED_NEXT_LOGICAL_STEP)); + } + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + }).start(); + debugEventHandler.clearPermits(); + modelDebugger.resume(); + } + + @Override + public Variable[] internalVariables() { + EObject rootElement = executionContext.getResourceModel().getEObject( + executionContext.getRunConfiguration().getModelEntryPoint()); + List variables = new ArrayList<>(); + for (MutableField mf : partAccessor.extractMutableField(rootElement)) { + variables.add(new Variable(mf.getName(), mf.getValue() == null ? "null" : mf.getValue().toString())); + } + return variables.toArray(new Variable[0]); + } + + @Override + public StackFrame[] internalStackTrace() { + EObject eObj = modelDebugger.getCurrentInstruction(); + List mepFrames = new ArrayList(); + long i = 0L; + while (eObj != null) { + ICompositeNode node = NodeModelUtils.getNode(eObj); + StackFrame frame = new StackFrame(i++, eObj.toString(), (long) node.getStartLine(), 0L); + mepFrames.add(frame); + eObj = eObj.eContainer(); + } + return mepFrames.toArray(new StackFrame[0]); + } + + @Override + public String internalSource() { + EObject rootElement = executionContext.getResourceModel().getEObject( + executionContext.getRunConfiguration().getModelEntryPoint()); + return NodeModelUtils.getNode(rootElement).getText(); + } + + private List mepEventListeners = new ArrayList<>(); + + @Override + public void addMEPEventListener(IMEPEventListener listener) { + mepEventListeners.add(listener); + } + + @Override + public void removeMEPEventListener(IMEPEventListener listener) { + mepEventListeners.remove(listener); + } + + @Override + public void removeAllMEPEventListeners() { + mepEventListeners.clear(); + } + + private void notifyListeners(Stopped event) { + new Thread(new Runnable() { + @Override + public void run() { + for (IMEPEventListener eventListener : mepEventListeners) { + eventListener.stopReceived(event); + } + } + }).start(); + } + + private void notifyListeners(Output event) { + new Thread(new Runnable() { + @Override + public void run() { + for (IMEPEventListener eventListener : mepEventListeners) { + eventListener.outputReceived(event); + } + } + }).start(); + } + +} diff --git a/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.mep/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/mep/RemoteTraceExplorer.java b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.mep/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/mep/RemoteTraceExplorer.java new file mode 100644 index 0000000..6a730f5 --- /dev/null +++ b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.mep/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/mep/RemoteTraceExplorer.java @@ -0,0 +1,43 @@ +package org.eclipse.gemoc.execution.sequential.javaengine.mep; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.gemoc.executionframework.mep.trace.IRemoteTraceExplorer; +import org.eclipse.gemoc.executionframework.mep.trace.ITraceExplorerEventListener; +import org.eclipse.gemoc.trace.commons.model.trace.Step; +import org.eclipse.gemoc.trace.gemoc.traceaddon.GenericTraceExplorer; + +public class RemoteTraceExplorer extends GenericTraceExplorer implements IRemoteTraceExplorer { + + public RemoteTraceExplorer() { + super(null, null); + } + + + private List traceExplorerEventListeners = new ArrayList<>(); + + @Override + public void addTraceExplorerEventListener(ITraceExplorerEventListener listener) { + traceExplorerEventListeners.add(listener); + } + + @Override + public void removeTraceExplorerEventListener(ITraceExplorerEventListener listener) { + traceExplorerEventListeners.remove(listener); + } + + @Override + public void removeAllTraceExplorerEventListeners() { + traceExplorerEventListeners.clear(); + } + + @Override + public void updateCallStack(Step step) { + super.updateCallStack(step); + for (ITraceExplorerEventListener listener : traceExplorerEventListeners) { + listener.updatedCallStack(); + } + } + +} diff --git a/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.mep/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/mep/RemoteTraceManagerAddon.java b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.mep/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/mep/RemoteTraceManagerAddon.java new file mode 100644 index 0000000..ea5ece7 --- /dev/null +++ b/java_engine/pomfirst/org.eclipse.gemoc.execution.sequential.javaengine.mep/src/main/java/org/eclipse/gemoc/execution/sequential/javaengine/mep/RemoteTraceManagerAddon.java @@ -0,0 +1,109 @@ +package org.eclipse.gemoc.execution.sequential.javaengine.mep; + + +import java.util.Collections; + +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.ecore.xmi.impl.XMIResourceFactoryImpl; +import org.eclipse.emf.transaction.TransactionalEditingDomain; +import org.eclipse.emf.transaction.util.TransactionUtil; +import org.eclipse.gemoc.commons.eclipse.emf.EMFResource; +import org.eclipse.gemoc.executionframework.mep.trace.IRemoteTraceAddon; +import org.eclipse.gemoc.trace.commons.model.launchconfiguration.LaunchConfiguration; +import org.eclipse.gemoc.trace.commons.model.trace.Dimension; +import org.eclipse.gemoc.trace.commons.model.trace.State; +import org.eclipse.gemoc.trace.commons.model.trace.Step; +import org.eclipse.gemoc.trace.commons.model.trace.Trace; +import org.eclipse.gemoc.trace.commons.model.trace.TracedObject; +import org.eclipse.gemoc.trace.commons.model.trace.Value; +import org.eclipse.gemoc.trace.gemoc.api.IStateManager; +import org.eclipse.gemoc.trace.gemoc.api.ITraceExplorer; +import org.eclipse.gemoc.trace.gemoc.traceaddon.GenericTraceEngineAddon; +import org.eclipse.gemoc.trace.gemoc.traceaddon.GenericTraceExtractor; +import org.eclipse.gemoc.trace.gemoc.traceaddon.GenericTraceNotifier; +import org.eclipse.gemoc.xdsmlframework.api.core.IExecutionContext; +import org.eclipse.gemoc.xdsmlframework.api.engine_addon.modelchangelistener.BatchModelChangeListener; + +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; + +public class RemoteTraceManagerAddon extends GenericTraceEngineAddon implements IRemoteTraceAddon { + + @Override + public void engineAboutToStart(IExecutionContext context) { + if (_executionContext == null) { + _executionContext = context; + + // load addon options from the execution context + this.activateUpdateEquivalenceClasses = false; + + Resource modelResource = _executionContext.getResourceModel(); + + // Creating the resource of the trace + // val ResourceSet rs = modelResource.getResourceSet() + ResourceSet rs = new ResourceSetImpl(); + + // We check whether or not we need transactions + TransactionalEditingDomain ed = TransactionUtil.getEditingDomain(rs); + needTransaction = ed != null; + + if (!rs.getResourceFactoryRegistry().getExtensionToFactoryMap().containsKey("trace")) { + rs.getResourceFactoryRegistry().getExtensionToFactoryMap().put("trace", new XMIResourceFactoryImpl()); + } + + URI traceModelURI = URI.createPlatformResourceURI("execution.trace", false); + Resource traceResource = rs.createResource(traceModelURI); + + // We construct a new listener addon if required + this.listenerAddon = new BatchModelChangeListener(Collections.singleton(_executionContext.getResourceModel())); + listenerAddon.registerObserver(this); + + LaunchConfiguration launchConfiguration = null; + + BiMap> exeToTraced = HashBiMap.create(); + + // We construct the trace constructor, using the concrete generated method + traceConstructor = constructTraceConstructor(modelResource, traceResource, exeToTraced); + + // We initialize the trace + modifyTrace(new Runnable() { + public void run() { + traceConstructor.initTrace(launchConfiguration); + }; + }); + + // And we enable trace exploration by loading it in a new trace explorer + EObject root = traceResource.getContents().get(0); + if (root instanceof Trace) { + trace = (Trace, TracedObject, State>) root; + IStateManager> stateManager = constructStateManager(modelResource, exeToTraced.inverse()); + traceExplorer.loadTrace(trace, stateManager); + traceExtractor = new GenericTraceExtractor(trace, activateUpdateEquivalenceClasses); + traceListener = new BatchModelChangeListener(EMFResource.getRelatedResources(traceResource)); + traceNotifier = new GenericTraceNotifier(traceListener); + traceNotifier.addListener(traceExtractor); + traceNotifier.addListener(traceExplorer); + } + } + } + + @Override + public void aboutToExecuteStep(Step step) { + manageStep(step, true); + } + + @Override + public void stepExecuted(Step step) { + manageStep(step, false); + } + + @Override + public void setTraceExplorer(ITraceExplorer, State, TracedObject, Dimension, Value> traceExplorer) { + this.traceExplorer = traceExplorer; + } + +} diff --git a/java_engine/pomfirst/pom.xml b/java_engine/pomfirst/pom.xml new file mode 100644 index 0000000..5eb31d0 --- /dev/null +++ b/java_engine/pomfirst/pom.xml @@ -0,0 +1,86 @@ + + + 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.gemoc.execution.sequential.javaengine.headless.mep + org.eclipse.gemoc.execution.sequential.javaengine.mep + + + + + + + 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/java_xdsml/plugins/org.eclipse.gemoc.execution.sequential.javaxdsml.ide.ui/.project b/java_xdsml/plugins/org.eclipse.gemoc.execution.sequential.javaxdsml.ide.ui/.project index 02b8431..bc73c1a 100644 --- a/java_xdsml/plugins/org.eclipse.gemoc.execution.sequential.javaxdsml.ide.ui/.project +++ b/java_xdsml/plugins/org.eclipse.gemoc.execution.sequential.javaxdsml.ide.ui/.project @@ -30,8 +30,14 @@ + + org.eclipse.m2e.core.maven2Builder + + + + org.eclipse.m2e.core.maven2Nature org.eclipse.jdt.core.javanature org.eclipse.pde.PluginNature org.eclipse.xtext.ui.shared.xtextNature diff --git a/java_xdsml/plugins/org.eclipse.gemoc.execution.sequential.javaxdsml.ide.ui/src/org/eclipse/gemoc/execution/sequential/javaxdsml/ide/ui/wizards/CreateNewGemocSequentialLanguageProject.java b/java_xdsml/plugins/org.eclipse.gemoc.execution.sequential.javaxdsml.ide.ui/src/org/eclipse/gemoc/execution/sequential/javaxdsml/ide/ui/wizards/CreateNewGemocSequentialLanguageProject.java index 524926c..7e235de 100644 --- a/java_xdsml/plugins/org.eclipse.gemoc.execution.sequential.javaxdsml.ide.ui/src/org/eclipse/gemoc/execution/sequential/javaxdsml/ide/ui/wizards/CreateNewGemocSequentialLanguageProject.java +++ b/java_xdsml/plugins/org.eclipse.gemoc.execution.sequential.javaxdsml.ide.ui/src/org/eclipse/gemoc/execution/sequential/javaxdsml/ide/ui/wizards/CreateNewGemocSequentialLanguageProject.java @@ -176,8 +176,8 @@ private void updateManifestFile (IProject project, IProgressMonitor monitor) { try { ManifestChanger manifestChanger = new ManifestChanger(project.getFile("META-INF/MANIFEST.MF")); - manifestChanger.addPluginDependency("org.eclipse.xtend.lib", "2.14.0", false, true); - manifestChanger.addPluginDependency("org.eclipse.xtext.xbase.lib", "2.14.0", false, true); + manifestChanger.addPluginDependency("org.eclipse.xtend.lib", "2.21.0", false, true); + manifestChanger.addPluginDependency("org.eclipse.xtext.xbase.lib", "2.21.0", false, true); manifestChanger.addPluginDependency("com.google.guava", "0.0.0", false, true); manifestChanger.addPluginDependency("org.eclipse.emf.ecore.xmi", "2.8.0", true, true); manifestChanger.addPluginDependency("org.eclipse.emf.ecore", "2.8.0", true, true); diff --git a/java_xdsml/plugins/org.eclipse.gemoc.execution.sequential.javaxdsml.metaprog/.project b/java_xdsml/plugins/org.eclipse.gemoc.execution.sequential.javaxdsml.metaprog/.project index 4b16fa6..fea4753 100644 --- a/java_xdsml/plugins/org.eclipse.gemoc.execution.sequential.javaxdsml.metaprog/.project +++ b/java_xdsml/plugins/org.eclipse.gemoc.execution.sequential.javaxdsml.metaprog/.project @@ -20,8 +20,14 @@ + + org.eclipse.m2e.core.maven2Builder + + + + org.eclipse.m2e.core.maven2Nature org.eclipse.pde.PluginNature org.eclipse.jdt.core.javanature diff --git a/java_xdsml/plugins/org.eclipse.gemoc.execution.sequential.javaxdsml.metaprog/plugin.xml b/java_xdsml/plugins/org.eclipse.gemoc.execution.sequential.javaxdsml.metaprog/plugin.xml index c0950ba..fb8fc57 100644 --- a/java_xdsml/plugins/org.eclipse.gemoc.execution.sequential.javaxdsml.metaprog/plugin.xml +++ b/java_xdsml/plugins/org.eclipse.gemoc.execution.sequential.javaxdsml.metaprog/plugin.xml @@ -4,8 +4,14 @@ + dependencies="org.eclipse.gemoc.metaprog.ecore" + name="org.eclipse.gemoc.metaprog.kermeta3"> + + diff --git a/java_xdsml/plugins/org.eclipse.gemoc.execution.sequential.javaxdsml.metaprog/src/org/eclipse/gemoc/execution/sequential/javaxdsml/ruleprovider/Kermeta3Rule.java b/java_xdsml/plugins/org.eclipse.gemoc.execution.sequential.javaxdsml.metaprog/src/org/eclipse/gemoc/execution/sequential/javaxdsml/ruleprovider/Kermeta3Rule.java new file mode 100644 index 0000000..a3b8940 --- /dev/null +++ b/java_xdsml/plugins/org.eclipse.gemoc.execution.sequential.javaxdsml.metaprog/src/org/eclipse/gemoc/execution/sequential/javaxdsml/ruleprovider/Kermeta3Rule.java @@ -0,0 +1,22 @@ +package org.eclipse.gemoc.execution.sequential.javaxdsml.ruleprovider; + +import org.eclipse.gemoc.dsl.Entry; +import org.eclipse.gemoc.xdsmlframework.api.extensions.metaprog.ILanguageComponentValidator; +import org.eclipse.gemoc.xdsmlframework.api.extensions.metaprog.Message; +import org.eclipse.gemoc.xdsmlframework.api.extensions.metaprog.Severity; +import org.eclipse.gemoc.xdsmlframework.extensions.kermeta3.Kermeta3RuleHelper; + +public class Kermeta3Rule implements ILanguageComponentValidator { + + private Kermeta3RuleHelper k3Helper = new Kermeta3RuleHelper(true); + + + @Override + public Message validate(Entry entry) { + if("k3".matches(entry.getKey())) { + return k3Helper.execute(entry.getValue(), entry.eResource().getURI()); + } + return(new Message("", Severity.DEFAULT)); + } + +} diff --git a/java_xdsml/plugins/org.eclipse.gemoc.execution.sequential.javaxdsml.metaprog/src/org/eclipse/gemoc/execution/sequential/javaxdsml/ruleprovider/Kermeta3RuleProvider.java b/java_xdsml/plugins/org.eclipse.gemoc.execution.sequential.javaxdsml.metaprog/src/org/eclipse/gemoc/execution/sequential/javaxdsml/ruleprovider/Kermeta3RuleProvider.java deleted file mode 100644 index a834311..0000000 --- a/java_xdsml/plugins/org.eclipse.gemoc.execution.sequential.javaxdsml.metaprog/src/org/eclipse/gemoc/execution/sequential/javaxdsml/ruleprovider/Kermeta3RuleProvider.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.eclipse.gemoc.execution.sequential.javaxdsml.ruleprovider; - -import java.util.Collection; -import java.util.HashSet; -import java.util.Set; - -import org.eclipse.gemoc.xdsmlframework.api.extensions.metaprog.IRule; -import org.eclipse.gemoc.xdsmlframework.api.extensions.metaprog.IRuleProvider; -import org.eclipse.gemoc.xdsmlframework.api.extensions.metaprog.EcoreRule; -import org.eclipse.gemoc.xdsmlframework.extensions.kermeta3.Kermeta3Rule; - - -/** - * RuleProvider used for the Kermeta3 meta-programming approach - * @author GUEGUEN Ronan - * - */ -public class Kermeta3RuleProvider implements IRuleProvider { - - private Set ruleSet = new HashSet(); - - /** - * Creates a RuleProvider for the Kermeta3 meta-programming approach, contains rules from the Ecore RuleProvider - */ - public Kermeta3RuleProvider() { - ruleSet.add(new EcoreRule()); - ruleSet.add(new Kermeta3Rule(true)); - } - - @Override - public Collection getValidationRules(){ - return ruleSet; - - } - -} diff --git a/pom.xml b/pom.xml index 6d62def..0cc3e00 100644 --- a/pom.xml +++ b/pom.xml @@ -10,18 +10,18 @@ pom - 1.5.1 - 2.14.0 + 1.7.0 + 2.21.0 UTF-8 scm:git:https://github.com/eclipse/gemoc-studio-execution-java.git - http://download.eclipse.org/releases/photon + http://download.eclipse.org/releases/2020-03 http://www.kermeta.org/k3/update_2018-09-05 - http://melange.inria.fr/updatesite/nightly/update_2018-12-03/ + http://melange.inria.fr/updatesite/nightly/update_2020-06-19 http://download.eclipse.org/elk/updates/releases/0.4.1 http://download.eclipse.org/tools/ajdt/48/dev/update - https://download.eclipse.org/sirius/updates/releases/6.1.3/photon + false @@ -70,11 +70,6 @@ p2 ${aspectJ.p2.url} - - Sirius - p2 - ${sirius.p2.url} - @@ -92,8 +87,8 @@ ${tycho-version} UTF-8 - 1.8 - 1.8 + 11 + 11 com.oracle @@ -251,40 +246,15 @@ - - - - - - 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 - - - + org.apache.maven.plugins maven-compiler-plugin 3.8.0 - 1.8 - 1.8 + 11 + 11 ${project.build.sourceEncoding} 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