]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.acorn/src/org/simantics/acorn/AcornSessionManagerImpl.java
Merge commit '2a46c55'
[simantics/platform.git] / bundles / org.simantics.acorn / src / org / simantics / acorn / AcornSessionManagerImpl.java
1 package org.simantics.acorn;
2
3 import java.nio.file.Path;
4 import java.util.concurrent.ConcurrentHashMap;
5
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;
19
20 import fi.vtt.simantics.procore.internal.SessionImplDb;
21 import fi.vtt.simantics.procore.internal.SessionImplSocket;
22
23 public class AcornSessionManagerImpl implements SessionManager {
24
25     private static AcornSessionManagerImpl INSTANCE;
26     
27     private ConcurrentHashMap<SessionImplDb, Database.Session> sessionMap = new ConcurrentHashMap<>();
28     private ListenerList<SessionListener> sessionListeners = new ListenerList<>(SessionListener.class);
29     private SessionErrorHandler errorHandler;
30
31         private Database database;
32
33     private AcornSessionManagerImpl() {}
34     
35     void finish() {
36         sessionMap = null;
37         sessionListeners = null;
38     }
39
40     @Override
41     public void addSessionListener(SessionListener listener) {
42         sessionListeners.add(listener);
43     }
44
45     @Override
46     public Session createSession(SessionReference sessionReference, UserAuthenticationAgent authAgent)
47     throws DatabaseException {
48         SessionImplDb sessionImpl = new SessionImplDb(this, authAgent);
49         boolean ok = false;
50         try {
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);
57             ok = true;
58         } catch (Throwable e) {
59             Logger.defaultLogError("Connection failed. See exception for details.", e);
60             try {
61                 fireSessionClosed(sessionImpl, e);
62                 sessionMap.remove(sessionImpl);
63                 sessionImpl = null;
64             } catch (Throwable t) {
65             }
66             throw new DatabaseException(e);
67         } finally {
68             if (!ok && null != sessionImpl)
69                 sessionImpl.getService(LifecycleSupport.class).close();
70         }
71         return sessionImpl;
72     }
73
74     @Override
75     public void removeSessionListener(SessionListener listener) {
76         sessionListeners.remove(listener);
77     }
78
79     private void fireSessionOpened(SessionImplSocket session) {
80         SessionEvent se = new SessionEvent(session, null);
81         for (SessionListener listener : sessionListeners.getListeners()) {
82                listener.sessionOpened(se);
83         }
84     }
85
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);
90         }
91     }
92
93     @Override
94     public void shutdown(Session s, Throwable cause) {
95         SessionImplSocket sis = (SessionImplSocket) s;
96         if (null == sis)
97             return;
98         try {
99             fireSessionClosed(sis, cause);
100         } finally {
101             sessionMap.remove(s);
102         }
103     }
104
105     @Override
106     public SessionErrorHandler getErrorHandler() {
107         return errorHandler;
108     }
109
110     @Override
111     public void setErrorHandler(SessionErrorHandler errorHandler) {
112         this.errorHandler = errorHandler;
113     }
114
115     public synchronized static AcornSessionManagerImpl getInstance() {
116         if (INSTANCE == null)
117             INSTANCE = new AcornSessionManagerImpl();
118         return INSTANCE;
119     }
120
121     @Override
122     public Database getDatabase() {
123         return database;
124     }
125
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;
131     }
132 }