001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com) 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * For further information about Alkacon Software GmbH & Co. KG, please see the 018 * company website: http://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: http://www.opencms.org 022 * 023 * You should have received a copy of the GNU Lesser General Public 024 * License along with this library; if not, write to the Free Software 025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 026 */ 027 028package org.opencms.main; 029 030import org.opencms.util.CmsCollectionsGenericWrapper; 031import org.opencms.util.CmsUUID; 032 033import java.util.ArrayList; 034import java.util.ConcurrentModificationException; 035import java.util.Iterator; 036import java.util.List; 037import java.util.Map; 038 039import org.apache.commons.collections.FastHashMap; 040 041/** 042 * The default session storage provider implementation.<p> 043 * 044 * Implementation based on a {@link FastHashMap}.<p> 045 * 046 * @since 6.5.5 047 */ 048public class CmsDefaultSessionStorageProvider implements I_CmsSessionStorageProvider { 049 050 /** Stores the session info objects mapped to the session id. */ 051 private FastHashMap m_sessions; 052 053 /** 054 * @see org.opencms.main.I_CmsSessionStorageProvider#get(org.opencms.util.CmsUUID) 055 */ 056 public CmsSessionInfo get(CmsUUID sessionId) { 057 058 return (CmsSessionInfo)m_sessions.get(sessionId); 059 } 060 061 /** 062 * @see org.opencms.main.I_CmsSessionStorageProvider#getAll() 063 */ 064 public List<CmsSessionInfo> getAll() { 065 066 return getAllOfUser(null); 067 } 068 069 /** 070 * @see org.opencms.main.I_CmsSessionStorageProvider#getAllOfUser(org.opencms.util.CmsUUID) 071 */ 072 public List<CmsSessionInfo> getAllOfUser(CmsUUID userId) { 073 074 try { 075 return getAllSelected(CmsCollectionsGenericWrapper.<CmsUUID, CmsSessionInfo> map(m_sessions), userId); 076 } catch (ConcurrentModificationException e) { 077 // try again with a clone this time 078 return getAllSelected( 079 CmsCollectionsGenericWrapper.<CmsUUID, CmsSessionInfo> map(m_sessions.clone()), 080 userId); 081 } 082 } 083 084 /** 085 * @see org.opencms.main.I_CmsSessionStorageProvider#getSize() 086 */ 087 public int getSize() { 088 089 return m_sessions.size(); 090 } 091 092 /** 093 * @see org.opencms.main.I_CmsSessionStorageProvider#initialize() 094 */ 095 public void initialize() { 096 097 // create a map for all sessions, these will be mapped using their session id 098 m_sessions = new FastHashMap(); 099 // set to "fast" mode (will be reset for write access) 100 m_sessions.setFast(true); 101 } 102 103 /** 104 * @see org.opencms.main.I_CmsSessionStorageProvider#put(org.opencms.main.CmsSessionInfo) 105 */ 106 public CmsSessionInfo put(CmsSessionInfo sessionInfo) { 107 108 return (CmsSessionInfo)m_sessions.put(sessionInfo.getSessionId(), sessionInfo); 109 } 110 111 /** 112 * @see org.opencms.main.I_CmsSessionStorageProvider#remove(org.opencms.util.CmsUUID) 113 */ 114 public CmsSessionInfo remove(CmsUUID sessionId) { 115 116 return (CmsSessionInfo)m_sessions.remove(sessionId); 117 } 118 119 /** 120 * @see org.opencms.main.I_CmsSessionStorageProvider#shutdown() 121 */ 122 public void shutdown() { 123 124 m_sessions.clear(); 125 m_sessions = null; 126 } 127 128 /** 129 * @see org.opencms.main.I_CmsSessionStorageProvider#validate() 130 */ 131 public void validate() { 132 133 try { 134 // change session map to full synchronization or "slow" mode 135 m_sessions.setFast(false); 136 Iterator<Map.Entry<CmsUUID, CmsSessionInfo>> sessions = CmsCollectionsGenericWrapper.<CmsUUID, CmsSessionInfo> map( 137 m_sessions).entrySet().iterator(); 138 while (sessions.hasNext()) { 139 Map.Entry<CmsUUID, CmsSessionInfo> entry = sessions.next(); 140 CmsUUID sessionId = entry.getKey(); 141 CmsSessionInfo sessionInfo = entry.getValue(); 142 if ((sessionInfo != null) && (m_sessions.get(sessionId) != null)) { 143 // may be the case in case of concurrent modification 144 if (sessionInfo.isExpired()) { 145 // session is invalid, try to remove it 146 try { 147 sessions.remove(); 148 } catch (ConcurrentModificationException ex) { 149 // ignore, better luck next time... 150 } 151 } 152 } 153 } 154 } catch (ConcurrentModificationException ex) { 155 // CME can also be triggered from the Iterator#next() method. 156 // ignore, better luck next time... 157 } finally { 158 // it may be null during shutdown 159 if (m_sessions != null) { 160 // reset session map to "fast" mode 161 m_sessions.setFast(true); 162 } 163 } 164 } 165 166 /** 167 * Returns all sessions or all sessions matching the user id from the provided Map.<p> 168 * 169 * @param allSessions the Map of existing sessions 170 * @param userId the id of the user, if null all sessions will be returned 171 * 172 * @return all sessions or all sessions matching the user id from the provided Map 173 */ 174 private List<CmsSessionInfo> getAllSelected(Map<CmsUUID, CmsSessionInfo> allSessions, CmsUUID userId) { 175 176 List<CmsSessionInfo> userSessions = new ArrayList<CmsSessionInfo>(); 177 Iterator<Map.Entry<CmsUUID, CmsSessionInfo>> i = allSessions.entrySet().iterator(); 178 while (i.hasNext()) { 179 Map.Entry<CmsUUID, CmsSessionInfo> entry = i.next(); 180 CmsSessionInfo sessionInfo = entry.getValue(); 181 if ((sessionInfo != null) && ((userId == null) || userId.equals(sessionInfo.getUserId()))) { 182 // sessionInfo == null may be the case in case of concurrent modification 183 userSessions.add(sessionInfo); 184 } 185 } 186 return userSessions; 187 } 188}