Improved PapyrusUtils model and Jupyter engine

Updated papyrus utils module
Added cell autorun from script argument support
Added engine auto termination when browser page is closed.
Allow headless notebook execution

Change-Id: I7f2669af75798b2729325945fb49ad9af29555bb
Signed-off-by: Sebastien Revol <sebastien.revol@cea.fr>
diff --git a/bundles/org.eclipse.papyrus.ease.lang.python.jupyter/.gitignore b/bundles/org.eclipse.papyrus.ease.lang.python.jupyter/.gitignore
new file mode 100644
index 0000000..f6eeff7
--- /dev/null
+++ b/bundles/org.eclipse.papyrus.ease.lang.python.jupyter/.gitignore
@@ -0,0 +1 @@
+/.pydevproject
diff --git a/bundles/org.eclipse.papyrus.ease.lang.python.jupyter/.project b/bundles/org.eclipse.papyrus.ease.lang.python.jupyter/.project
index 9457dde..f43bb0e 100644
--- a/bundles/org.eclipse.papyrus.ease.lang.python.jupyter/.project
+++ b/bundles/org.eclipse.papyrus.ease.lang.python.jupyter/.project
@@ -24,5 +24,6 @@
 	<natures>
 		<nature>org.eclipse.pde.PluginNature</nature>
 		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.python.pydev.pythonNature</nature>
 	</natures>
 </projectDescription>
diff --git a/bundles/org.eclipse.papyrus.ease.lang.python.jupyter/jupyter/kernels/ease_py4j_kernel/ease_init.py b/bundles/org.eclipse.papyrus.ease.lang.python.jupyter/jupyter/kernels/ease_py4j_kernel/ease_init.py
index c22a73e..bf7a539 100644
--- a/bundles/org.eclipse.papyrus.ease.lang.python.jupyter/jupyter/kernels/ease_py4j_kernel/ease_init.py
+++ b/bundles/org.eclipse.papyrus.ease.lang.python.jupyter/jupyter/kernels/ease_py4j_kernel/ease_init.py
@@ -1,3 +1,17 @@
+#################################################################################
+# Copyright (c) 2019 CEA LIST and others.
+# 
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License 2.0
+# which accompanies this distribution, and is available at
+# https://www.eclipse.org/legal/epl-2.0/
+#
+# SPDX-License-Identifier: EPL-2.0
+#
+#  Contributors:
+#  CEA LIST - Initial API and implementation
+#   
+#################################################################################
 import sys
 import os
 
@@ -7,6 +21,7 @@
 
 
 import ease_py4j_main 
+from IPython.display import Javascript, display_javascript 
 
 #in IPyhton __builtins__ is a dict, in CPython there is a __builtins__.__dict__ attribute
 class IPythonScriptEngineExecute(ease_py4j_main._pyease_ScriptEngineExecute):
@@ -37,4 +52,11 @@
     engine.set_gateway(gateway)
     # tell Java that we are up and running and where to direct
     # calls to python to.
-    gateway.entry_point.pythonStartupComplete(python_port, engine)
\ No newline at end of file
+    gateway.entry_point.pythonStartupComplete(python_port, engine)
+   
+
+def get_cells_to_run():
+    return gateway.entry_point.getCellsToRun()
+    
+    
+    
\ No newline at end of file
diff --git a/bundles/org.eclipse.papyrus.ease.lang.python.jupyter/jupyter/kernels/ease_py4j_kernel/ease_py4j_kernel.py b/bundles/org.eclipse.papyrus.ease.lang.python.jupyter/jupyter/kernels/ease_py4j_kernel/ease_py4j_kernel.py
index af6ea43..e505deb 100644
--- a/bundles/org.eclipse.papyrus.ease.lang.python.jupyter/jupyter/kernels/ease_py4j_kernel/ease_py4j_kernel.py
+++ b/bundles/org.eclipse.papyrus.ease.lang.python.jupyter/jupyter/kernels/ease_py4j_kernel/ease_py4j_kernel.py
@@ -1,45 +1,23 @@
-
+#################################################################################
+# Copyright (c) 2019 CEA LIST and others.
+# 
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License 2.0
+# which accompanies this distribution, and is available at
+# https://www.eclipse.org/legal/epl-2.0/
+#
+# SPDX-License-Identifier: EPL-2.0
+#
+#  Contributors:
+#  CEA LIST - Initial API and implementation
+#   
+#################################################################################
 
 code='''
 import ease_init
 ease_init.connect_to_ease()
 '''
 
