/** * Gracefully terminate the active use of the public methods of this component. This method should * be the last one called on a given instance of this component. * * @exception LifecycleException if this component detects a fatal error that needs to be reported */ public void stop() throws LifecycleException { if (debug >= 1) log("Stopping"); // Validate and update our current component state if (!started) throw new LifecycleException(sm.getString("standardManager.notStarted")); lifecycle.fireLifecycleEvent(STOP_EVENT, null); started = false; // Stop the background reaper thread threadStop(); // Write out sessions try { unload(); } catch (IOException e) { log(sm.getString("standardManager.managerUnload"), e); } // Expire all active sessions Session sessions[] = findSessions(); for (int i = 0; i < sessions.length; i++) { StandardSession session = (StandardSession) sessions[i]; if (!session.isValid()) continue; try { session.expire(); } catch (Throwable t) {; } } // Require a new random number generator if we are restarted this.random = null; }
/** * Load and return the Session associated with the specified session identifier from this Store, * without removing it. If there is no such stored Session, return <code>null</code>. * * @param id Session identifier of the session to load * @exception ClassNotFoundException if a deserialization error occurs * @exception IOException if an input/output error occurs */ @Override public Session load(String id) throws ClassNotFoundException, IOException { // Open an input stream to the specified pathname, if any File file = file(id); if (file == null) { return (null); } if (!file.exists()) { return (null); } if (manager.getContext().getLogger().isDebugEnabled()) { manager .getContext() .getLogger() .debug(sm.getString(getStoreName() + ".loading", id, file.getAbsolutePath())); } ObjectInputStream ois = null; Loader loader = null; ClassLoader classLoader = null; ClassLoader oldThreadContextCL = Thread.currentThread().getContextClassLoader(); try (FileInputStream fis = new FileInputStream(file.getAbsolutePath()); BufferedInputStream bis = new BufferedInputStream(fis)) { Context context = manager.getContext(); if (context != null) loader = context.getLoader(); if (loader != null) classLoader = loader.getClassLoader(); if (classLoader != null) { Thread.currentThread().setContextClassLoader(classLoader); ois = new CustomObjectInputStream(bis, classLoader); } else { ois = new ObjectInputStream(bis); } StandardSession session = (StandardSession) manager.createEmptySession(); session.readObjectData(ois); session.setManager(manager); return (session); } catch (FileNotFoundException e) { if (manager.getContext().getLogger().isDebugEnabled()) manager.getContext().getLogger().debug("No persisted data file found"); return (null); } finally { if (ois != null) { // Close the input stream try { ois.close(); } catch (IOException f) { // Ignore } } Thread.currentThread().setContextClassLoader(oldThreadContextCL); } }
/** * Called by our background reaper thread to check if Sessions saved in our store are subject of * being expired. If so expire the Session and remove it from the Store. */ public void processExpires() { long timeNow = System.currentTimeMillis(); String[] keys = null; if (!started) { return; } try { keys = keys(); } catch (IOException e) { manager.getContainer().getLogger().error("Error getting keys", e); return; } if (manager.getContainer().getLogger().isDebugEnabled()) { manager .getContainer() .getLogger() .debug(getStoreName() + ": processExpires check number of " + keys.length + " sessions"); } for (int i = 0; i < keys.length; i++) { try { StandardSession session = (StandardSession) load(keys[i]); if (session == null) { continue; } int timeIdle = (int) ((timeNow - session.thisAccessedTime) / 1000L); if (timeIdle < session.getMaxInactiveInterval()) { continue; } if (manager.getContainer().getLogger().isDebugEnabled()) { manager .getContainer() .getLogger() .debug(getStoreName() + ": processExpires expire store session " + keys[i]); } if (((PersistentManagerBase) manager).isLoaded(keys[i])) { // recycle old backup session session.recycle(); } else { // expire swapped out session session.expire(); } remove(keys[i]); } catch (Exception e) { manager.getContainer().getLogger().error("Session: " + keys[i] + "; ", e); try { remove(keys[i]); } catch (IOException e2) { manager.getContainer().getLogger().error("Error removing key", e2); } } } }
/** Invalidate all sessions that have expired. */ private void processExpires() { long timeNow = System.currentTimeMillis(); Session sessions[] = findSessions(); for (int i = 0; i < sessions.length; i++) { StandardSession session = (StandardSession) sessions[i]; if (!session.isValid()) continue; int maxInactiveInterval = session.getMaxInactiveInterval(); if (maxInactiveInterval < 0) continue; int timeIdle = // Truncate, do not round up (int) ((timeNow - session.getLastAccessedTime()) / 1000L); if (timeIdle >= maxInactiveInterval) { try { session.expire(); } catch (Throwable t) { log(sm.getString("standardManager.expireException"), t); } } } }
/** * Save the specified Session into this Store. Any previously saved information for the associated * session identifier is replaced. * * @param session Session to be saved * @exception IOException if an input/output error occurs */ @Override public void save(Session session) throws IOException { // Open an output stream to the specified pathname, if any File file = file(session.getIdInternal()); if (file == null) { return; } if (manager.getContext().getLogger().isDebugEnabled()) { manager .getContext() .getLogger() .debug( sm.getString( getStoreName() + ".saving", session.getIdInternal(), file.getAbsolutePath())); } try (FileOutputStream fos = new FileOutputStream(file.getAbsolutePath()); ObjectOutputStream oos = new ObjectOutputStream(new BufferedOutputStream(fos))) { ((StandardSession) session).writeObjectData(oos); } }
/** * Save any currently active sessions in the appropriate persistence mechanism, if any. If * persistence is not supported, this method returns without doing anything. * * @exception IOException if an input/output error occurs */ public void unload() throws IOException { if (debug >= 1) log("Unloading persisted sessions"); // Open an output stream to the specified pathname, if any File file = file(); if (file == null) return; if (debug >= 1) log(sm.getString("standardManager.unloading", pathname)); FileOutputStream fos = null; ObjectOutputStream oos = null; try { fos = new FileOutputStream(file.getAbsolutePath()); oos = new ObjectOutputStream(new BufferedOutputStream(fos)); } catch (IOException e) { log(sm.getString("standardManager.unloading.ioe", e), e); if (oos != null) { try { oos.close(); } catch (IOException f) {; } oos = null; } throw e; } // Write the number of active sessions, followed by the details ArrayList list = new ArrayList(); synchronized (sessions) { if (debug >= 1) log("Unloading " + sessions.size() + " sessions"); try { oos.writeObject(new Integer(sessions.size())); Iterator elements = sessions.values().iterator(); while (elements.hasNext()) { StandardSession session = (StandardSession) elements.next(); list.add(session); session.passivate(); session.writeObjectData(oos); } } catch (IOException e) { log(sm.getString("standardManager.unloading.ioe", e), e); if (oos != null) { try { oos.close(); } catch (IOException f) {; } oos = null; } throw e; } } // Flush and close the output stream try { oos.flush(); oos.close(); oos = null; } catch (IOException e) { if (oos != null) { try { oos.close(); } catch (IOException f) {; } oos = null; } throw e; } // Expire all the sessions we just wrote if (debug >= 1) log("Expiring " + list.size() + " persisted sessions"); Iterator expires = list.iterator(); while (expires.hasNext()) { StandardSession session = (StandardSession) expires.next(); try { session.expire(false); } catch (Throwable t) {; } } if (debug >= 1) log("Unloading complete"); }
/** * Load any currently active sessions that were previously unloaded to the appropriate persistence * mechanism, if any. If persistence is not supported, this method returns without doing anything. * * @exception ClassNotFoundException if a serialized class cannot be found during the reload * @exception IOException if an input/output error occurs */ public void load() throws ClassNotFoundException, IOException { if (debug >= 1) log("Start: Loading persisted sessions"); // Initialize our internal data structures recycled.clear(); sessions.clear(); // Open an input stream to the specified pathname, if any File file = file(); if (file == null) return; if (debug >= 1) log(sm.getString("standardManager.loading", pathname)); FileInputStream fis = null; ObjectInputStream ois = null; Loader loader = null; ClassLoader classLoader = null; try { fis = new FileInputStream(file.getAbsolutePath()); BufferedInputStream bis = new BufferedInputStream(fis); if (container != null) loader = container.getLoader(); if (loader != null) classLoader = loader.getClassLoader(); if (classLoader != null) { if (debug >= 1) log("Creating custom object input stream for class loader " + classLoader); ois = new CustomObjectInputStream(bis, classLoader); } else { if (debug >= 1) log("Creating standard object input stream"); ois = new ObjectInputStream(bis); } } catch (FileNotFoundException e) { if (debug >= 1) log("No persisted data file found"); return; } catch (IOException e) { log(sm.getString("standardManager.loading.ioe", e), e); if (ois != null) { try { ois.close(); } catch (IOException f) {; } ois = null; } throw e; } // Load the previously unloaded active sessions synchronized (sessions) { try { Integer count = (Integer) ois.readObject(); int n = count.intValue(); if (debug >= 1) log("Loading " + n + " persisted sessions"); for (int i = 0; i < n; i++) { StandardSession session = new StandardSession(this); session.readObjectData(ois); session.setManager(this); sessions.put(session.getId(), session); session.activate(); } } catch (ClassNotFoundException e) { log(sm.getString("standardManager.loading.cnfe", e), e); if (ois != null) { try { ois.close(); } catch (IOException f) {; } ois = null; } throw e; } catch (IOException e) { log(sm.getString("standardManager.loading.ioe", e), e); if (ois != null) { try { ois.close(); } catch (IOException f) {; } ois = null; } throw e; } finally { // Close the input stream try { if (ois != null) ois.close(); } catch (IOException f) { // ignored } // Delete the persistent storage file if (file != null && file.exists()) file.delete(); } } if (debug >= 1) log("Finish: Loading persisted sessions"); }
/** * Save a session to the Store. * * @param session the session to be stored * @exception IOException if an input/output error occurs */ public void save(Session session) throws IOException { String saveSql = "INSERT INTO " + sessionTable + " (" + sessionIdCol + ", " + sessionAppCol + ", " + sessionDataCol + ", " + sessionValidCol + ", " + sessionMaxInactiveCol + ", " + sessionLastAccessedCol + ") VALUES (?, ?, ?, ?, ?, ?)"; ObjectOutputStream oos = null; ByteArrayOutputStream bos = null; ByteArrayInputStream bis = null; InputStream in = null; synchronized (this) { Connection _conn = getConnection(); if (_conn == null) { return; } // If sessions already exist in DB, remove and insert again. // TODO: // * Check if ID exists in database and if so use UPDATE. remove(session.getId()); try { bos = new ByteArrayOutputStream(); oos = new ObjectOutputStream(new BufferedOutputStream(bos)); ((StandardSession) session).writeObjectData(oos); oos.close(); byte[] obs = bos.toByteArray(); int size = obs.length; bis = new ByteArrayInputStream(obs, 0, size); in = new BufferedInputStream(bis, size); if (preparedSaveSql == null) { preparedSaveSql = _conn.prepareStatement(saveSql); } preparedSaveSql.setString(1, session.getId()); preparedSaveSql.setString(2, getName()); preparedSaveSql.setBinaryStream(3, in, size); preparedSaveSql.setString(4, session.isValid() ? "1" : "0"); preparedSaveSql.setInt(5, session.getMaxInactiveInterval()); preparedSaveSql.setLong(6, session.getLastAccessedTime()); preparedSaveSql.execute(); } catch (SQLException e) { log(sm.getString(getStoreName() + ".SQLException", e)); } catch (IOException e) {; } finally { if (bis != null) { bis.close(); } if (in != null) { in.close(); } release(_conn); } } if (debug > 0) { log(sm.getString(getStoreName() + ".saving", session.getId(), sessionTable)); } }
/** * Load the Session associated with the id <code>id</code>. If no such session is found <code>null * </code> is returned. * * @param id a value of type <code>String</code> * @return the stored <code>Session</code> * @exception ClassNotFoundException if an error occurs * @exception IOException if an input/output error occurred */ public Session load(String id) throws ClassNotFoundException, IOException { ResultSet rst = null; StandardSession _session = null; Loader loader = null; ClassLoader classLoader = null; ObjectInputStream ois = null; BufferedInputStream bis = null; Container container = manager.getContainer(); String loadSql = "SELECT " + sessionIdCol + ", " + sessionDataCol + " FROM " + sessionTable + " WHERE " + sessionIdCol + " = ? AND " + sessionAppCol + " = ?"; synchronized (this) { Connection _conn = getConnection(); if (_conn == null) { return (null); } try { if (preparedLoadSql == null) { preparedLoadSql = _conn.prepareStatement(loadSql); } preparedLoadSql.setString(1, id); preparedLoadSql.setString(2, getName()); rst = preparedLoadSql.executeQuery(); if (rst.next()) { bis = new BufferedInputStream(rst.getBinaryStream(2)); if (container != null) { loader = container.getLoader(); } if (loader != null) { classLoader = loader.getClassLoader(); } if (classLoader != null) { ois = new CustomObjectInputStream(bis, classLoader); } else { ois = new ObjectInputStream(bis); } if (debug > 0) { log(sm.getString(getStoreName() + ".loading", id, sessionTable)); } _session = (StandardSession) manager.createEmptySession(); _session.readObjectData(ois); _session.setManager(manager); } else if (debug > 0) { log(getStoreName() + ": No persisted data object found"); } } catch (SQLException e) { log(sm.getString(getStoreName() + ".SQLException", e)); } finally { try { if (rst != null) { rst.close(); } } catch (SQLException e) {; } if (ois != null) { try { ois.close(); } catch (IOException e) {; } } release(_conn); } } return (_session); }