]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/util/RuntimeEnvironmentRequest.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.db.layer0 / src / org / simantics / db / layer0 / util / RuntimeEnvironmentRequest.java
diff --git a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/util/RuntimeEnvironmentRequest.java b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/util/RuntimeEnvironmentRequest.java
new file mode 100644 (file)
index 0000000..23ee4fc
--- /dev/null
@@ -0,0 +1,162 @@
+package org.simantics.db.layer0.util;\r
+\r
+import java.util.HashMap;\r
+import java.util.Map;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.common.request.ParametrizedPrimitiveRead;\r
+import org.simantics.db.common.request.UnaryRead;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.layer0.internal.SimanticsInternal;\r
+import org.simantics.db.procedure.Listener;\r
+import org.simantics.db.request.Read;\r
+import org.simantics.scl.compiler.environment.specification.EnvironmentSpecification;\r
+import org.simantics.scl.compiler.module.repository.ImportFailureException;\r
+import org.simantics.scl.compiler.module.repository.UpdateListener;\r
+import org.simantics.scl.compiler.runtime.RuntimeEnvironment;\r
+import org.simantics.scl.osgi.SCLOsgi;\r
+import org.simantics.scl.runtime.SCLContext;\r
+\r
+/**\r
+ * Finds the runtime environment of a model or other index root.\r
+ * \r
+ * @author Hannu Niemistö\r
+ * @author Antti Villberg\r
+ */\r
+public class RuntimeEnvironmentRequest extends UnaryRead<Resource, RuntimeEnvironment> {\r
+\r
+    public RuntimeEnvironmentRequest(Resource parameter) {\r
+        super(parameter);\r
+    }\r
+    \r
+    protected void fillEnvironmentSpecification(EnvironmentSpecification environmentSpecification) {\r
+    }\r
+\r
+    static class UpdateListenerImpl implements UpdateListener {\r
+               \r
+       final EnvironmentSpecification environmentSpecification;\r
+       final Listener<RuntimeEnvironment> callback;\r
+       \r
+       UpdateListenerImpl(EnvironmentSpecification environmentSpecification, Listener<RuntimeEnvironment> callback) {\r
+               this.environmentSpecification = environmentSpecification;\r
+               this.callback = callback;\r
+       }\r
+\r
+        @Override\r
+        public void notifyAboutUpdate() {\r
+               if(callback.isDisposed()) {\r
+                       return;\r
+               }\r
+               getRuntimeEnvironment(environmentSpecification, callback, this);\r
+        }\r
+\r
+       final public static void getRuntimeEnvironment(EnvironmentSpecification environmentSpecification, Listener<RuntimeEnvironment> callback, UpdateListenerImpl listener) {\r
+\r
+                       try {\r
+                               \r
+                       SCLContext context = SCLContext.getCurrent();\r
+                       \r
+                       RuntimeEnvironment env;\r
+                       Object graph = context.get("graph");\r
+                       if(graph == null)\r
+                    try {\r
+                        env = SimanticsInternal.getSession().syncRequest(new Read<RuntimeEnvironment>() {\r
+                            @Override\r
+                            public RuntimeEnvironment perform(ReadGraph graph) throws DatabaseException {\r
+                               \r
+                                SCLContext sclContext = SCLContext.getCurrent();\r
+                               Object oldGraph = sclContext.get("graph");\r
+                                try {\r
+                                       sclContext.put("graph", graph);\r
+                                    return SCLOsgi.MODULE_REPOSITORY.createRuntimeEnvironment(\r
+                                            environmentSpecification,\r
+                                            callback.getClass().getClassLoader(), listener);\r
+                                } catch (ImportFailureException e) {\r
+                                    throw new DatabaseException(e);\r
+                                } catch (Throwable t) {\r
+                                    throw new DatabaseException(t);\r
+                                } finally {\r
+                                    sclContext.put("graph", oldGraph);\r
+                                }\r
+                            }\r
+                        });\r
+                    } catch (DatabaseException e) {\r
+                        callback.exception(e);\r
+                        return;\r
+                    }\r
+                else \r
+                           env = SCLOsgi.MODULE_REPOSITORY.createRuntimeEnvironment(\r
+                                   environmentSpecification,\r
+                                   callback.getClass().getClassLoader(), listener);\r
+                       callback.execute(env);\r
+                       } catch (ImportFailureException e) {\r
+                               callback.exception(new DatabaseException(e));\r
+                       }\r
+\r
+       }\r
+        \r
+    };     \r
+\r
+    // This is needed to prevent garbage collection from collecting UpdateListenerImpls\r
+    // -ModuleRepository only makes a weak reference to the listener\r
+    final static Map<String, UpdateListenerImpl> map = new HashMap<String, UpdateListenerImpl>(); \r
+    \r
+    @Override\r
+    public RuntimeEnvironment perform(ReadGraph graph)\r
+            throws DatabaseException {\r
+        final EnvironmentSpecification environmentSpecification = EnvironmentSpecification.of(\r
+                "Builtin", "",\r
+                "Prelude", "",\r
+                "Simantics/All", "");\r
+        fillEnvironmentSpecification(environmentSpecification);\r
+        Resource mainModule = Layer0Utils.getPossibleChild(graph, parameter, "SCLMain");\r
+        String mainModuleUri;\r
+        if(mainModule != null) {\r
+            mainModuleUri = graph.getURI(mainModule);\r
+            environmentSpecification.importModule(mainModuleUri, "");\r
+        }\r
+        else\r
+            mainModuleUri = graph.getURI(parameter) + "/#"; // Add something dummy to the model uri that cannot be in a real URI\r
+        \r
+            return graph.syncRequest(new ParametrizedPrimitiveRead<String, RuntimeEnvironment>(mainModuleUri) {\r
+               \r
+               @Override\r
+               public void register(ReadGraph graph, Listener<RuntimeEnvironment> procedure) {\r
+\r
+                       SCLContext context = SCLContext.getCurrent();\r
+                       Object oldGraph = context.put("graph", graph);\r
+                       try {\r
+\r
+                               if(procedure.isDisposed()) {\r
+                                       UpdateListenerImpl.getRuntimeEnvironment(environmentSpecification, procedure, null);\r
+                               } else {\r
+                                       UpdateListenerImpl impl = new UpdateListenerImpl(environmentSpecification, procedure);\r
+                                       impl.notifyAboutUpdate();\r
+                                               map.put(parameter, impl);\r
+                               }\r
+\r
+                       } finally {\r
+                               context.put("graph", oldGraph);\r
+                       }\r
+\r
+               }\r
+                \r
+                @Override\r
+                public void unregistered() {\r
+                       map.remove(parameter);\r
+                }\r
+                \r
+            });\r
+    }\r
+    \r
+    @Override\r
+    public int hashCode() {\r
+        return 31*getClass().hashCode() + super.hashCode();\r
+    }\r
+\r
+    public static void flush() {\r
+        map.clear();\r
+    }\r
+\r
+}\r