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