1 /*******************************************************************************
2 * Copyright (c) 2007, 2011 Association for Decentralized Information Management
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
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.db.management;
14 import java.lang.reflect.Method;
15 import java.util.Arrays;
16 import java.util.UUID;
17 import java.util.concurrent.TimeoutException;
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;
36 * Holds all information that is needed to create and manage a single database
37 * session in the Simantics workbench UI.
39 * @see org.simantics.ui.SimanticsUI
40 * @see org.simantics.db.layer0.util.Simantics
41 * @author Tuukka Lehtonen
43 public class SessionContext extends HintContext implements ISessionContext, Disposable {
45 private static final boolean SESSION_DEBUG = false;
47 private Session session;
49 public static SessionContext create(Session session, boolean initialize) throws DatabaseException {
50 return new SessionContext(session, initialize);
53 private SessionContext(Session session, boolean initialize) throws DatabaseException {
55 initializeSession(session);
56 this.session = session;
59 private void initializeSession(Session s) throws DatabaseException {
60 s.registerService(VirtualGraph.class, s.getService(VirtualGraphSupport.class).getMemoryPersistent(UUID.randomUUID().toString()));
62 // Builtins needs to be initialized for the new session before
63 // anything useful can be done with it.
64 s.syncRequest(new Read<Object>() {
66 public Object perform(ReadGraph g) {
67 // Registers Builtins with the ServiceLocator of the Graph's session.
68 Layer0.getInstance(g);
76 public Session getSession() {
78 throw new IllegalStateException("SessionContext is disposed");
83 public Session peekSession() {
88 * Do dispose procedures. This method is invoked at most once.
90 protected void doDispose() {
93 } catch (Exception e) {
94 throw new RuntimeException(e);
99 public void close() throws IllegalStateException, InterruptedException, TimeoutException {
102 } catch (RuntimeException e) {
103 Throwable t = e.getCause();
104 if (t instanceof RuntimeException) {
105 throw (RuntimeException) t;
106 } else if (t instanceof Error) {
108 } else if (t instanceof InterruptedException) {
109 throw (InterruptedException) t;
110 } else if (t instanceof TimeoutException) {
111 throw (TimeoutException) t;
117 private void doClose() throws DatabaseException {
118 for (Key k : getHints().keySet()) {
120 Object o = removeHint(k);
121 if (o instanceof IDisposable) {
122 ((IDisposable) o).safeDispose();
127 if (session != null) {
129 System.err.println("Closing session: " + session/*address*/);
132 LifecycleSupport support = session.getService(LifecycleSupport.class);
133 support.close(0, true);
139 public int hashCode() {
140 if (session == null) return 0;
141 return session.hashCode();
145 public boolean equals(Object obj) {
148 if (obj == null || getClass() != obj.getClass())
150 final SessionContext other = (SessionContext) obj;
151 // if (!address.equals(other.address))
153 return session.equals(other.session);
157 public String toString() {
158 StringBuilder s = new StringBuilder();
159 s.append("SessionContext [info=" + session + ", hints=");
160 s.append(Arrays.toString(getHints().values().toArray()));
166 // IDisposable implementation (AbstractDisposable)
168 SyncListenerList<IDisposeListener> disposeListeners = null;
170 private DisposeState disposeStatus = DisposeState.Alive;
172 protected void assertNotDisposed() {
174 throw new AssertionError(this + " is disposed.");
178 public DisposeState getDisposeState() {
179 return disposeStatus;
183 public boolean isDisposed() {
184 return disposeStatus == DisposeState.Disposed;
187 public boolean isAlive() {
188 return disposeStatus == DisposeState.Alive;
192 public void dispose() {
194 synchronized (this) {
195 if (disposeStatus == DisposeState.Disposing)
198 disposeStatus = DisposeState.Disposing;
207 disposeStatus = DisposeState.Disposed;
213 * Disposes if not disposed
216 public void safeDispose() {
218 synchronized (this) {
219 if (disposeStatus != DisposeState.Alive)
221 disposeStatus = DisposeState.Disposing;
230 disposeStatus = DisposeState.Disposed;
235 protected boolean hasDisposeListeners() {
236 return disposeListeners!=null && !disposeListeners.isEmpty();
239 private final static Method onDisposed = SyncListenerList.getMethod(IDisposeListener.class, "onDisposed");
241 private void fireDisposed() {
242 if (disposeListeners==null) return;
243 disposeListeners.fireEventSync(onDisposed, this);
246 @SuppressWarnings("unused")
247 private void fireDisposedAsync() {
248 if (disposeListeners==null) return;
249 disposeListeners.fireEventAsync(onDisposed, this);
253 public void addDisposeListener(IDisposeListener listener) {
254 lazyGetListenerList().add(listener);
258 public void addDisposeListener(IDisposeListener listener, IThreadWorkQueue thread) {
259 lazyGetListenerList().add(thread, listener);
263 public void removeDisposeListener(IDisposeListener listener) {
264 if (disposeListeners==null) return;
265 disposeListeners.remove(listener);
269 public void removeDisposeListener(IDisposeListener listener, IThreadWorkQueue thread) {
270 if (disposeListeners==null) return;
271 disposeListeners.remove(thread, listener);
274 private synchronized SyncListenerList<IDisposeListener> lazyGetListenerList()
276 if (disposeListeners==null)
277 disposeListeners = new SyncListenerList<IDisposeListener>(IDisposeListener.class);
278 return disposeListeners;
282 protected void finalize() throws Throwable {