]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/util/RuntimeEnvironmentRequest2.java
Merge commit '876ede6'
[simantics/platform.git] / bundles / org.simantics.db.layer0 / src / org / simantics / db / layer0 / util / RuntimeEnvironmentRequest2.java
1 package org.simantics.db.layer0.util;\r
2 \r
3 import java.util.Collection;\r
4 import java.util.HashMap;\r
5 import java.util.Map;\r
6 \r
7 import org.simantics.db.ReadGraph;\r
8 import org.simantics.db.Resource;\r
9 import org.simantics.db.common.request.BinaryRead;\r
10 import org.simantics.db.common.request.ObjectsWithType;\r
11 import org.simantics.db.common.request.ParametrizedPrimitiveRead;\r
12 import org.simantics.db.exception.DatabaseException;\r
13 import org.simantics.db.layer0.internal.SimanticsInternal;\r
14 import org.simantics.db.procedure.Listener;\r
15 import org.simantics.db.request.Read;\r
16 import org.simantics.layer0.Layer0;\r
17 import org.simantics.scl.compiler.environment.specification.EnvironmentSpecification;\r
18 import org.simantics.scl.compiler.module.repository.ImportFailureException;\r
19 import org.simantics.scl.compiler.module.repository.UpdateListener;\r
20 import org.simantics.scl.compiler.runtime.RuntimeEnvironment;\r
21 import org.simantics.scl.osgi.SCLOsgi;\r
22 import org.simantics.scl.runtime.SCLContext;\r
23 \r
24 /**\r
25  * Finds the runtime environment of a model or other index root.\r
26  * \r
27  * @author Hannu Niemistö\r
28  * @author Antti Villberg\r
29  */\r
30 public class RuntimeEnvironmentRequest2 extends BinaryRead<Resource, Resource, RuntimeEnvironment> {\r
31 \r
32     public RuntimeEnvironmentRequest2(Resource parameter, Resource parameter2) {\r
33         super(parameter, parameter2);\r
34     }\r
35     \r
36     protected void fillEnvironmentSpecification(EnvironmentSpecification environmentSpecification) {\r
37     }\r
38 \r
39     static class UpdateListenerImpl implements UpdateListener {\r
40           \r
41      final EnvironmentSpecification environmentSpecification;\r
42      final Listener<RuntimeEnvironment> callback;\r
43      \r
44      UpdateListenerImpl(EnvironmentSpecification environmentSpecification, Listener<RuntimeEnvironment> callback) {\r
45       this.environmentSpecification = environmentSpecification;\r
46       this.callback = callback;\r
47      }\r
48 \r
49         @Override\r
50         public void notifyAboutUpdate() {\r
51          if(callback.isDisposed()) {\r
52           return;\r
53          }\r
54          getRuntimeEnvironment(environmentSpecification, callback, this);\r
55         }\r
56 \r
57      final public static void getRuntimeEnvironment(EnvironmentSpecification environmentSpecification, Listener<RuntimeEnvironment> callback, UpdateListenerImpl listener) {\r
58 \r
59    try {\r
60     \r
61           SCLContext context = SCLContext.getCurrent();\r
62           \r
63           RuntimeEnvironment env;\r
64           Object graph = context.get("graph");\r
65           if(graph == null)\r
66                     try {\r
67                         env = SimanticsInternal.getSession().syncRequest(new Read<RuntimeEnvironment>() {\r
68                             @Override\r
69                             public RuntimeEnvironment perform(ReadGraph graph) throws DatabaseException {\r
70                              \r
71                                 SCLContext sclContext = SCLContext.getCurrent();\r
72                              Object oldGraph = sclContext.get("graph");\r
73                                 try {\r
74                                  sclContext.put("graph", graph);\r
75                                     return SCLOsgi.MODULE_REPOSITORY.createRuntimeEnvironment(\r
76                                             environmentSpecification,\r
77                                             callback.getClass().getClassLoader(), listener);\r
78                                 } catch (ImportFailureException e) {\r
79                                     throw new DatabaseException(e);\r
80                                 } catch (Throwable t) {\r
81                                     throw new DatabaseException(t);\r
82                                 } finally {\r
83                                     sclContext.put("graph", oldGraph);\r
84                                 }\r
85                             }\r
86                         });\r
87                     } catch (DatabaseException e) {\r
88                         callback.exception(e);\r
89                         return;\r
90                     }\r
91                 else \r
92               env = SCLOsgi.MODULE_REPOSITORY.createRuntimeEnvironment(\r
93                       environmentSpecification,\r
94                       callback.getClass().getClassLoader(), listener);\r
95           callback.execute(env);\r
96    } catch (ImportFailureException e) {\r
97     callback.exception(new DatabaseException(e));\r
98    }\r
99 \r
100      }\r
101         \r
102     };     \r
103 \r
104     // This is needed to prevent garbage collection from collecting UpdateListenerImpls\r
105     // -ModuleRepository only makes a weak reference to the listener\r
106     final static Map<EnvironmentSpecification, UpdateListenerImpl> map = new HashMap<>(); \r
107     \r
108     @Override\r
109     public RuntimeEnvironment perform(ReadGraph graph)\r
110             throws DatabaseException {\r
111         final EnvironmentSpecification environmentSpecification = EnvironmentSpecification.of(\r
112                 "Builtin", "",\r
113                 "Prelude", "",\r
114                 "Simantics/All", "");\r
115         fillEnvironmentSpecification(environmentSpecification);\r
116         \r
117         Layer0 L0 = Layer0.getInstance(graph);\r
118         Collection<Resource> sclModules = graph.syncRequest(new ObjectsWithType(parameter, L0.ConsistsOf, L0.SCLModule));\r
119         for (Resource sclModule : sclModules)\r
120             environmentSpecification.importModule(graph.getURI(sclModule), "");\r
121         \r
122         Resource mainModule = Layer0Utils.getPossibleChild(graph, parameter2, "SCLMain");\r
123         if(mainModule != null)\r
124             environmentSpecification.importModule(graph.getURI(mainModule), "");\r
125         \r
126         return graph.syncRequest(new ParametrizedPrimitiveRead<EnvironmentSpecification, RuntimeEnvironment>(environmentSpecification) {\r
127          \r
128          @Override\r
129          public void register(ReadGraph graph, Listener<RuntimeEnvironment> procedure) {\r
130 \r
131           SCLContext context = SCLContext.getCurrent();\r
132           Object oldGraph = context.put("graph", graph);\r
133           try {\r
134 \r
135            if(procedure.isDisposed()) {\r
136             UpdateListenerImpl.getRuntimeEnvironment(parameter, procedure, null);\r
137            } else {\r
138             UpdateListenerImpl impl = new UpdateListenerImpl(parameter, procedure);\r
139             impl.notifyAboutUpdate();\r
140             map.put(parameter, impl);\r
141            }\r
142 \r
143           } finally {\r
144            context.put("graph", oldGraph);\r
145           }\r
146 \r
147          }\r
148             \r
149             @Override\r
150             public void unregistered() {\r
151              map.remove(parameter);\r
152             }\r
153             \r
154         });\r
155     }\r
156     \r
157     @Override\r
158     public int hashCode() {\r
159         return 31*getClass().hashCode() + super.hashCode();\r
160     }\r
161 \r
162     public static void flush() {\r
163         map.clear();\r
164     }\r
165 \r
166 }