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.io.IOException;
15 import java.lang.reflect.Method;
16 import java.util.Arrays;
17 import java.util.UUID;
18 import java.util.concurrent.TimeoutException;
20 import org.eclipse.core.runtime.IStatus;
21 import org.simantics.db.Disposable;
22 import org.simantics.db.ReadGraph;
23 import org.simantics.db.ServerReference;
24 import org.simantics.db.Session;
25 import org.simantics.db.SessionManager;
26 import org.simantics.db.SessionReference;
27 import org.simantics.db.VirtualGraph;
28 import org.simantics.db.authentication.UserAuthenticationAgent;
29 import org.simantics.db.common.processor.MergingDelayedWriteProcessor;
30 import org.simantics.db.common.processor.MergingGraphRequestProcessor;
31 import org.simantics.db.common.request.ReadRequest;
32 import org.simantics.db.exception.DatabaseException;
33 import org.simantics.db.exception.InternalException;
34 import org.simantics.db.management.internal.Activator;
35 import org.simantics.db.service.LifecycleSupport;
36 import org.simantics.db.service.VirtualGraphSupport;
37 import org.simantics.db.services.GlobalServiceInitializer;
38 import org.simantics.layer0.Layer0;
39 import org.simantics.utils.datastructures.disposable.DisposeState;
40 import org.simantics.utils.datastructures.disposable.IDisposable;
41 import org.simantics.utils.datastructures.disposable.IDisposeListener;
42 import org.simantics.utils.datastructures.hints.HintContext;
43 import org.simantics.utils.threads.IThreadWorkQueue;
44 import org.simantics.utils.threads.SyncListenerList;
46 import fi.vtt.simantics.procore.ProCoreServerReference;
47 import fi.vtt.simantics.procore.ProCoreSessionReference;
48 import fi.vtt.simantics.procore.SessionManagerSource;
51 * Holds all information that is needed to create and manage a single database
52 * session in the Simantics workbench UI.
54 * @see org.simantics.ui.SimanticsUI
55 * @see org.simantics.db.layer0.util.Simantics
56 * @author Tuukka Lehtonen
58 public class SessionContext extends HintContext implements ISessionContext, Disposable {
59 private static final boolean SESSION_DEBUG = false;
61 // private final IServerAddress address;
63 private Session session;
65 private UserAuthenticationAgent authenticator;
67 private boolean servicesRegistered = false;
69 private IStatus servicesRegisteredStatus = null;
71 public static SessionContext create(Session session, boolean initialize) throws DatabaseException {
72 return new SessionContext(session, initialize);
75 // public static SessionContext openSession(IServerAddress info, UserAuthenticationAgent auth) throws IOException, DatabaseException {
76 // return new SessionContext(info, auth, false);
79 // public static SessionContext openAndInitializeSession(IServerAddress info, UserAuthenticationAgent auth) throws IOException, DatabaseException {
80 // return new SessionContext(info, auth, true);
83 private static SessionReference createSessionReference(/*IServerAddress address,*/ long sessionId) throws InternalException {
84 ProCoreServerReference server = new ProCoreServerReference();
85 ProCoreSessionReference ref = new ProCoreSessionReference(server, sessionId);
89 // private SessionContext(IServerAddress addr, UserAuthenticationAgent auth, boolean initialize) throws IOException, DatabaseException {
91 // throw new IllegalArgumentException("null address");
92 //// this.address = addr;
93 // this.authenticator = auth;
95 // SessionManager sessionManager = SessionManagerProvider.getInstance().getSessionManager();
98 // initializeSession(sessionManager);
99 // if (SESSION_DEBUG) {
100 // System.err.println("Initialized session: " + addr);
101 // System.err.flush();
104 // SessionReference ref = createSessionReference(SessionManagerSource.NullSessionId);
105 // this.session = sessionManager.createSession(ref, auth);
106 // if (SESSION_DEBUG) {
107 // System.err.println("Opened session: " + addr);
108 // System.err.flush();
114 private SessionContext(Session session, boolean initialize) throws DatabaseException {
116 initializeSession(session);
117 ServerReference ref = session.getService( LifecycleSupport.class ).getSessionReference().getServerReference();
118 // this.address = ref.serverAddress();
119 this.session = session;
122 private void initializeSession(SessionManager sessionManager) throws DatabaseException, IOException {
124 boolean success = false;
126 SessionReference ref = createSessionReference(SessionManagerSource.NullSessionId);
127 s = sessionManager.createSession(ref, authenticator);
128 initializeSession(s);
134 LifecycleSupport support = s.getService(LifecycleSupport.class);
141 private void initializeSession(Session s) throws DatabaseException {
142 s.registerService(MergingGraphRequestProcessor.class, new MergingGraphRequestProcessor("SessionService", s, 20));
143 s.registerService(MergingDelayedWriteProcessor.class, new MergingDelayedWriteProcessor(s, 20));
144 s.registerService(VirtualGraph.class, s.getService(VirtualGraphSupport.class).getMemoryPersistent(UUID.randomUUID().toString()));
146 // Builtins needs to be initialized for the new session before
147 // anything useful can be done with it.
148 s.syncRequest(new ReadRequest() {
150 public void run(ReadGraph g) {
151 // Registers Builtins with the ServiceLocator of the Graph's session.
152 Layer0.getInstance(g);
157 public void registerServices() {
158 if (servicesRegistered)
161 // Register any services available for the SessionLocator of the new
163 servicesRegisteredStatus = new GlobalServiceInitializer().initialize(session);
164 if (!servicesRegisteredStatus.isOK()) {
165 Activator.getDefault().getLog().log(servicesRegisteredStatus);
168 servicesRegistered = true;
172 // public IServerAddress getAddress() {
177 public Session getSession() {
179 throw new IllegalStateException("SessionContext is disposed");
184 public Session peekSession() {
189 * Do dispose procedures. This method is invoked at most once.
191 protected void doDispose() {
194 } catch (Exception e) {
195 throw new RuntimeException(e);
200 public void close() throws IllegalStateException, InterruptedException, TimeoutException {
203 } catch (RuntimeException e) {
204 Throwable t = e.getCause();
205 if (t instanceof RuntimeException) {
206 throw (RuntimeException) t;
207 } else if (t instanceof Error) {
209 } else if (t instanceof InterruptedException) {
210 throw (InterruptedException) t;
211 } else if (t instanceof TimeoutException) {
212 throw (TimeoutException) t;
218 private void doClose() throws DatabaseException {
219 for (Key k : getHints().keySet()) {
221 Object o = removeHint(k);
222 if (o instanceof IDisposable) {
223 ((IDisposable) o).safeDispose();
228 if (session != null) {
230 System.err.println("Closing session: " + session/*address*/);
233 LifecycleSupport support = session.getService(LifecycleSupport.class);
234 support.close(0, true);
240 public int hashCode() {
241 if (session == null) return 0;
242 return session.hashCode();
246 public boolean equals(Object obj) {
249 if (obj == null || getClass() != obj.getClass())
251 final SessionContext other = (SessionContext) obj;
252 // if (!address.equals(other.address))
254 return session.equals(other.session);
258 public String toString() {
259 StringBuilder s = new StringBuilder();
260 s.append("SessionContext [info=" + session + ", hints=");
261 s.append(Arrays.toString(getHints().values().toArray()));
267 // IDisposable implementation (AbstractDisposable)
269 SyncListenerList<IDisposeListener> disposeListeners = null;
271 private DisposeState disposeStatus = DisposeState.Alive;
273 protected void assertNotDisposed() {
275 throw new AssertionError(this + " is disposed.");
279 public DisposeState getDisposeState() {
280 return disposeStatus;
284 public boolean isDisposed() {
285 return disposeStatus == DisposeState.Disposed;
288 public boolean isAlive() {
289 return disposeStatus == DisposeState.Alive;
293 public void dispose() {
295 synchronized (this) {
296 if (disposeStatus == DisposeState.Disposing)
299 disposeStatus = DisposeState.Disposing;
308 disposeStatus = DisposeState.Disposed;
314 * Disposes if not disposed
317 public void safeDispose() {
319 synchronized (this) {
320 if (disposeStatus != DisposeState.Alive)
322 disposeStatus = DisposeState.Disposing;
331 disposeStatus = DisposeState.Disposed;
336 protected boolean hasDisposeListeners() {
337 return disposeListeners!=null && !disposeListeners.isEmpty();
340 private final static Method onDisposed = SyncListenerList.getMethod(IDisposeListener.class, "onDisposed");
342 private void fireDisposed() {
343 if (disposeListeners==null) return;
344 disposeListeners.fireEventSync(onDisposed, this);
347 @SuppressWarnings("unused")
348 private void fireDisposedAsync() {
349 if (disposeListeners==null) return;
350 disposeListeners.fireEventAsync(onDisposed, this);
354 public void addDisposeListener(IDisposeListener listener) {
355 lazyGetListenerList().add(listener);
359 public void addDisposeListener(IDisposeListener listener, IThreadWorkQueue thread) {
360 lazyGetListenerList().add(thread, listener);
364 public void removeDisposeListener(IDisposeListener listener) {
365 if (disposeListeners==null) return;
366 disposeListeners.remove(listener);
370 public void removeDisposeListener(IDisposeListener listener, IThreadWorkQueue thread) {
371 if (disposeListeners==null) return;
372 disposeListeners.remove(thread, listener);
375 private synchronized SyncListenerList<IDisposeListener> lazyGetListenerList()
377 if (disposeListeners==null)
378 disposeListeners = new SyncListenerList<IDisposeListener>(IDisposeListener.class);
379 return disposeListeners;
383 protected void finalize() throws Throwable {