blob: c53578bfca3171c4ed8f10d1bb936f1e3a59e93a [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005, 2016 Cognos Incorporated, IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Cognos Incorporated - initial API and implementation
* IBM Corporation - bug fixes and enhancements
* Raymond Augé <raymond.auge@liferay.com> - Bug 436698
*******************************************************************************/
package org.eclipse.equinox.http.servlet.internal.servlet;
import java.io.Serializable;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import javax.servlet.ServletContext;
import javax.servlet.http.*;
import org.eclipse.equinox.http.servlet.internal.context.ContextController;
import org.eclipse.equinox.http.servlet.internal.util.EventListeners;
// This class adapts HttpSessions in order to return the right ServletContext and attributes
public class HttpSessionAdaptor implements HttpSession, Serializable {
private static final long serialVersionUID = 3418610936889860782L;
static class ParentSessionListener implements HttpSessionBindingListener, Serializable {
private static final long serialVersionUID = 4626167646903550760L;
private static final String PARENT_SESSION_LISTENER_KEY = "org.eclipse.equinox.http.parent.session.listener"; //$NON-NLS-1$
transient final Set<HttpSessionAdaptor> innerSessions = Collections.newSetFromMap(new ConcurrentHashMap<HttpSessionAdaptor, Boolean>());
@Override
public void valueBound(HttpSessionBindingEvent event) {
// do nothing
}
@Override
public void valueUnbound(HttpSessionBindingEvent event) {
// Here we assume the unbound event is signifying the session is being invalidated.
// Must invalidate the inner sessions
Iterator<HttpSessionAdaptor> iterator = innerSessions.iterator();
while (iterator.hasNext()) {
HttpSessionAdaptor innerSession = iterator.next();
iterator.remove();
ContextController contextController =
innerSession.getController();
EventListeners eventListeners =
contextController.getEventListeners();
List<HttpSessionListener> httpSessionListeners =
eventListeners.get(HttpSessionListener.class);
if (!httpSessionListeners.isEmpty()) {
HttpSessionEvent httpSessionEvent = new HttpSessionEvent(
innerSession);
for (HttpSessionListener listener : httpSessionListeners) {
try {
listener.sessionDestroyed(httpSessionEvent);
}
catch (IllegalStateException ise) {
// outer session is already invalidated
}
}
}
contextController.removeActiveSession(
innerSession.getSession());
}
}
static void addHttpSessionAdaptor(HttpSessionAdaptor innerSession) {
HttpSession httpSession = innerSession.getSession();
ParentSessionListener parentListener;
// need to have a global lock here because we must ensure that this is added only once
synchronized (httpSession) {
parentListener = (ParentSessionListener) httpSession.getAttribute(PARENT_SESSION_LISTENER_KEY);
if (parentListener == null) {
parentListener = new ParentSessionListener();
httpSession.setAttribute(PARENT_SESSION_LISTENER_KEY, parentListener);
}
}
parentListener.innerSessions.add(innerSession);
}
static void removeHttpSessionAdaptor(HttpSessionAdaptor innerSession) {
HttpSession httpSession = innerSession.getSession();
ParentSessionListener parentListener = (ParentSessionListener) httpSession.getAttribute(PARENT_SESSION_LISTENER_KEY);
if (parentListener != null) {
parentListener.innerSessions.remove(innerSession);
}
}
}
class HttpSessionAttributeWrapper implements HttpSessionBindingListener, HttpSessionActivationListener, Serializable {
private static final long serialVersionUID = 7945998375225990980L;
final String name;
final Object value;
final boolean added;
final HttpSessionAdaptor innerSession;
public HttpSessionAttributeWrapper(HttpSessionAdaptor innerSession, String name, Object value, boolean added) {
this.innerSession = innerSession;
this.name = name;
this.value = value;
this.added = added;
}
@Override
public void valueBound(HttpSessionBindingEvent event) {
List<HttpSessionAttributeListener> listeners = getEventListeners().get(
HttpSessionAttributeListener.class);
for (HttpSessionAttributeListener listener : listeners) {
if (added) {
listener.attributeAdded(event);
}
else {
listener.attributeReplaced(event);
}
}
if (value instanceof HttpSessionBindingListener) {
((HttpSessionBindingListener) value).valueBound(new HttpSessionBindingEvent(innerSession, name, value));
}
}
@Override
public void valueUnbound(HttpSessionBindingEvent event) {
if (!added) {
List<HttpSessionAttributeListener> listeners = getEventListeners().get(
HttpSessionAttributeListener.class);
for (HttpSessionAttributeListener listener : listeners) {
listener.attributeRemoved(event);
}
}
if (value instanceof HttpSessionBindingListener) {
((HttpSessionBindingListener) value).valueUnbound(new HttpSessionBindingEvent(innerSession, name, value));
}
}
@Override
public void sessionWillPassivate(HttpSessionEvent se) {
if (value instanceof HttpSessionActivationListener) {
((HttpSessionActivationListener) value).sessionWillPassivate(new HttpSessionEvent(innerSession));
}
}
@Override
public void sessionDidActivate(HttpSessionEvent se) {
if (value instanceof HttpSessionActivationListener) {
((HttpSessionActivationListener) value).sessionDidActivate(new HttpSessionEvent(innerSession));
}
}
private EventListeners getEventListeners() {
return innerSession.getController().getEventListeners();
}
@Override
public String toString() {
return String.valueOf(value);
}
}
private transient final ContextController controller;
private transient final HttpSession session;
private transient final ServletContext servletContext;
private transient final String attributePrefix;
private String string;
static public HttpSessionAdaptor createHttpSessionAdaptor(
HttpSession session, ServletContext servletContext, ContextController controller) {
HttpSessionAdaptor sessionAdaptor = new HttpSessionAdaptor(session, servletContext, controller);
ParentSessionListener.addHttpSessionAdaptor(sessionAdaptor);
return sessionAdaptor;
}
private HttpSessionAdaptor(
HttpSession session, ServletContext servletContext, ContextController controller) {
this.session = session;
this.servletContext = servletContext;
this.controller = controller;
this.attributePrefix = "equinox.http." + controller.getContextName(); //$NON-NLS-1$
}
public ContextController getController() {
return controller;
}
public HttpSession getSession() {
return session;
}
public ServletContext getServletContext() {
return servletContext;
}
public Object getAttribute(String arg0) {
Object result = session.getAttribute(attributePrefix + arg0);
if (result instanceof HttpSessionAttributeWrapper) {
result = ((HttpSessionAttributeWrapper) result).value;
}
return result;
}
public Enumeration<String> getAttributeNames() {
return Collections.enumeration(getAttributeNames0());
}
private Collection<String> getAttributeNames0() {
Collection<String> result = new ArrayList<String>();
Enumeration<String> containerSessionAttributes = session.getAttributeNames();
while(containerSessionAttributes.hasMoreElements()) {
String attribute = containerSessionAttributes.nextElement();
if (attribute.startsWith(attributePrefix)) {
result.add(attribute.substring(attributePrefix.length()));
}
}
return result;
}
/**@deprecated*/
public Object getValue(String arg0) {
return getAttribute(arg0);
}
/**@deprecated*/
public String[] getValueNames() {
Collection<String> result = getAttributeNames0();
return result.toArray(new String[result.size()]);
}
public void invalidate() {
HttpSessionEvent httpSessionEvent = new HttpSessionEvent(this);
for (HttpSessionListener listener : controller.getEventListeners().get(HttpSessionListener.class)) {
try {
listener.sessionDestroyed(httpSessionEvent);
}
catch (IllegalStateException ise) {
// outer session is already invalidated
}
}
try {
for (String attribute : getAttributeNames0()) {
removeAttribute(attribute);
}
}
catch (IllegalStateException ise) {
// outer session is already invalidated
}
try {
ParentSessionListener.removeHttpSessionAdaptor(this);
}
catch (IllegalStateException ise) {
// outer session is already invalidated
}
controller.removeActiveSession(session);
}
public void invokeSessionListeners (List<Class<? extends EventListener>> classes, EventListener listener) {
if (classes == null) {
return;
}
for (Class<? extends EventListener> clazz : classes) {
if (clazz.equals(HttpSessionListener.class)){
HttpSessionEvent sessionEvent = new HttpSessionEvent(this);
HttpSessionListener httpSessionListener = (HttpSessionListener) listener;
httpSessionListener.sessionDestroyed(sessionEvent);
}
if (clazz.equals(HttpSessionBindingListener.class) || clazz.equals(HttpSessionAttributeListener.class)) {
Enumeration<String> attributeNames = getAttributeNames();
while (attributeNames.hasMoreElements()) {
String attributeName = attributeNames.nextElement();
HttpSessionBindingEvent sessionBindingEvent = new HttpSessionBindingEvent(this, attributeName);
if (clazz.equals(HttpSessionBindingListener.class)) {
HttpSessionBindingListener httpSessionBindingListener = (HttpSessionBindingListener) listener;
httpSessionBindingListener.valueUnbound(sessionBindingEvent);
}
if (clazz.equals(HttpSessionAttributeListener.class)) {
HttpSessionAttributeListener httpSessionAttributeListener = (HttpSessionAttributeListener) listener;
httpSessionAttributeListener.attributeRemoved(sessionBindingEvent);
}
}
}
}
}
/**@deprecated*/
public void putValue(String arg0, Object arg1) {
setAttribute(arg0, arg1);
}
public void removeAttribute(String arg0) {
session.removeAttribute(attributePrefix + arg0);
}
/**@deprecated*/
public void removeValue(String arg0) {
removeAttribute(arg0);
}
public void setAttribute(String name, Object value) {
Object actualValue = null;
if (value != null) {
boolean added = (session.getAttribute(attributePrefix + name) == null);
actualValue = new HttpSessionAttributeWrapper(this, name, value, added);
}
session.setAttribute(attributePrefix + name, actualValue);
}
public void setMaxInactiveInterval(int arg0) {
// Not sure this can be done per context helper
session.setMaxInactiveInterval(arg0);
}
public long getCreationTime() {
// Not sure this can be done per context helper
return session.getCreationTime();
}
public String getId() {
// Not sure this can be done per context helper
return session.getId();
}
public long getLastAccessedTime() {
// Not sure this can be done per context helper
return session.getLastAccessedTime();
}
public int getMaxInactiveInterval() {
// Not sure this can be done per context helper
return session.getMaxInactiveInterval();
}
/**@deprecated*/
public javax.servlet.http.HttpSessionContext getSessionContext() {
// Not sure this can be done per context helper and I think null is returned anyway
return session.getSessionContext();
}
public boolean isNew() {
// Not sure this can be done per context helper
return session.isNew();
}
@Override
public String toString() {
String value = string;
if (value == null) {
value = SIMPLE_NAME + '[' + session.getId() + ", " + attributePrefix + ']'; //$NON-NLS-1$
string = value;
}
return value;
}
private static final String SIMPLE_NAME =
HttpSessionAdaptor.class.getSimpleName();
}