| /* Copyright (c) 2001-2010, The HSQL Development Group |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are met: |
| * |
| * Redistributions of source code must retain the above copyright notice, this |
| * list of conditions and the following disclaimer. |
| * |
| * Redistributions in binary form must reproduce the above copyright notice, |
| * this list of conditions and the following disclaimer in the documentation |
| * and/or other materials provided with the distribution. |
| * |
| * Neither the name of the HSQL Development Group nor the names of its |
| * contributors may be used to endorse or promote products derived from this |
| * software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG, |
| * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| |
| package org.hsqldb; |
| |
| import org.hsqldb.HsqlNameManager.HsqlName; |
| import org.hsqldb.lib.Iterator; |
| import org.hsqldb.lib.LongKeyHashMap; |
| import org.hsqldb.rights.User; |
| |
| /** |
| * Container that maintains a map of session id's to Session objects. |
| * Responsible for managing opening and closing of sessions. |
| * |
| * @author Fred Toussi (fredt@users dot sourceforge.net) |
| * @version 1.9.0 |
| * @since 1.7.2 |
| */ |
| public class SessionManager { |
| |
| long sessionIdCount = 0; |
| private LongKeyHashMap sessionMap = new LongKeyHashMap(); |
| private Session sysSession; |
| private Session sysLobSession; |
| |
| /** |
| * @todo: |
| * Eliminate the Database-centric nature of SessionManager. |
| * e.g. Sessions should be able to migrate from one Database instance |
| * to another using session control language moderated by SessionManager |
| */ |
| |
| /** |
| * Constructs an new SessionManager handling the specified Database. |
| * Creates a SYS User. |
| */ |
| public SessionManager(Database db) { |
| |
| User sysUser = db.getUserManager().getSysUser(); |
| |
| sysSession = new Session(db, sysUser, false, false, sessionIdCount++, |
| null, 0); |
| sysLobSession = new Session(db, sysUser, true, false, |
| sessionIdCount++, null, 0); |
| } |
| |
| /** |
| * @todo: |
| * It should be possible to create an initially 'disconnected' Session that |
| * can execute general commands using a SessionCommandInterpreter. |
| * |
| * EXAMPLES: Open a Session to start a Server, add/remove |
| * databases hosted by an existing Server, connect to a |
| * Database... |
| * |
| * REQUIRES: auth scheme independent of any particular Database instance |
| * e.g. provide service to use /etc/passwd and /etc/groups, |
| * JAAS-plugin, etc. |
| */ |
| |
| /** |
| * Binds the specified Session object into this SessionManager's active |
| * Session registry. This method is typically called internally as |
| * the final step, when a successful connection has been made. |
| * |
| * @param db the database to which the new Session is initially connected |
| * @param user the Session User |
| * @param readonly the ReadOnly attribute for the new Session |
| * @param forLog true when session is for reading a log |
| * @param timeZoneSeconds the session time zone second interval |
| * @return Session |
| */ |
| public synchronized Session newSession(Database db, User user, |
| boolean readonly, boolean forLog, |
| String zoneString, |
| int timeZoneSeconds) { |
| |
| Session s = new Session(db, user, !forLog, readonly, sessionIdCount, |
| zoneString, timeZoneSeconds); |
| |
| s.isProcessingLog = forLog; |
| |
| sessionMap.put(sessionIdCount, s); |
| |
| sessionIdCount++; |
| |
| return s; |
| } |
| |
| /** |
| * Retrieves a new SYS Session. |
| */ |
| public Session getSysSessionForScript(Database db) { |
| |
| Session session = new Session(db, db.getUserManager().getSysUser(), |
| false, false, 0, null, 0); |
| |
| session.isProcessingScript = true; |
| |
| return session; |
| } |
| |
| public Session getSysLobSession() { |
| return sysLobSession; |
| } |
| |
| /** |
| * Retrieves the common SYS Session. |
| */ |
| public Session getSysSession() { |
| |
| sysSession.currentSchema = |
| sysSession.database.schemaManager.getDefaultSchemaHsqlName(); |
| sysSession.isProcessingScript = false; |
| sysSession.isProcessingLog = false; |
| |
| sysSession.setUser(sysSession.database.getUserManager().getSysUser()); |
| |
| return sysSession; |
| } |
| |
| /** |
| * Retrieves the common SYS Session. |
| */ |
| public Session getSysSession(String schema, User user) { |
| |
| sysSession.currentSchema = |
| sysSession.database.schemaManager.getSchemaHsqlName(schema); |
| sysSession.isProcessingScript = false; |
| sysSession.isProcessingLog = false; |
| |
| sysSession.setUser(user); |
| |
| return sysSession; |
| } |
| |
| public Session newSysSession(HsqlName schema, User user) { |
| |
| Session session = new Session(sysSession.database, user, false, false, |
| 0, null, 0); |
| |
| session.currentSchema = schema; |
| |
| return session; |
| } |
| |
| /** |
| * Closes all Sessions registered with this SessionManager. |
| */ |
| public synchronized void closeAllSessions() { |
| |
| // don't disconnect system user; need it to save database |
| Session[] sessions = getAllSessions(); |
| |
| for (int i = 0; i < sessions.length; i++) { |
| sessions[i].close(); |
| } |
| } |
| |
| /** |
| * Removes the session from management and disconnects. |
| */ |
| synchronized void removeSession(Session session) { |
| sessionMap.remove(session.getId()); |
| } |
| |
| /** |
| * Removes all Sessions registered with this SessionManager. |
| */ |
| synchronized void clearAll() { |
| sessionMap.clear(); |
| } |
| |
| /** |
| * Returns true if no session exists beyond the sys session. |
| */ |
| synchronized boolean isEmpty() { |
| return sessionMap.isEmpty(); |
| } |
| |
| /** |
| * Retrieves a list of the Sessions in this container that |
| * are visible to the specified Session, given the access rights of |
| * the Session User. |
| */ |
| public synchronized Session[] getVisibleSessions(Session session) { |
| return session.isAdmin() ? getAllSessions() |
| : new Session[]{ session }; |
| } |
| |
| /** |
| * Retrieves the Session with the specified Session identifier or null |
| * if no such Session is registered with this SessionManager. |
| */ |
| synchronized Session getSession(long id) { |
| return (Session) sessionMap.get(id); |
| } |
| |
| public synchronized Session[] getAllSessions() { |
| |
| Session[] sessions = new Session[sessionMap.size()]; |
| Iterator it = sessionMap.values().iterator(); |
| |
| for (int i = 0; it.hasNext(); i++) { |
| sessions[i] = (Session) it.next(); |
| } |
| |
| return sessions; |
| } |
| |
| public synchronized boolean isUserActive(String userName) { |
| |
| Iterator it = sessionMap.values().iterator(); |
| |
| for (int i = 0; it.hasNext(); i++) { |
| Session session = (Session) it.next(); |
| |
| if (userName.equals(session.getUser().getNameString())) { |
| return true; |
| } |
| } |
| |
| return false; |
| } |
| |
| public synchronized void removeSchemaReference(Schema schema) { |
| |
| Iterator it = sessionMap.values().iterator(); |
| |
| for (int i = 0; it.hasNext(); i++) { |
| Session session = (Session) it.next(); |
| |
| if (session.getCurrentSchemaHsqlName() == schema.getName()) { |
| session.resetSchema(); |
| } |
| } |
| } |
| |
| public synchronized void resetLoggedSchemas() { |
| |
| Iterator it = sessionMap.values().iterator(); |
| |
| for (int i = 0; it.hasNext(); i++) { |
| Session session = (Session) it.next(); |
| |
| session.loggedSchema = null; |
| } |
| |
| this.sysLobSession.loggedSchema = null; |
| } |
| } |