package org.jboss.web.tomcat.tc5.session;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.Session;
import org.apache.catalina.session.StandardManager;
import org.apache.catalina.Context;
import org.apache.catalina.Globals;
import org.jboss.mx.util.MBeanProxyExt;
import org.jboss.mx.util.MBeanServerLocator;
import org.jboss.ha.httpsession.interfaces.SerializableHttpSession;
import org.jboss.ha.httpsession.server.ClusteredHTTPSessionServiceMBean;
import java.io.IOException;
import javax.ejb.EJBException;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Cookie;
import org.jboss.logging.Logger;
import org.jboss.metadata.WebMetaData;
public class JBossManagerCMP
extends StandardManager
implements AbstractJBossManager, JBossManagerCMPMBean
{
private static final String info = "JBossManagerCMP/1.0";
private static Logger log = Logger.getLogger(JBossManagerCMP.class);
private ClusteredHTTPSessionServiceMBean proxy;
private ObjectName clusteredHttpServiceName;
protected ObjectName objectName;
protected boolean started = false;
private boolean useLocalCache = true;
protected int invalidateSessionPolicy = WebMetaData.SESSION_INVALIDATE_SET_AND_NON_PRIMITIVE_GET;
protected int replicationType = WebMetaData.REPLICATION_TYPE_SYNC;
public JBossManagerCMP()
{
}
public void init(String name, WebMetaData webMetaData, boolean useJK, boolean useLocalCache)
throws ClusteringNotSupportedException
{
this.useLocalCache = useLocalCache;
setDistributable(true);
this.invalidateSessionPolicy = webMetaData.getInvalidateSessionPolicy();
this.replicationType = webMetaData.getReplicationType();
try
{
clusteredHttpServiceName = new ObjectName("jboss", "service", "ClusteredHttpSession");
proxy = (ClusteredHTTPSessionServiceMBean) MBeanProxyExt.create(ClusteredHTTPSessionServiceMBean.class, clusteredHttpServiceName);
}
catch (Throwable e)
{
log.info("ClusteredHTTPSessionService not found");
throw new ClusteringNotSupportedException("ClusteredHTTPSessionService not found");
}
try
{
proxy.setSessionTimeout(14400000);
objectName = new ObjectName("jboss.web:service=ClusterManager,WebModule=" + name);
log.info("ClusteredHTTPSessionService found");
}
catch (Throwable e)
{
log.error("Could not create ObjectName", e);
throw new ClusteringNotSupportedException(e.toString());
}
}
public boolean isUseLocalCache()
{
return useLocalCache;
}
public Integer getLocalActiveSessionCount()
{
return new Integer(sessions.size());
}
public ClusteredSession[] getSessions()
{
ClusteredSession[] sess = new ClusteredSession[0];
synchronized (sessions)
{
sess = (ClusteredSession[]) sessions.values().toArray(sess);
}
return sess;
}
public int getInvalidateSessionPolicy()
{
return this.invalidateSessionPolicy;
}
public int getReplicationType()
{
return replicationType;
}
public Session createSession()
{
ClusteredSessionCMP session = new ClusteredSessionCMP(this);
session.setNew(true);
session.setCreationTime(System.currentTimeMillis());
session.setMaxInactiveInterval(this.maxInactiveInterval);
String sessionId = this.getNextId();
String jvmRoute = this.getJvmRoute();
if (jvmRoute != null)
{
sessionId += '.' + jvmRoute;
}
session.setValid(true);
session.setId(sessionId);
return session;
}
public String getJvmRouteId(String id)
{
String sessid = null;
if (id != null)
{
if (this.getJvmRoute() != null)
{
if (!this.getJvmRoute().equals(id.substring(id.indexOf('.') + 1, id.length())))
{
sessid = id.substring(0, id.indexOf('.') + 1) + this.getJvmRoute();
log.debug("JvmRoute id is :" + sessid);
}
else
{
return id;
}
}
}
return sessid;
}
public void setSessionCookie(String sessionId)
{
HttpServletResponse response = (HttpServletResponse) ClusteredSessionValve.responseThreadLocal.get();
setNewSessionCookie(sessionId, response);
}
public void setNewSessionCookie(String sessionId, HttpServletResponse response)
{
if (response != null)
{
Context context = (Context) container;
if (context.getCookies())
{
Cookie newCookie = new Cookie(Globals.SESSION_COOKIE_NAME, sessionId);
if (log.isDebugEnabled())
{
log.debug("Setting cookie with session id:" + sessionId + " & name:" + Globals.SESSION_COOKIE_NAME);
}
newCookie.setMaxAge(-1);
newCookie.setPath(context.getPath());
response.addCookie(newCookie);
}
}
}
public Session findSession(String id) throws IOException
{
ClusteredSessionCMP session = null;
if (id == null)
{
return null;
}
log.debug("Looking for session with id=" + id);
if (useLocalCache)
{
synchronized (sessions)
{
session = (ClusteredSessionCMP) sessions.get(id);
}
if (session == null && this.getJvmRoute() != null)
{
String key = getJvmRouteId(id);
synchronized (sessions)
{
session = (ClusteredSessionCMP) sessions.get(key);
}
if (session != null)
{
setSessionCookie(session.getId());
}
}
if (session == null)
{
session = loadSession(id);
if (session == null && this.getJvmRoute() != null)
{
session = loadSession(getJvmRouteId(id));
}
if (session != null)
{
if (this.getJvmRoute() != null)
{
String sessionid = getJvmRouteId(id);
session.setId(sessionid);
setSessionCookie(sessionid);
}
else
{
log.debug("Found in distributed store - adding to local store");
add(session);
}
}
}
}
else
{
session = loadSession(id);
if (session == null && this.getJvmRoute() != null)
{
String sessionId = this.getJvmRouteId(id);
session = loadSession(sessionId);
if (session != null)
{
session.setId(sessionId);
setSessionCookie(sessionId);
id = sessionId;
}
}
if (session != null)
{
synchronized (sessions)
{
sessions.put(id, session);
}
}
}
if (session != null)
{
log.debug("Found");
}
return session;
}
public void add(Session session)
{
if (session == null)
{
return;
}
if (!session.isValid())
{
log.error("Cannot add session with id=" + session.getId() + " because it is invalid");
return;
}
if (session instanceof ClusteredSessionCMP)
{
synchronized (sessions)
{
sessions.put(session.getId(), session);
try
{
storeSession(session);
}
catch (Exception e)
{
log.error("Adding a session to the clustered store failed", e);
}
log.debug("Session with id=" + session.getId() + " added");
}
}
else
{
throw new IllegalArgumentException("You can only add ClusteredSessionCMPs to this Manager");
}
}
public void remove(Session session)
{
if (session == null)
{
return;
}
synchronized (sessions)
{
try
{
removeSession(session.getId());
}
catch (Exception e)
{
log.warn("Removing a session from the clustered store failed", e);
}
sessions.remove(session.getId());
log.debug("Session with id=" + session.getId() + " removed");
}
}
public void removeLocal(Session session)
{
if (session == null)
{
return;
}
synchronized (sessions)
{
sessions.remove(session.getId());
}
}
public void removeLocal(String id)
{
if (id == null)
{
return;
}
synchronized (sessions)
{
sessions.remove(id);
}
}
protected void recycle(Session session)
{
}
public String getInfo()
{
return info;
}
public void start() throws LifecycleException
{
startManager();
}
public void stop() throws LifecycleException
{
stopManager();
}
protected void startManager() throws LifecycleException
{
log.info("Starting");
if (started)
throw new LifecycleException
(sm.getString("standardManager.alreadyStarted"));
lifecycle.fireLifecycleEvent(START_EVENT, null);
started = true;
try
{
MBeanServer server = MBeanServerLocator.locateJBoss();
server.registerMBean(this, objectName);
}
catch (Exception e)
{
log.error("Could not register ClusterManagerMBean to MBeanServer", e);
}
}
protected void stopManager() throws LifecycleException
{
log.info("Stopping");
if (!started)
throw new LifecycleException
(sm.getString("standardManager.notStarted"));
lifecycle.fireLifecycleEvent(STOP_EVENT, null);
started = false;
try
{
MBeanServer server = MBeanServerLocator.locateJBoss();
server.unregisterMBean(objectName);
}
catch (Exception e)
{
log.error("Could not unregister ClusterManagerMBean from MBeanServer", e);
}
}
public void load() throws ClassNotFoundException, IOException
{
}
public void unload() throws IOException
{
}
public void run()
{
}
private String getNextId()
{
return proxy.getSessionId();
}
public boolean storeSession(Session session)
{
if (session == null)
{
return false;
}
if (session.isValid())
{
ClusteredSessionCMP cmpSession = (ClusteredSessionCMP) session;
cmpSession.passivate();
if (log.isDebugEnabled())
{
log.debug("Replicating session with id " + session.getId());
}
if (!cmpSession.isReplicationTypeAlreadySet())
cmpSession.setReplicationTypeForSession(this.replicationType);
proxy.setHttpSession(session.getId(), (SerializableHttpSession) session);
}
return true;
}
protected ClusteredSessionCMP loadSession(String id)
{
ClusteredSessionCMP session = null;
if (id == null)
{
return null;
}
try
{
ClassLoader ctxCL = super.getContainer().getLoader().getClassLoader();
session = (ClusteredSessionCMP) proxy.getHttpSession(id, ctxCL);
if (session != null)
{
session.initAfterLoad(this);
}
}
catch (EJBException e)
{
log.debug("Loading a session out of the clustered store failed", e);
}
return session;
}
protected void removeSession(String id)
{
if (id == null)
{
return;
}
try
{
proxy.removeHttpSession(id);
}
catch (EJBException e)
{
log.debug("Removing a session out of the clustered store failed", e);
}
}
public void processExpires()
{
long timeNow = System.currentTimeMillis();
Session sessions[] = findSessions();
log.debug("Looking for sessions that have expired");
for (int i = 0; i < sessions.length; ++i)
{
ClusteredSessionCMP session = (ClusteredSessionCMP) sessions[i];
if (!session.isValid())
{
continue;
}
int maxInactiveInterval = session.getMaxInactiveInterval();
if (maxInactiveInterval < 0)
{
continue;
}
int timeIdle =
(int) ((timeNow - session.getLastAccessedTime()) / 1000L);
if (timeIdle >= maxInactiveInterval)
{
try
{
log.debug("Session with id = " + session.getId() + " has expired on local node");
ClusteredSessionCMP clusteredSession = loadSession(session.getId());
if (clusteredSession != null)
{
int timeIdleCluster =
(int) ((timeNow - clusteredSession.getLastAccessedTime()) / 1000L);
if (timeIdleCluster < maxInactiveInterval)
{
log.debug("Session " + session.getId() + " has only expired on local node but is alive on another node - removing only from local store");
removeLocal(session);
continue;
}
log.debug("Session " + session.getId() + " has also expired on all other nodes - removing globally");
}
session.expire();
}
catch (Throwable t)
{
log.error("Problems while expiring session with id = " + session.getId(), t);
}
}
}
}
}