--- /dev/null
+package org.simantics.acorn;
+
+import java.nio.file.Path;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.simantics.db.Database;
+import org.simantics.db.Session;
+import org.simantics.db.SessionErrorHandler;
+import org.simantics.db.SessionManager;
+import org.simantics.db.SessionReference;
+import org.simantics.db.authentication.UserAuthenticationAgent;
+import org.simantics.db.common.utils.Logger;
+import org.simantics.db.event.SessionEvent;
+import org.simantics.db.event.SessionListener;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.service.LifecycleSupport;
+import org.simantics.utils.datastructures.ListenerList;
+
+import fi.vtt.simantics.procore.internal.SessionImplDb;
+import fi.vtt.simantics.procore.internal.SessionImplSocket;
+
+public class AcornSessionManagerImpl implements SessionManager {
+
+ private static AcornSessionManagerImpl INSTANCE;
+
+ private ConcurrentHashMap<SessionImplSocket, SessionImplSocket> sessionMap = new ConcurrentHashMap<SessionImplSocket, SessionImplSocket>();
+ private ListenerList<SessionListener> sessionListeners = new ListenerList<SessionListener>(SessionListener.class);
+ private SessionErrorHandler errorHandler;
+
+ private Database database;
+
+ private AcornSessionManagerImpl() {}
+
+ void finish() {
+ sessionMap = null;
+ sessionListeners = null;
+ }
+
+ @Override
+ public void addSessionListener(SessionListener listener) {
+ sessionListeners.add(listener);
+ }
+
+ @Override
+ public Session createSession(SessionReference sessionReference, UserAuthenticationAgent authAgent)
+ throws DatabaseException {
+ SessionImplDb sessionImpl = new SessionImplDb(this, authAgent);
+ boolean ok = false;
+ try {
+ Path dbFolder = sessionReference.getServerReference().getDBFolder();
+ database = AcornDatabaseManager.getDatabase(dbFolder);
+ Database.Session dbSession = database.newSession(sessionImpl);
+ sessionImpl.connect(sessionReference, dbSession);
+ sessionMap.put(sessionImpl, sessionImpl);
+ fireSessionOpened(sessionImpl);
+ ok = true;
+ } catch (Throwable e) {
+ Logger.defaultLogError("Connection failed. See exception for details.", e);
+ try {
+ fireSessionClosed(sessionImpl, e);
+ sessionMap.remove(sessionImpl);
+ sessionImpl = null;
+ } catch (Throwable t) {
+ }
+ throw new DatabaseException(e);
+ } finally {
+ if (!ok && null != sessionImpl)
+ sessionImpl.getService(LifecycleSupport.class).close();
+ }
+ return sessionImpl;
+ }
+
+ @Override
+ public void removeSessionListener(SessionListener listener) {
+ sessionListeners.remove(listener);
+ }
+
+ private void fireSessionOpened(SessionImplSocket session) {
+ SessionEvent se = new SessionEvent(session, null);
+ for (SessionListener listener : sessionListeners.getListeners()) {
+ listener.sessionOpened(se);
+ }
+ }
+
+ private void fireSessionClosed(SessionImplSocket session, Throwable cause) {
+ SessionEvent se = new SessionEvent(session, cause);
+ for (SessionListener listener : sessionListeners.getListeners()) {
+ listener.sessionClosed(se);
+ }
+ }
+
+ @Override
+ public void shutdown(Session s, Throwable cause) {
+ SessionImplSocket sis = sessionMap.get(s);
+ if (null == sis)
+ return;
+ try {
+ fireSessionClosed(sis, cause);
+ } finally {
+ sessionMap.remove(s);
+ }
+ }
+
+ @Override
+ public SessionErrorHandler getErrorHandler() {
+ return errorHandler;
+ }
+
+ @Override
+ public void setErrorHandler(SessionErrorHandler errorHandler) {
+ this.errorHandler = errorHandler;
+ }
+
+ public synchronized static AcornSessionManagerImpl getInstance() {
+ if (INSTANCE == null)
+ INSTANCE = new AcornSessionManagerImpl();
+ return INSTANCE;
+ }
+
+ @Override
+ public Database getDatabase() {
+ return database;
+ }
+
+}