/**
* Licensed to Apereo under one or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information regarding copyright ownership. Apereo
* licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use
* this file except in compliance with the License. You may obtain a copy of the License at the
* following location:
*
* <p>http://www.apache.org/licenses/LICENSE-2.0
*
* <p>Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apereo.portal.spring.web.context.support;
import java.io.Serializable;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apereo.portal.url.IPortalRequestUtils;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.Scope;
import org.springframework.web.context.request.SessionScope;
import org.springframework.web.util.WebUtils;
/**
* Wraps {@link SessionScope} to provide functionality when no session is available by using a
* singleton instance.
*
*/
public class PortalSessionScope implements Scope {
public static final String DESTRUCTION_CALLBACK_NAME_PREFIX =
PortalSessionScope.class.getName() + ".DESTRUCTION_CALLBACK.";
protected final Log logger = LogFactory.getLog(this.getClass());
private IPortalRequestUtils portalRequestUtils;
public IPortalRequestUtils getPortalRequestUtils() {
return this.portalRequestUtils;
}
@Autowired
public void setPortalRequestUtils(IPortalRequestUtils portalRequestUtils) {
this.portalRequestUtils = portalRequestUtils;
}
/*
* (non-Javadoc)
* @see org.springframework.beans.factory.config.Scope#resolveContextualObject(java.lang.String)
*/
@Override
public Object resolveContextualObject(String arg0) {
//TODO implement me!
return null;
}
/* (non-Javadoc)
* @see org.springframework.beans.factory.config.Scope#get(java.lang.String, org.springframework.beans.factory.ObjectFactory)
*/
public Object get(String name, ObjectFactory<?> objectFactory) {
final HttpSession session = this.getPortalSesion(true);
final Object sessionMutex = WebUtils.getSessionMutex(session);
synchronized (sessionMutex) {
Object scopedObject = session.getAttribute(name);
if (scopedObject == null) {
scopedObject = objectFactory.getObject();
session.setAttribute(name, scopedObject);
}
return scopedObject;
}
}
/* (non-Javadoc)
* @see org.springframework.beans.factory.config.Scope#getConversationId()
*/
public String getConversationId() {
final HttpSession session = this.getPortalSesion(false);
if (session == null) {
return null;
}
return session.getId();
}
/* (non-Javadoc)
* @see org.springframework.beans.factory.config.Scope#registerDestructionCallback(java.lang.String, java.lang.Runnable)
*/
public void registerDestructionCallback(String name, Runnable callback) {
final HttpSession session = this.getPortalSesion(true);
final DestructionCallbackBindingListener callbackListener =
new DestructionCallbackBindingListener(callback);
session.setAttribute(DESTRUCTION_CALLBACK_NAME_PREFIX + name, callbackListener);
}
/* (non-Javadoc)
* @see org.springframework.beans.factory.config.Scope#remove(java.lang.String)
*/
public Object remove(String name) {
final HttpSession session = this.getPortalSesion(false);
if (session == null) {
return null;
}
final Object sessionMutex = WebUtils.getSessionMutex(session);
synchronized (sessionMutex) {
final Object attribute = session.getAttribute(name);
if (attribute != null) {
session.removeAttribute(name);
}
return attribute;
}
}
protected HttpSession getPortalSesion(boolean create) {
final HttpServletRequest portalRequest = this.portalRequestUtils.getCurrentPortalRequest();
return portalRequest.getSession(create);
}
/**
* Adapter that implements the Servlet 2.3 HttpSessionBindingListener interface, wrapping a
* session destruction callback.
*/
private static class DestructionCallbackBindingListener
implements HttpSessionBindingListener, Serializable {
private static final long serialVersionUID = 1L;
private final transient Runnable destructionCallback;
public DestructionCallbackBindingListener(Runnable destructionCallback) {
this.destructionCallback = destructionCallback;
}
public void valueBound(HttpSessionBindingEvent event) {}
public void valueUnbound(HttpSessionBindingEvent event) {
if (this.destructionCallback != null) {
this.destructionCallback.run();
}
}
}
}