001: /* Copyright (c) 2001-2005, The HSQL Development Group
002: * All rights reserved.
003: *
004: * Redistribution and use in source and binary forms, with or without
005: * modification, are permitted provided that the following conditions are met:
006: *
007: * Redistributions of source code must retain the above copyright notice, this
008: * list of conditions and the following disclaimer.
009: *
010: * Redistributions in binary form must reproduce the above copyright notice,
011: * this list of conditions and the following disclaimer in the documentation
012: * and/or other materials provided with the distribution.
013: *
014: * Neither the name of the HSQL Development Group nor the names of its
015: * contributors may be used to endorse or promote products derived from this
016: * software without specific prior written permission.
017: *
018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
020: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
021: * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
022: * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
023: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
024: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
025: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
026: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
027: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
028: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029: */
030:
031: package org.hsqldb;
032:
033: import org.hsqldb.lib.IntKeyHashMap;
034: import org.hsqldb.lib.Iterator;
035: import org.hsqldb.SchemaManager.Schema;
036:
037: /**
038: * Container that maintains a map of session id's to Session objects.
039: * Responsible for managing opening and closing of sessions.
040: *
041: * @author fredt@users
042: * @version 1.8.0
043: * @since 1.7.2
044: */
045: public class SessionManager {
046:
047: int sessionIdCount = 1;
048: private IntKeyHashMap sessionMap = new IntKeyHashMap();
049: private Session sysSession;
050:
051: // TODO:
052: //
053: // Eliminate the Database-centric nature of SessionManager.
054: // e.g. Sessions should be able to migrate from one Database instance
055: // to another using session control language moderated by
056: // SessionManager
057:
058: /**
059: * Constructs an new SessionManager handling the specified Database.
060: * Creates a SYS User.
061: */
062: public SessionManager(Database db) {
063:
064: User sysUser = db.getUserManager().getSysUser();
065:
066: sysSession = new Session(db, sysUser, false, false, 0);
067: }
068:
069: // TODO:
070: //
071: // It should be possible to create an initially 'disconnected' Session that
072: // can execute general commands using a SessionCommandInterpreter.
073: //
074: // EXAMPLES: Open a Session to start a Server, add/remove
075: // databases hosted by an existing Server, connect to a
076: // Database...
077: //
078: // REQUIRES: auth scheme independent of any particular Database instance
079: // e.g. provide service to use /etc/passwd and /etc/groups,
080: // JAAS-plugin, etc.
081:
082: /**
083: * Binds the specified Session object into this SessionManager's active
084: * Session registry. This method is typically called internally from
085: * {@link
086: * Database#connect(String,String) Database.connect(username,password)}
087: * as the final step, when a successful connection has been made.
088: *
089: * @param db the database to which the new Session is initially connected
090: * @param user the initial Session User
091: * @param readonly the initial ReadOnly attribute for the new Session
092: */
093: public synchronized Session newSession(Database db, User user,
094: boolean readonly, boolean forlog) {
095:
096: Session s = new Session(db, user, true, readonly,
097: sessionIdCount);
098:
099: s.isProcessingLog = forlog;
100:
101: if (!forlog && sessionMap.isEmpty()) {
102: HsqlException[] warnings = sysSession.getAndClearWarnings();
103:
104: for (int i = 0; i < warnings.length; i++) {
105: s.addWarning(warnings[i]);
106: }
107: }
108:
109: sessionMap.put(sessionIdCount, s);
110:
111: sessionIdCount++;
112:
113: return s;
114: }
115:
116: /**
117: * Retrieves the special SYS Session.
118: *
119: * @return the special SYS Session
120: */
121: public Session getSysSession(String schema, boolean forScript)
122: throws HsqlException {
123:
124: sysSession.currentSchema = sysSession.database.schemaManager
125: .getSchemaHsqlName(schema);
126: sysSession.isProcessingScript = forScript;
127: sysSession.isProcessingLog = false;
128:
129: sysSession.setUser(sysSession.database.getUserManager()
130: .getSysUser());
131:
132: return sysSession;
133: }
134:
135: /**
136: * Retrieves the special SYS Session.
137: *
138: * @return the special SYS Session
139: */
140: public Session getSysSession() {
141:
142: sysSession.currentSchema = sysSession.database.schemaManager.defaultSchemaHsqlName;
143: sysSession.isProcessingScript = false;
144: sysSession.isProcessingLog = false;
145:
146: sysSession.setUser(sysSession.database.getUserManager()
147: .getSysUser());
148:
149: return sysSession;
150: }
151:
152: /**
153: * Retrieves the special SYS Session.
154: *
155: * @return the special SYS Session
156: */
157: public Session getSysSession(String schema, User user)
158: throws HsqlException {
159:
160: sysSession.currentSchema = sysSession.database.schemaManager
161: .getSchemaHsqlName(schema);
162: sysSession.isProcessingScript = false;
163: sysSession.isProcessingLog = false;
164:
165: sysSession.setUser(user);
166:
167: return sysSession;
168: }
169:
170: /** @todo sig change should be either: closeAllSessions(Database) or closeAllSessions(dbID) */
171:
172: /**
173: * Closes all Sessions registered with this SessionManager.
174: */
175: public synchronized void closeAllSessions() {
176:
177: // don't disconnect system user; need it to save database
178: Session[] sessions = getAllSessions();
179:
180: for (int i = 0; i < sessions.length; i++) {
181: sessions[i].close();
182: }
183: }
184:
185: /**
186: * Removes the session from management and disconnects.
187: *
188: * @param session to disconnect
189: */
190: synchronized void removeSession(Session session) {
191: sessionMap.remove(session.getId());
192: }
193:
194: /**
195: * Removes all Sessions registered with this SessionManager.
196: */
197: synchronized void clearAll() {
198: sessionMap.clear();
199: }
200:
201: /**
202: * Returns true if no session exists beyond the sys session.
203: */
204: synchronized boolean isEmpty() {
205: return sessionMap.isEmpty();
206: }
207:
208: /**
209: * Retrieves a list of the Sessions in this container that
210: * are visible to the specified Session, given the access rights of
211: * the Session User.
212: *
213: * @param session The Session determining visibility
214: * @return the Sessions visible to the specified Session
215: */
216: synchronized Session[] getVisibleSessions(Session session) {
217: return session.isAdmin() ? getAllSessions()
218: : new Session[] { session };
219: }
220:
221: /**
222: * Retrieves the Session with the specified Session identifier or null
223: * if no such Session is registered with this SessionManager.
224: */
225: synchronized Session getSession(int id) {
226: return (Session) sessionMap.get(id);
227: }
228:
229: public synchronized Session[] getAllSessions() {
230:
231: Session[] sessions = new Session[sessionMap.size()];
232: Iterator it = sessionMap.values().iterator();
233:
234: for (int i = 0; it.hasNext(); i++) {
235: sessions[i] = (Session) it.next();
236: }
237:
238: return sessions;
239: }
240:
241: public synchronized boolean isUserActive(String userName) {
242:
243: Iterator it = sessionMap.values().iterator();
244:
245: for (int i = 0; it.hasNext(); i++) {
246: Session session = (Session) it.next();
247:
248: if (userName.equals(session.getUser().getName())) {
249: return true;
250: }
251: }
252:
253: return false;
254: }
255:
256: public synchronized void removeSchemaReference(Schema schema) {
257:
258: Iterator it = sessionMap.values().iterator();
259:
260: for (int i = 0; it.hasNext(); i++) {
261: Session session = (Session) it.next();
262:
263: if (session.currentSchema == schema.name) {
264: session.resetSchema();
265: }
266: }
267: }
268: }
|