001: /*
002: * This file is part of PFIXCORE.
003: *
004: * PFIXCORE is free software; you can redistribute it and/or modify
005: * it under the terms of the GNU Lesser General Public License as published by
006: * the Free Software Foundation; either version 2 of the License, or
007: * (at your option) any later version.
008: *
009: * PFIXCORE is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
012: * GNU Lesser General Public License for more details.
013: *
014: * You should have received a copy of the GNU Lesser General Public License
015: * along with PFIXCORE; if not, write to the Free Software
016: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
017: *
018: */
019:
020: package de.schlund.pfixxml.serverutil;
021:
022: import java.io.IOException;
023: import java.lang.management.ManagementFactory;
024: import java.util.ArrayList;
025: import java.util.HashMap;
026: import java.util.Iterator;
027: import java.util.LinkedList;
028: import java.util.List;
029: import java.util.Set;
030:
031: import javax.management.MBeanServer;
032: import javax.management.ObjectName;
033: import javax.servlet.http.HttpSession;
034: import javax.servlet.http.HttpSessionBindingEvent;
035: import javax.servlet.http.HttpSessionBindingListener;
036:
037: import org.apache.log4j.Logger;
038:
039: /**
040: *
041: *
042: */
043:
044: public class SessionAdmin implements HttpSessionBindingListener,
045: SessionAdminMBean {
046:
047: public static String LISTENER = "__SESSION_LISTENER__";
048: public static String PARENT_SESS_ID = "__PARENT_SESSION_ID__";
049: public static final String SESSION_IS_SECURE = "__SESSION_IS_SECURE__";
050: private static SessionAdmin instance = new SessionAdmin();
051: private static final Logger LOG = Logger
052: .getLogger(SessionAdmin.class);
053: /** Maps session to it's id. */
054: private HashMap<HttpSession, String> sessionid = new HashMap<HttpSession, String>();
055: private HashMap<String, SessionInfoStruct> sessioninfo = new HashMap<String, SessionInfoStruct>();
056: private HashMap<String, HttpSession> parentinfo = new HashMap<String, HttpSession>();
057: private HashMap<String, String> parentinfo_rev = new HashMap<String, String>();
058:
059: private SessionAdmin() {
060: try {
061: MBeanServer mbeanServer = ManagementFactory
062: .getPlatformMBeanServer();
063: ObjectName objectName = new ObjectName(
064: "Pustefix:type=SessionAdmin");
065: mbeanServer.registerMBean(this , objectName);
066: } catch (Exception x) {
067: LOG.error("Can't register SessionAdmin MBean!", x);
068: }
069: }
070:
071: public String toString() {
072: return "[Number of active Sessions: "
073: + sessioninfo.keySet().size() + "]";
074: }
075:
076: public void registerSession(HttpSession sess, String serverName,
077: String remoteAddr) {
078: registerSession(sess, null, serverName, remoteAddr);
079: }
080:
081: /**
082: * Register a new session.
083: * @param session the session to register.
084: * @param trailog a trailog from another session.
085: * @param conutil.
086: */
087: public void registerSession(HttpSession session,
088: LinkedList<SessionInfoStruct.TrailElement> trailog,
089: String serverName, String remoteAddr) {
090: SessionInfoStruct info = new SessionInfoStruct(session,
091: trailog, serverName, remoteAddr);
092:
093: synchronized (sessioninfo) {
094: session.setAttribute(LISTENER, this );
095: sessionid.put(session, session.getId());
096: sessioninfo.put(session.getId(), info);
097: }
098: synchronized (parentinfo) {
099: synchronized (parentinfo_rev) {
100: String parentid = (String) session
101: .getAttribute(PARENT_SESS_ID);
102: if (parentid != null && !parentid.equals("")) {
103: parentinfo.put(parentid, session);
104: parentinfo_rev.put(session.getId(), parentid);
105: }
106: }
107: }
108: }
109:
110: public boolean idWasParentSession(String id) {
111: synchronized (parentinfo) {
112: if (parentinfo.get(id) != null) {
113: return true;
114: } else {
115: return false;
116: }
117: }
118: }
119:
120: public HttpSession getChildSessionForParentId(String id) {
121: synchronized (parentinfo) {
122: return (HttpSession) parentinfo.get(id);
123: }
124: }
125:
126: public void valueBound(HttpSessionBindingEvent event) {
127: }
128:
129: public void valueUnbound(HttpSessionBindingEvent event) {
130: HttpSession session = event.getSession();
131: synchronized (sessioninfo) {
132: // CAUTITION: as of Tomcat 5.5.10, session.getId throws an exception
133: // (see http://issues.apache.org/bugzilla/show_bug.cgi?id=36994)
134: // This is why we need the sessionid maps.
135: String id = sessionid.get(session);
136: SessionInfoStruct sessinf = sessioninfo.get(id);
137: if (sessinf != null) {
138: synchronized (parentinfo) {
139: synchronized (parentinfo_rev) {
140: String parentid = (String) parentinfo_rev
141: .get(id);
142: if (parentid != null) {
143: parentinfo.remove(parentid);
144: parentinfo_rev.remove(id);
145: LOG
146: .debug("\n\n********* Removed parentid mapping "
147: + parentid
148: + "->"
149: + id
150: + " *********\n");
151: }
152: }
153: }
154: }
155: sessioninfo.remove(id);
156: sessionid.remove(session);
157: LOG.debug("\n\n********* Invalidated Session " + id
158: + " *********\n");
159: }
160: }
161:
162: public void touchSession(String servlet, String stylesheet,
163: HttpSession sess) {
164: synchronized (sessioninfo) {
165: SessionInfoStruct info = (SessionInfoStruct) sessioninfo
166: .get(sess.getId());
167: if (info != null) {
168: info.updateTimestamp(servlet, stylesheet);
169: } else {
170: LOG.warn("*** SessionInfoStruct for Session " + sess
171: + " was NULL!!!");
172: }
173: }
174: }
175:
176: public Set<String> getAllSessionIds() {
177: return sessioninfo.keySet();
178: }
179:
180: public int getSessionNumber() {
181: return sessioninfo.size();
182: }
183:
184: public SessionInfoStruct getInfo(HttpSession sess) {
185: synchronized (sessioninfo) {
186: return ((SessionInfoStruct) sessioninfo.get(sess.getId()));
187: }
188: }
189:
190: public SessionInfoStruct getInfo(String sessid) {
191: synchronized (sessioninfo) {
192: return ((SessionInfoStruct) sessioninfo.get(sessid));
193: }
194: }
195:
196: public static SessionAdmin getInstance() {
197: return instance;
198: }
199:
200: public String getExternalSessionId(HttpSession session) {
201: String result = "NOSUCHSESSION";
202: if (session != null) {
203: Boolean secure = (Boolean) session
204: .getAttribute(SESSION_IS_SECURE);
205: String parentid = (String) session
206: .getAttribute(PARENT_SESS_ID);
207: if (secure != null && secure.booleanValue()
208: && parentid != null) {
209: result = parentid;
210: } else if (secure == null || !secure.booleanValue()) {
211: result = session.getId();
212: }
213: }
214: return result;
215: }
216:
217: //accessible via JMX:
218:
219: public List<SessionData> getSessions(String serverName,
220: String remoteAddr) {
221: SessionAdmin admin;
222: Iterator<String> iter;
223: String id;
224: List<SessionData> lst;
225: SessionInfoStruct info;
226:
227: lst = new ArrayList<SessionData>();
228: admin = SessionAdmin.getInstance();
229: iter = admin.getAllSessionIds().iterator();
230: while (iter.hasNext()) {
231: id = (String) iter.next();
232: info = admin.getInfo(id);
233: if (serverName.equals(info.getData().getServerName())
234: && remoteAddr
235: .equals(info.getData().getRemoteAddr())) {
236: lst.add(info.getData());
237: }
238: }
239: return lst;
240: }
241:
242: public void invalidateSession(String id) throws IOException {
243: getSession(id).invalidate();
244: }
245:
246: public HttpSession getSession(String id) throws IOException {
247: SessionInfoStruct info = getInfo(id);
248: if (info == null) {
249: throw new IOException("session not found: " + id);
250: }
251: return info.getSession();
252: }
253:
254: }
|