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 {
44 private static final boolean SESSION_DEBUG = false;
46 // private final IServerAddress address;
48 private Session session;
50 public static SessionContext create(Session session, boolean initialize) throws DatabaseException {
51 return new SessionContext(session, initialize);
54 private SessionContext(Session session, boolean initialize) throws DatabaseException {
56 initializeSession(session);
57 this.session = session;
60 private void initializeSession(Session s) throws DatabaseException {
61 s.registerService(VirtualGraph.class, s.getService(VirtualGraphSupport.class).getMemoryPersistent(UUID.randomUUID().toString()));
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>() {
67 public Object perform(ReadGraph g) {
68 // Registers Builtins with the ServiceLocator of the Graph's session.
69 Layer0.getInstance(g);
77 // public IServerAddress getAddress() {
82 public Session getSession() {
84 throw new IllegalStateException("SessionContext is disposed");
89 public Session peekSession() {
94 * Do dispose procedures. This method is invoked at most once.
96 protected void doDispose() {
99 } catch (Exception e) {
100 throw new RuntimeException(e);
105 public void close() throws IllegalStateException, InterruptedException, TimeoutException {
108 } catch (RuntimeException e) {
109 Throwable t = e.getCause();
110 if (t instanceof RuntimeException) {
111 throw (RuntimeException) t;
112 } else if (t instanceof Error) {
114 } else if (t instanceof InterruptedException) {
115 throw (InterruptedException) t;
116 } else if (t instanceof TimeoutException) {
117 throw (TimeoutException) t;
123 private void doClose() throws DatabaseException {
124 for (Key k : getHints().keySet()) {
126 Object o = removeHint(k);
127 if (o instanceof IDisposable) {
128 ((IDisposable) o).safeDispose();
133 if (session != null) {
135 System.err.println("Closing session: " + session/*address*/);
138 LifecycleSupport support = session.getService(LifecycleSupport.class);
139 support.close(0, true);
145 public int hashCode() {
146 if (session == null) return 0;
147 return session.hashCode();
151 public boolean equals(Object obj) {
154 if (obj == null || getClass() != obj.getClass())
156 final SessionContext other = (SessionContext) obj;
157 // if (!address.equals(other.address))
159 return session.equals(other.session);
163 public String toString() {
164 StringBuilder s = new StringBuilder();
165 s.append("SessionContext [info=" + session + ", hints=");
166 s.append(Arrays.toString(getHints().values().toArray()));
172 // IDisposable implementation (AbstractDisposable)
174 SyncListenerList<IDisposeListener> disposeListeners = null;
176 private DisposeState disposeStatus = DisposeState.Alive;
178 protected void assertNotDisposed() {
180 throw new AssertionError(this + " is disposed.");
184 public DisposeState getDisposeState() {
185 return disposeStatus;
189 public boolean isDisposed() {
190 return disposeStatus == DisposeState.Disposed;
193 public boolean isAlive() {
194 return disposeStatus == DisposeState.Alive;
198 public void dispose() {
200 synchronized (this) {
201 if (disposeStatus == DisposeState.Disposing)
204 disposeStatus = DisposeState.Disposing;
213 disposeStatus = DisposeState.Disposed;
219 * Disposes if not disposed
222 public void safeDispose() {
224 synchronized (this) {
225 if (disposeStatus != DisposeState.Alive)
227 disposeStatus = DisposeState.Disposing;
236 disposeStatus = DisposeState.Disposed;
241 protected boolean hasDisposeListeners() {
242 return disposeListeners!=null && !disposeListeners.isEmpty();
245 private final static Method onDisposed = SyncListenerList.getMethod(IDisposeListener.class, "onDisposed");
247 private void fireDisposed() {
248 if (disposeListeners==null) return;
249 disposeListeners.fireEventSync(onDisposed, this);
252 @SuppressWarnings("unused")
253 private void fireDisposedAsync() {
254 if (disposeListeners==null) return;
255 disposeListeners.fireEventAsync(onDisposed, this);
259 public void addDisposeListener(IDisposeListener listener) {
260 lazyGetListenerList().add(listener);
264 public void addDisposeListener(IDisposeListener listener, IThreadWorkQueue thread) {
265 lazyGetListenerList().add(thread, listener);
269 public void removeDisposeListener(IDisposeListener listener) {
270 if (disposeListeners==null) return;
271 disposeListeners.remove(listener);
275 public void removeDisposeListener(IDisposeListener listener, IThreadWorkQueue thread) {
276 if (disposeListeners==null) return;
277 disposeListeners.remove(thread, listener);
280 private synchronized SyncListenerList<IDisposeListener> lazyGetListenerList()
282 if (disposeListeners==null)
283 disposeListeners = new SyncListenerList<IDisposeListener>(IDisposeListener.class);
284 return disposeListeners;
288 protected void finalize() throws Throwable {