-#TODO : manage to use this kind of code to terminate the server when the tab is closed in the browser
-code2 ='''from IPython.display import Javascript
-Javascript(\'\'\'
-window.addEventListener('beforeunload', function() {
-    
-    require(['base/js/utils'], function(utils){
-            utils.ajax(utils.url_path_join(
-                utils.get_body_data("baseUrl"),
-                "api",
-                "shutdown"), 
-                {
-                type: "POST",
-                }
-            );
-        }
-    
-    );
-    
-});
-
-window.onbeforeunload = function () {
-   
-    require(['base/js/utils'], function(utils){
-            utils.ajax(utils.url_path_join(
-                utils.get_body_data("baseUrl"),
-                "api",
-                "shutdown"
-            ), {
-                type: "POST",
-            });
-    
-    });
-}
-\'\'\')'''
-
 if __name__ == '__main__':  
     
     from ipykernel.kernelapp import IPKernelApp
diff --git a/bundles/org.eclipse.papyrus.ease.lang.python.jupyter/jupyter/kernels/ease_py4j_kernel/kernel.js b/bundles/org.eclipse.papyrus.ease.lang.python.jupyter/jupyter/kernels/ease_py4j_kernel/kernel.js
new file mode 100644
index 0000000..3673c25
--- /dev/null
+++ b/bundles/org.eclipse.papyrus.ease.lang.python.jupyter/jupyter/kernels/ease_py4j_kernel/kernel.js
@@ -0,0 +1,70 @@
+/*****************************************************************************
+ * Copyright (c) 2019 CEA LIST and others.
+ * 
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *   CEA LIST - Initial API and implementation
+ *   
+ *****************************************************************************/
+
+function shutdownEASE() {
+	var code = 'env= loadModule("Environment")\n'
+			+ 'env.getScriptEngine().terminate()\n'
+	var kernel = IPython.notebook.kernel;
+	kernel.execute(code);
+}
+
+window.addEventListener('unload', shutdownEASE);
+
+window.onbeforeunload = shutdownEASE;
+
+code_show=true;
+
+var handler = function() {
+	if (code_show) {
+		$('div.input').hide();
+	} else {
+		$('div.input').show();
+	}
+	code_show = !code_show
+
+};
+
+var action = {
+	icon : 'fa-code', // a font-awesome class used on buttons, etc
+	help : 'Toggle code',
+	help_index : 'zz',
+	handler : handler
+};
+var prefix = 'my_extension';
+var action_name = 'hide-code';
+
+var full_action_name = Jupyter.actions.register(action, action_name, prefix); 
+Jupyter.toolbar.add_buttons_group([ full_action_name ]);
+
+
+
+Jupyter.notebook.events.on('kernel_ready.Kernel', () => {
+	IPython.notebook.kernel.execute(
+		    "ease_init.get_cells_to_run()", 
+		{
+		    	iopub: {
+		    		output: function(response) {
+		    			var cells =   eval(response.content.data["text/plain"])  
+		    			Jupyter.notebook.execute_cells(cells)
+		    		}
+		    	}
+		},
+		{
+		silent: false, 
+		store_history: false, 
+		stop_on_error: true
+		}
+	)
+});
diff --git a/bundles/org.eclipse.papyrus.ease.lang.python.jupyter/src/org/eclipse/papyrus/ease/lang/python/jupyter/internal/JupyterEngine.java b/bundles/org.eclipse.papyrus.ease.lang.python.jupyter/src/org/eclipse/papyrus/ease/lang/python/jupyter/internal/JupyterEngine.java
index 25d6dfc..bbb9fc1 100644
--- a/bundles/org.eclipse.papyrus.ease.lang.python.jupyter/src/org/eclipse/papyrus/ease/lang/python/jupyter/internal/JupyterEngine.java
+++ b/bundles/org.eclipse.papyrus.ease.lang.python.jupyter/src/org/eclipse/papyrus/ease/lang/python/jupyter/internal/JupyterEngine.java
@@ -23,6 +23,7 @@
 import java.util.Map;
 
 import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.Platform;
 import org.eclipse.ease.AbstractReplScriptEngine;
 import org.eclipse.ease.Logger;
 import org.eclipse.ease.Script;
