]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.db.management/src/org/simantics/db/management/SessionContext.java
Playground for Antti.
[simantics/platform.git] / bundles / org.simantics.db.management / src / org / simantics / db / management / SessionContext.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2011 Association for Decentralized Information Management
3  * in Industry THTH ry.
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.db.management;
13
14 import java.lang.reflect.Method;
15 import java.util.Arrays;
16 import java.util.UUID;
17 import java.util.concurrent.TimeoutException;
18
19 import org.simantics.db.Disposable;
20 import org.simantics.db.ReadGraph;
21 import org.simantics.db.Session;
22 import org.simantics.db.VirtualGraph;
23 import org.simantics.db.exception.DatabaseException;
24 import org.simantics.db.request.Read;
25 import org.simantics.db.service.LifecycleSupport;
26 import org.simantics.db.service.VirtualGraphSupport;
27 import org.simantics.layer0.Layer0;
28 import org.simantics.utils.datastructures.disposable.DisposeState;
29 import org.simantics.utils.datastructures.disposable.IDisposable;
30 import org.simantics.utils.datastructures.disposable.IDisposeListener;
31 import org.simantics.utils.datastructures.hints.HintContext;
32 import org.simantics.utils.threads.IThreadWorkQueue;
33 import org.simantics.utils.threads.SyncListenerList;
34
35 /**
36  * Holds all information that is needed to create and manage a single database
37  * session in the Simantics workbench UI.
38  *
39  * @see org.simantics.ui.SimanticsUI
40  * @see org.simantics.db.layer0.util.Simantics
41  * @author Tuukka Lehtonen
42  */
43 public class SessionContext extends HintContext implements ISessionContext, Disposable {
44     private static final boolean    SESSION_DEBUG            = false;
45
46 //    private final IServerAddress        address;
47
48     private Session                 session;
49
50     public static SessionContext create(Session session, boolean initialize) throws DatabaseException {
51         return new SessionContext(session, initialize);
52     }
53
54     private SessionContext(Session session, boolean initialize) throws DatabaseException {
55         if (initialize)
56             initializeSession(session);
57         this.session = session;
58     }
59
60     private void initializeSession(Session s) throws DatabaseException {
61         s.registerService(VirtualGraph.class, s.getService(VirtualGraphSupport.class).getMemoryPersistent(UUID.randomUUID().toString()));
62
63         // Builtins needs to be initialized for the new session before
64         // anything useful can be done with it.
65         s.syncRequest(new Read<Object>() {
66             @Override
67             public Object perform(ReadGraph g) {
68                 // Registers Builtins with the ServiceLocator of the Graph's session.
69                 Layer0.getInstance(g);
70                 return null;
71             }
72         });
73         
74     }
75
76 //    @Override
77 //    public IServerAddress getAddress() {
78 //        return address;
79 //    }
80
81     @Override
82     public Session getSession() {
83         if (session == null)
84             throw new IllegalStateException("SessionContext is disposed");
85         return session;
86     }
87
88     @Override
89     public Session peekSession() {
90         return session;
91     }
92
93     /**
94      * Do dispose procedures. This method is invoked at most once.
95      */
96     protected void doDispose() {
97         try {
98             doClose();
99         } catch (Exception e) {
100             throw new RuntimeException(e);
101         }
102     }
103
104     @Override
105     public void close() throws IllegalStateException, InterruptedException, TimeoutException {
106         try {
107             dispose();
108         } catch (RuntimeException e) {
109             Throwable t = e.getCause();
110             if (t instanceof RuntimeException) {
111                 throw (RuntimeException) t;
112             } else if (t instanceof Error) {
113                 throw (Error) t;
114             } else if (t instanceof InterruptedException) {
115                 throw (InterruptedException) t;
116             } else if (t instanceof TimeoutException) {
117                 throw (TimeoutException) t;
118             }
119             throw e;
120         }
121     }
122
123     private void doClose() throws DatabaseException {
124         for (Key k : getHints().keySet()) {
125             if (k != null) {
126                 Object o = removeHint(k);
127                 if (o instanceof IDisposable) {
128                     ((IDisposable) o).safeDispose();
129                 }
130             }
131         }
132
133         if (session != null) {
134             if (SESSION_DEBUG) {
135                 System.err.println("Closing session: " + session/*address*/);
136                 System.err.flush();
137             }
138             LifecycleSupport support = session.getService(LifecycleSupport.class);
139             support.close(0, true);
140             session = null;
141         }
142     }
143
144     @Override
145     public int hashCode() {
146         if (session == null) return 0;
147         return session.hashCode();
148     }
149
150     @Override
151     public boolean equals(Object obj) {
152         if (this == obj)
153             return true;
154         if (obj == null || getClass() != obj.getClass())
155             return false;
156         final SessionContext other = (SessionContext) obj;
157 //        if (!address.equals(other.address))
158 //            return false;
159         return session.equals(other.session);
160     }
161
162     @Override
163     public String toString() {
164         StringBuilder s = new StringBuilder();
165         s.append("SessionContext [info=" + session + ", hints=");
166         s.append(Arrays.toString(getHints().values().toArray()));
167         s.append("]");
168         return s.toString();
169     }
170
171
172     // IDisposable implementation (AbstractDisposable)
173
174     SyncListenerList<IDisposeListener> disposeListeners = null;
175
176     private DisposeState disposeStatus = DisposeState.Alive;
177
178     protected void assertNotDisposed() {
179         if (isDisposed())
180             throw new AssertionError(this + " is disposed.");
181     }
182
183     @Override
184     public DisposeState getDisposeState() {
185         return disposeStatus;
186     }
187
188     @Override
189     public boolean isDisposed() {
190         return disposeStatus == DisposeState.Disposed;
191     }
192
193     public boolean isAlive() {
194         return disposeStatus == DisposeState.Alive;
195     }
196
197     @Override
198     public void dispose() {
199         try {
200             synchronized (this) {
201                 if (disposeStatus == DisposeState.Disposing)
202                     return;
203                 assertNotDisposed();
204                 disposeStatus = DisposeState.Disposing;
205             }
206             try {
207                 fireDisposed();
208             } finally {
209                 doDispose();
210             }
211         } finally {
212             synchronized(this) {
213                 disposeStatus = DisposeState.Disposed;
214             }
215         }
216     }
217
218     /**
219      * Disposes if not disposed
220      */
221     @Override
222     public void safeDispose() {
223         try {
224             synchronized (this) {
225                 if (disposeStatus != DisposeState.Alive)
226                     return;
227                 disposeStatus = DisposeState.Disposing;
228             }
229             try {
230                 fireDisposed();
231             } finally {
232                 doDispose();
233             }
234         } finally {
235             synchronized(this) {
236                 disposeStatus = DisposeState.Disposed;
237             }
238         }
239     }
240
241     protected boolean hasDisposeListeners() {
242         return disposeListeners!=null && !disposeListeners.isEmpty();
243     }
244
245     private final static Method onDisposed = SyncListenerList.getMethod(IDisposeListener.class, "onDisposed");
246
247     private void fireDisposed() {
248         if (disposeListeners==null) return;
249         disposeListeners.fireEventSync(onDisposed, this);
250     }
251
252     @SuppressWarnings("unused")
253     private void fireDisposedAsync() {
254         if (disposeListeners==null) return;
255         disposeListeners.fireEventAsync(onDisposed, this);
256     }
257
258     @Override
259     public void addDisposeListener(IDisposeListener listener) {
260         lazyGetListenerList().add(listener);
261     }
262
263     @Override
264     public void addDisposeListener(IDisposeListener listener, IThreadWorkQueue thread) {
265         lazyGetListenerList().add(thread, listener);
266     }
267
268     @Override
269     public void removeDisposeListener(IDisposeListener listener) {
270         if (disposeListeners==null) return;
271         disposeListeners.remove(listener);
272     }
273
274     @Override
275     public void removeDisposeListener(IDisposeListener listener, IThreadWorkQueue thread) {
276         if (disposeListeners==null) return;
277         disposeListeners.remove(thread, listener);
278     }
279
280     private synchronized SyncListenerList<IDisposeListener> lazyGetListenerList()
281     {
282         if (disposeListeners==null)
283             disposeListeners = new SyncListenerList<IDisposeListener>(IDisposeListener.class);
284         return disposeListeners;
285     }
286
287     @Override
288     protected void finalize() throws Throwable {
289         try {
290             safeDispose();
291         } finally {
292             super.finalize();
293         }
294     }
295
296 }