1 package org.simantics.acorn;
3 import java.nio.file.Path;
4 import java.util.concurrent.ConcurrentHashMap;
6 import org.simantics.db.Database;
7 import org.simantics.db.Session;
8 import org.simantics.db.SessionErrorHandler;
9 import org.simantics.db.SessionManager;
10 import org.simantics.db.SessionReference;
11 import org.simantics.db.authentication.UserAuthenticationAgent;
12 import org.simantics.db.common.utils.Logger;
13 import org.simantics.db.event.SessionEvent;
14 import org.simantics.db.event.SessionListener;
15 import org.simantics.db.exception.DatabaseException;
16 import org.simantics.db.exception.RuntimeDatabaseException;
17 import org.simantics.db.service.LifecycleSupport;
18 import org.simantics.utils.datastructures.ListenerList;
20 import fi.vtt.simantics.procore.internal.SessionImplDb;
21 import fi.vtt.simantics.procore.internal.SessionImplSocket;
23 public class AcornSessionManagerImpl implements SessionManager {
25 private static AcornSessionManagerImpl INSTANCE;
27 private ConcurrentHashMap<SessionImplDb, Database.Session> sessionMap = new ConcurrentHashMap<>();
28 private ListenerList<SessionListener> sessionListeners = new ListenerList<>(SessionListener.class);
29 private SessionErrorHandler errorHandler;
31 private Database database;
33 private AcornSessionManagerImpl() {}
37 sessionListeners = null;
41 public void addSessionListener(SessionListener listener) {
42 sessionListeners.add(listener);
46 public Session createSession(SessionReference sessionReference, UserAuthenticationAgent authAgent)
47 throws DatabaseException {
48 SessionImplDb sessionImpl = new SessionImplDb(this, authAgent);
51 Path dbFolder = sessionReference.getServerReference().getDBFolder();
52 database = AcornDatabaseManager.getDatabase(dbFolder);
53 Database.Session dbSession = database.newSession(sessionImpl);
54 sessionImpl.connect(sessionReference, dbSession);
55 sessionMap.put(sessionImpl, dbSession);
56 fireSessionOpened(sessionImpl);
58 } catch (Throwable e) {
59 Logger.defaultLogError("Connection failed. See exception for details.", e);
61 fireSessionClosed(sessionImpl, e);
62 sessionMap.remove(sessionImpl);
64 } catch (Throwable t) {
66 throw new DatabaseException(e);
68 if (!ok && null != sessionImpl)
69 sessionImpl.getService(LifecycleSupport.class).close();
75 public void removeSessionListener(SessionListener listener) {
76 sessionListeners.remove(listener);
79 private void fireSessionOpened(SessionImplSocket session) {
80 SessionEvent se = new SessionEvent(session, null);
81 for (SessionListener listener : sessionListeners.getListeners()) {
82 listener.sessionOpened(se);
86 private void fireSessionClosed(SessionImplSocket session, Throwable cause) {
87 SessionEvent se = new SessionEvent(session, cause);
88 for (SessionListener listener : sessionListeners.getListeners()) {
89 listener.sessionClosed(se);
94 public void shutdown(Session s, Throwable cause) {
95 SessionImplSocket sis = (SessionImplSocket) s;
99 fireSessionClosed(sis, cause);
101 sessionMap.remove(s);
106 public SessionErrorHandler getErrorHandler() {
111 public void setErrorHandler(SessionErrorHandler errorHandler) {
112 this.errorHandler = errorHandler;
115 public synchronized static AcornSessionManagerImpl getInstance() {
116 if (INSTANCE == null)
117 INSTANCE = new AcornSessionManagerImpl();
122 public Database getDatabase() {
126 public GraphClientImpl2 getClient() {
127 if (sessionMap.values().size() > 1)
128 throw new RuntimeDatabaseException("Currently only one GraphClientImpl2 per session is supported!");
129 org.simantics.db.Database.Session client = sessionMap.values().iterator().next();
130 return (GraphClientImpl2) client;