@@ -128,7 +129,6 @@
 			
 			fPythonSideEngine = jupyterProxy.getPythonSideEngine();
 			
-			
 		
 		} catch (final Exception e) {
 			teardownEngine();
@@ -137,6 +137,8 @@
 		}
 	}
 
+	
+	protected Script notebookScript;
 
 	
 	private void initializeJupyterProxy() {
@@ -149,14 +151,30 @@
 				if (NOTE_BOOK_EXTENSION.equals(scriptFile.getFileExtension())){
 					jupyterProxy.setNotebook(scriptFile);
 					scriptToRemove.add(script);
+					notebookScript = script;
 				}
 			}
 			
 		}
 		getScheduledScripts().removeAll(scriptToRemove);
 		
+		List<Integer> cellsToRun = new ArrayList<>();
+		Object argObj = getVariable("argv");
+		if( argObj instanceof String[]) {
+			for (String arg : (String[])argObj) {
+				try {
+					Integer cellNumber = Integer.parseInt(arg);
+					cellsToRun.add(cellNumber);
+				}catch (NumberFormatException e) {
+					continue;
+				}
+				
+			}
+		}
+		jupyterProxy.addAutoCells(cellsToRun);
 	}
 
+	
 	@Override
 	protected Object execute(final Script script, final Object reference, final String fileName, final boolean uiThread) throws Throwable {
 		if (uiThread) {
@@ -197,6 +215,9 @@
 
 	@Override
 	public void terminateCurrent() {
+		if (notebookScript != null) {
+			notebookScript.setResult(0);
+		}
 		setTerminateOnIdle(true);
 	
 	}
@@ -216,13 +237,15 @@
 		// fPythonSideEngine.teardownEngine();
 		// }
 		
+		
+		
 		if (jupyterProxy != null) {
 			jupyterProxy.shutDown();
 		}
 		
 		Activator.getDefault().unRegisterProxy(jupyterProxy);
 		
-	
+
 		try {
 			// Wait until the gobblers have shovelled all their
 			// inputs before allowing the engine to considered terminated
diff --git a/bundles/org.eclipse.papyrus.ease.lang.python.jupyter/src/org/eclipse/papyrus/ease/lang/python/jupyter/internal/JupyterProxy.java b/bundles/org.eclipse.papyrus.ease.lang.python.jupyter/src/org/eclipse/papyrus/ease/lang/python/jupyter/internal/JupyterProxy.java
index 2819e78..e72b3eb 100644
--- a/bundles/org.eclipse.papyrus.ease.lang.python.jupyter/src/org/eclipse/papyrus/ease/lang/python/jupyter/internal/JupyterProxy.java
+++ b/bundles/org.eclipse.papyrus.ease.lang.python.jupyter/src/org/eclipse/papyrus/ease/lang/python/jupyter/internal/JupyterProxy.java
@@ -14,15 +14,19 @@
  *****************************************************************************/
 package org.eclipse.papyrus.ease.lang.python.jupyter.internal;
 
+import java.awt.Desktop;
 import java.io.File;
 import java.io.IOException;
 import java.net.InetSocketAddress;
 import java.net.MalformedURLException;
 import java.net.ServerSocket;
 import java.net.SocketAddress;
+import java.net.URI;
 import java.net.URISyntaxException;
 import java.net.URL;
 import java.nio.channels.SocketChannel;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.UUID;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
@@ -66,6 +70,7 @@
 
 	private static final String JUPYTER_PATH = "JUPYTER_PATH";
 
+
 	private static final String PYTHON_PATH = "PYTHONPATH";
 
 	private static final String EASE_PYTHON_COMMON_BUNDLE_ID = "org.eclipse.ease.lang.python";
@@ -90,8 +95,11 @@
 	private IPythonSideEngine pythonSideEngine;
 	private Process jupyterProcess;
 	private String notebookName;
-	
+
 	private String pythonInterpreter = getPythonInterpreterExec();
+	
+	
+	private List<Integer> cellToRun= new ArrayList<>();
 
 	public JupyterProxy() {
 
@@ -154,28 +162,25 @@
 		return jupyterProcess;
 	}
 
-	public void startJupyterProcess() throws InterruptedException, ScriptEngineException, IOException, URISyntaxException {
+	public void startJupyterProcess()
+			throws InterruptedException, ScriptEngineException, IOException, URISyntaxException {
 
 		notebookPort = getFreePort(8888);
 
-		
 		gatewayServer = new ClientServerBuilder(this).javaPort(0).pythonPort(0).build();
 		gatewayServer.startServer(true);
 		final int javaListeningPort = ((JavaServer) gatewayServer.getJavaServer()).getListeningPort();
-		
-		final ProcessBuilder pb = new ProcessBuilder();
 
-		
-		
+		final ProcessBuilder pb = new ProcessBuilder();
 
 		// we use Py4J python interpreter, should include Jupyter
 		pb.command().add(pythonInterpreter);
 		pb.command().add("-m");
 		pb.command().add("notebook");
 		pb.command().add("--notebook-dir=" + notebookDirectory);
-		String fullPath = notebookDirectory+File.separator+"static";
+		String fullPath = notebookDirectory + File.separator + "static";
 		fullPath = fullPath.replace("\\", "\\\\");
-		pb.command().add("--NotebookApp.extra_static_paths=['"+fullPath+"']");
+		pb.command().add("--NotebookApp.extra_static_paths=['" + fullPath + "']");
 		if (notebookPort > -1) {
 			pb.command().add("--port=" + notebookPort);
 		}
@@ -192,12 +197,14 @@
 		pb.environment().put(JUPYTER_PATH,
 				appendToCurrentEnvPath(JUPYTER_PATH, getJupyterPathDirectory().getAbsolutePath()));
 
+		
+	
+
 		// we also add the kernel directory in PYTHON_PATH in order to allow the
 		// first-level python to load our custom python kernel
 		pb.environment().put(PYTHON_PATH,
 				appendToCurrentEnvPath(PYTHON_PATH, getJupyterKernelDirectory().getAbsolutePath()));
-		
-		
+
 		// we now add several environment variable that will be read during our easepy4j
 		// kernel startup to establish connection
 		// with Py4J java side initiated by EASE
@@ -209,18 +216,14 @@
 		pb.environment().put(EASE_PYTHON_COMMON_SRC, getEASEPythonCommonSrc().getAbsolutePath());
 		pb.environment().put(EASE_PY4J_SRC, getPy4jEaseMainDir().getAbsolutePath());
 
-		
 		jupyterProcess = pb.start();
 
-		
-
-		
 		pythonStartupComplete = new CountDownLatch(1);
 
-		
-
 	}
 
+	
+
 	private String getPythonInterpreterExec() {
 		String interpreter = Platform.getPreferencesService().getString("org.eclipse.ease.lang.python.py4j",
 				"org.eclipse.ease.lang.python.py4j.INTERPRETER", "python", null);
@@ -233,20 +236,19 @@
 		return interpreter;
 	}
 
-	private void waitForJupyterStartup() throws InterruptedException, ScriptEngineException, IOException{
-		boolean scanning=true;
+	private void waitForJupyterStartup() throws InterruptedException, ScriptEngineException, IOException {
+		boolean scanning = true;
 		SocketAddress address = new InetSocketAddress("localhost", notebookPort);
-		
+
 		int attempts = 0;
-		while(scanning && attempts < 200){
-		    try{
-		    	attempts++;
-		    	SocketChannel.open(address);
-		        scanning=false;
-		    }
-		    catch(IOException e){
-		        Thread.sleep(100);//0.1 second
-		    } 
+		while (scanning && attempts < 200) {
+			try {
+				attempts++;
+				SocketChannel.open(address);
+				scanning = false;
+			} catch (IOException e) {
+				Thread.sleep(100);// 0.1 second
+			}
 		}
 		if (scanning) {
 			throw new ScriptEngineException("Jupyter notebook did not start within 20 seconds");
@@ -254,13 +256,14 @@
 	}
 
 	public void waitForKernelStartup() throws InterruptedException, ScriptEngineException, IOException {
-		
+
 		waitForJupyterStartup();
-		
-		//web browser will start the kernel if a notebook has been selected to be run as EASE script
-		//else user will have to manually start the kernel in the browser
+
+		// web browser will start the kernel if a notebook has been selected to be run
+		// as EASE script
+		// else user will have to manually start the kernel in the browser
 		openWebBrowser();
-		
+
 		// We wait here for the main notebook python process initialization
 		if (!pythonStartupComplete.await(PYTHON_STARTUP_TIMEOUT_SECONDS, TimeUnit.SECONDS)) {
 			throw new ScriptEngineException(
@@ -278,34 +281,60 @@
 		pythonStartupComplete.countDown();
 
 	}
+	
+	public List<Integer> getCellsToRun() {
+		return cellToRun;
+	}
+	
+	public void addAutoCells(List<Integer> cellsToRun) {
+		this.cellToRun.addAll(cellsToRun);
+		
+	}
 
 	private void openWebBrowser() {
+		if (PlatformUI.isWorkbenchRunning()) {
+			Display.getDefault().asyncExec(new Runnable() {
 
-		Display.getDefault().asyncExec(new Runnable() {
+				@Override
+				public void run() {
 
-			@Override
-			public void run() {
+					try {
+						// even if we wait for python startup, still have to wait for server startup to
+						// avoid to have to refresh the page
+						TimeUnit.SECONDS.sleep(3);
+						IWebBrowser browser = PlatformUI.getWorkbench().getBrowserSupport().createBrowser(null);
+						browser.openURL(getNoteBookURL());
+
+					} catch (MalformedURLException e) {
+						// TODO Auto-generated catch block
+						e.printStackTrace();
+
+					} catch (InterruptedException e) {
+						// TODO Auto-generated catch block
+						e.printStackTrace();
+					} catch (PartInitException e) {
+						// TODO Auto-generated catch block
+						e.printStackTrace();
+					}
+				}
+
+			});
+
+		} else {
+			if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) {
 
 				try {
-					// even if we wait for python startup, still have to wait for server startup to
-					// avoid to have to refresh the page
-					TimeUnit.SECONDS.sleep(3);
-					IWebBrowser browser = PlatformUI.getWorkbench().getBrowserSupport().createBrowser(null);
-					browser.openURL(getNoteBookURL());
-
-				} catch (PartInitException e) {
+					URI uri = getNoteBookURL().toURI();
+					Desktop.getDesktop().browse(uri);
+				} catch (IOException e) {
 					// TODO Auto-generated catch block
 					e.printStackTrace();
-				} catch (MalformedURLException e) {
-					// TODO Auto-generated catch block
-					e.printStackTrace();
-				} catch (InterruptedException e) {
+				} catch (URISyntaxException e) {
 					// TODO Auto-generated catch block
 					e.printStackTrace();
 				}
-
 			}
-		});
+		}
 
 	}
 
@@ -335,7 +364,7 @@
 	private File getPy4jPythonSrc() throws IOException {
 		final File py4jPythonBundleFile = FileLocator.getBundleFile(Platform.getBundle(PY4J_PYTHON_BUNDLE_ID));
 		final File py4jPythonSrc = new File(py4jPythonBundleFile, "/src");
-		//final File py4j = new File(py4jPythonSrc, "py4j");
+		// final File py4j = new File(py4jPythonSrc, "py4j");
 		if (!py4jPythonSrc.exists() || !py4jPythonSrc.isDirectory()) {
 			throw new IOException("Failed to find py4j python directory, expected it here: " + py4jPythonSrc);
 		}
@@ -351,10 +380,11 @@
 		}
 		return py4jEaseMain;
 	}
+
 	private File getJupyterPathDirectory() throws IOException, URISyntaxException {
-		final URL url = new URL("platform:/plugin/"+Activator.PLUGIN_ID+"/jupyter");
-		final URL fileURL = FileLocator.toFileURL(url);		
-		final File rootDir =  new File(URIUtil.toURI(fileURL).normalize());
+		final URL url = new URL("platform:/plugin/" + Activator.PLUGIN_ID + "/jupyter");
+		final URL fileURL = FileLocator.toFileURL(url);
+		final File rootDir = new File(URIUtil.toURI(fileURL).normalize());
 		if (!rootDir.exists() || !rootDir.isDirectory()) {
 			throw new IOException(
 					"Failed to find ease-py4j Jupyter kernel root directory, expected it here: " + rootDir);
@@ -390,8 +420,7 @@
 	 * port is being used between calling this and actually starting a server.
 	 * Handle blocked servers appropriately.
 	 * 
-	 * @param startPort
-	 *            Lowest desired port number.
+	 * @param startPort Lowest desired port number.
 	 * @return Free port (hopefully) close to startPort.
 	 */
 	public static int getFreePort(int startPort) {
@@ -429,19 +458,13 @@
 
 	public void shutDown() {
 
-		
-		ProcessBuilder stopProcess = new ProcessBuilder().command(
-				pythonInterpreter, 
-				"-m",
-				"notebook",
-				"stop",
-				Integer.toString(notebookPort)
-				);
-		
+		ProcessBuilder stopProcess = new ProcessBuilder().command(pythonInterpreter, "-m", "notebook", "stop",
+				Integer.toString(notebookPort));
+
 		try {
-			Process process =stopProcess.start();
+			Process process = stopProcess.start();
 			process.waitFor(PYTHON_SHUTDOWN_TIMEOUT_SECONDS, TimeUnit.SECONDS);
-			
+
 		} catch (IOException e1) {
 			// TODO Auto-generated catch block
 			e1.printStackTrace();
@@ -449,13 +472,13 @@
 			// TODO Auto-generated catch block
 			e.printStackTrace();
 		}
-		
-		
 
 		if (gatewayServer != null) {
 			gatewayServer.shutdown();
 		}
-		
+
 	}
 
+
+
 }
diff --git a/bundles/org.eclipse.papyrus.ease/META-INF/MANIFEST.MF b/bundles/org.eclipse.papyrus.ease/META-INF/MANIFEST.MF
index 0635358..3d3a6be 100644
--- a/bundles/org.eclipse.papyrus.ease/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.papyrus.ease/META-INF/MANIFEST.MF
@@ -22,7 +22,8 @@
  org.eclipse.gmf.runtime.diagram.ui,
  org.eclipse.papyrus.infra.gmfdiag.common,
  org.eclipse.papyrus.infra.viewpoints.policy,
- org.eclipse.papyrus.infra.emf
+ org.eclipse.papyrus.infra.emf,
+ org.eclipse.papyrus.uml.tools
 Export-Package: org.eclipse.papyrus.ease.module,
  org.eclipse.papyrus.ease.popup
 Bundle-Vendor: Eclipse Modeling Project
diff --git a/bundles/org.eclipse.papyrus.ease/src/org/eclipse/papyrus/ease/module/PapyrusUtilsModule.java b/bundles/org.eclipse.papyrus.ease/src/org/eclipse/papyrus/ease/module/PapyrusUtilsModule.java
index 8dab19d..50bf1e3 100644
--- a/bundles/org.eclipse.papyrus.ease/src/org/eclipse/papyrus/ease/module/PapyrusUtilsModule.java
+++ b/bundles/org.eclipse.papyrus.ease/src/org/eclipse/papyrus/ease/module/PapyrusUtilsModule.java
@@ -15,7 +15,6 @@
 package org.eclipse.papyrus.ease.module;
 
 import java.io.IOException;
-import java.lang.ref.WeakReference;
 import java.net.URISyntaxException;
 import java.net.URL;
 import java.util.Collection;
@@ -71,6 +70,7 @@
 import org.eclipse.papyrus.editor.PapyrusMultiDiagramEditor;
 import org.eclipse.papyrus.infra.architecture.ArchitectureDescriptionUtils;
 import org.eclipse.papyrus.infra.core.resource.ModelSet;
+import org.eclipse.papyrus.infra.core.resource.NotFoundException;
 import org.eclipse.papyrus.infra.core.services.ServiceException;
 import org.eclipse.papyrus.infra.core.services.ServiceMultiException;
 import org.eclipse.papyrus.infra.core.services.ServiceNotFoundException;
@@ -81,6 +81,8 @@
 import org.eclipse.papyrus.infra.types.core.utils.ElementTypeRegistryUtils;
 import org.eclipse.papyrus.infra.viewpoints.policy.PolicyChecker;
 import org.eclipse.papyrus.infra.viewpoints.policy.ViewPrototype;
+import org.eclipse.papyrus.uml.tools.model.UmlModel;
+import org.eclipse.papyrus.uml.tools.model.UmlUtils;
 import org.eclipse.swt.widgets.Display;
 import org.eclipse.ui.IEditorPart;
 import org.eclipse.ui.IWorkbench;
@@ -94,9 +96,8 @@
 public class PapyrusUtilsModule extends AbstractScriptModule {
 	
 	
-	private ModelSet currentModelSet = null; 
 
-	private IFile getDIFile(IFile inputFile) {
+	private static IFile getDIFile(IFile inputFile) {
 		IFile result = null;
 		if ("uml".equals(inputFile.getFileExtension())) {
 			result = (IFile) inputFile.getParent().findMember(inputFile.getName().replaceAll(".uml$", ".di"));
@@ -118,10 +119,10 @@
 	 *
 	 */
 	@WrapToScript
-	public org.eclipse.uml2.uml.Package getPapyrusModel(String modelPath)
+	public static  org.eclipse.uml2.uml.Package getPapyrusModel(String modelPath)
 			throws RuntimeException, CoreException, URISyntaxException, IOException, ServiceException {
 
-		Object resolved = ResourceTools.resolve(modelPath, getScriptEngine().getExecutedFile());
+		Object resolved = ResourceTools.resolve(modelPath);
 
 		
 		IFile diFile = null;
@@ -170,6 +171,7 @@
 
 			}
 
+			ModelSet currentModelSet = null;
 			if (editorPart != null) {
 				ServicesRegistry servicesRegistry = editorPart.getAdapter(ServicesRegistry.class);
 				if (servicesRegistry != null) {
@@ -207,7 +209,7 @@
 	 * @return the first object found with the given qualified name.
 	 */
 	@WrapToScript
-	public NamedElement getPapyrusNamedElement(Object context, String qualifiedName)
+	public static NamedElement getPapyrusNamedElement(Object context, String qualifiedName)
 			throws RuntimeException, CoreException, URISyntaxException, IOException, ServiceException {
 		ResourceSet resSet = null;
 		if (context instanceof String) {
@@ -232,24 +234,9 @@
 
 	}
 
-	static WeakReference<PapyrusMultiDiagramEditor> papyrus = null;
 
-	@WrapToScript
-	public static void setPapyrusSession(PapyrusMultiDiagramEditor editor) {
-		papyrus = new WeakReference<PapyrusMultiDiagramEditor>(editor);
-	}
-
-	public static PapyrusMultiDiagramEditor getPapyrusSession() {
-
-		if (papyrus != null && papyrus.get() != null) {
-			return papyrus.get();
-		} else {
-			PapyrusMultiDiagramEditor result = getActivePapyrusEditor();
-			setPapyrusSession(result);
-			return result;
-		}
-
-	}
+	
+	
 	
 	
 	@WrapToScript
@@ -280,7 +267,7 @@
 	@WrapToScript
 	public static EObject createSemanticElement(EObject owner, String elementTypeIdToCreate) {
 
-		PapyrusMultiDiagramEditor papyrus = getPapyrusSession();
+		PapyrusMultiDiagramEditor papyrus = getActivePapyrusEditor();
 		IElementType elementType = getElementType(papyrus, elementTypeIdToCreate);
 		if (elementType != null) {
 			return RequestUtils.createElementWithRequest(owner, elementType);
@@ -293,7 +280,7 @@
 			Node sourceNode, Double relativeXSource, Double relativeYSource, Node targetNode, Double relativeXTarget,
 			Double relativeYTarget) {
 
-		PapyrusMultiDiagramEditor papyrus = getPapyrusSession();
+		PapyrusMultiDiagramEditor papyrus = getActivePapyrusEditor();
 		IElementType elementType = getElementType(papyrus, graphicalElementTypeIdToCreate);
 
 		GraphicalEditPart diagramEditPart = (GraphicalEditPart) getActivePapyrusViewer(papyrus).getContents();
@@ -356,7 +343,7 @@
 			Integer y, @ScriptParameter(defaultValue = ScriptParameter.NULL) Integer width,
 			@ScriptParameter(defaultValue = ScriptParameter.NULL) Integer height) {
 
-		PapyrusMultiDiagramEditor papyrus = getPapyrusSession();
+		PapyrusMultiDiagramEditor papyrus = getActivePapyrusEditor();
 		IElementType elementType = getElementType(papyrus, graphicalElementTypeIdToCreate);
 		EditPart targetEditPart = calculateTargetEditPart(papyrus, (double) x, (double) y);
 
@@ -397,7 +384,7 @@
 			@Override
 			public void run() {
 
-				getActivePapyrusViewer(getPapyrusSession()).flush();
+				getActivePapyrusViewer(getActivePapyrusEditor()).flush();
 
 			}
 		};
@@ -434,7 +421,7 @@
 			@ScriptParameter(defaultValue = ScriptParameter.NULL) Integer width,
 			@ScriptParameter(defaultValue = ScriptParameter.NULL) Integer height) {
 
-		PapyrusMultiDiagramEditor papyrus = getPapyrusSession();
+		PapyrusMultiDiagramEditor papyrus = getActivePapyrusEditor();
 		IElementType elementType = getElementType(papyrus, graphicalElementTypeIdToCreate);
 		EditPart targetEditPart = calculateTargetEditPart(papyrus, (double) x, (double) y);
 
@@ -471,7 +458,7 @@
 			Double relativeX, Double relativeY, @ScriptParameter(defaultValue = ScriptParameter.NULL) Integer width,
 			@ScriptParameter(defaultValue = ScriptParameter.NULL) Integer height) {
 
-		PapyrusMultiDiagramEditor papyrus = getPapyrusSession();
+		PapyrusMultiDiagramEditor papyrus = getActivePapyrusEditor();
 		IElementType elementType = getElementType(papyrus, graphicalElementTypeIdToCreate);
 
 		Diagram diagram = DiagramUtils.getContainingDiagram(parentNode);
@@ -510,7 +497,7 @@
 			@ScriptParameter(defaultValue = ScriptParameter.NULL) Integer width,
 			@ScriptParameter(defaultValue = ScriptParameter.NULL) Integer height) {
 
-		PapyrusMultiDiagramEditor papyrus = getPapyrusSession();
+		PapyrusMultiDiagramEditor papyrus = getActivePapyrusEditor();
 		IElementType elementType = getElementType(papyrus, graphicalElementTypeIdToCreate);
 
 		if (elementType instanceof IHintedType && parentNode instanceof Node) {
@@ -522,7 +509,7 @@
 						.get(parentNode);
 			} else {
 				PrecisionPoint absoluteLocation = getAbsolutePoint(parentNode, relativeX, relativeY);
-				targetEditPart = (GraphicalEditPart) calculateTargetEditPart(getPapyrusSession(),
+				targetEditPart = (GraphicalEditPart) calculateTargetEditPart(getActivePapyrusEditor(),
 						absoluteLocation.preciseX(), absoluteLocation.preciseY());
 			}
 
@@ -656,6 +643,38 @@
 		return null;
 	}
 
+	
+	@WrapToScript
+	public static ModelSet getActivePapyrusModelSet() {
+		PapyrusMultiDiagramEditor papyrus = getActivePapyrusEditor();
+		try {
+			return papyrus.getServicesRegistry().getService(ModelSet.class);
+		} catch (ServiceException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+		return null;
+	}
+	
+	
+	
+	@WrapToScript
+	public static Package getActivePapyrusModel() {
+		
+		ModelSet modelSet = PapyrusUtilsModule.getActivePapyrusModelSet();
+		if (modelSet !=null) {
+			UmlModel umlModel = UmlUtils.getUmlModel(modelSet);
+			try {
+				return (Package) umlModel.lookupRoot();
+			} catch (NotFoundException e) {
+				// TODO Auto-generated catch block
+				e.printStackTrace();
+			}
+			
+		}
+		return null;
+	}
+	
 	public static GraphicalViewer getActivePapyrusViewer(PapyrusMultiDiagramEditor papyrusEditor) {
 
 		IEditorPart currentEditor = papyrusEditor.getActiveEditor();
@@ -665,4 +684,23 @@
 
 		return null;
 	}
+	
+	@WrapToScript
+	public static void saveAs(String uriString) {
+		String cleanedURI = uriString.replaceAll("workspace:", "platform:/resource");
+		URI uri = URI.createURI(cleanedURI);
+		PapyrusMultiDiagramEditor papyrus = getActivePapyrusEditor();
+		try {
+			ModelSet modelSet = papyrus.getServicesRegistry().getService(ModelSet.class);
+			modelSet.saveAs(uri);
+			
+		} catch (ServiceException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		} catch (IOException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+		
+	}
 }