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