renamed "contextProperties" attribute to "contextParameters" (matching web.xml naming); "contextParameters" contains Servlet/PortletConfig parameters as well; added default "servletContext" and "servletConfig" environment beans; added default "portletContext" and "portletConfig" environment beans; added default web scope "application", wrapping a ServletContext/PortletContext; MockPortletSession supports destruction of session attributes on invalidation
git-svn-id: https://src.springframework.org/svn/spring-framework/trunk@1094 50f2f4bb-b051-0410-bef5-90022cba6387
This commit is contained in:
parent
d10d95e98d
commit
f70e482841
|
|
@ -30,6 +30,7 @@ import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import javax.portlet.PortletContext;
|
import javax.portlet.PortletContext;
|
||||||
import javax.portlet.PortletRequestDispatcher;
|
import javax.portlet.PortletRequestDispatcher;
|
||||||
|
import javax.activation.FileTypeMap;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
@ -152,7 +153,7 @@ public class MockPortletContext implements PortletContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getMajorVersion() {
|
public int getMajorVersion() {
|
||||||
return 1;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getMinorVersion() {
|
public int getMinorVersion() {
|
||||||
|
|
@ -160,7 +161,7 @@ public class MockPortletContext implements PortletContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getMimeType(String filePath) {
|
public String getMimeType(String filePath) {
|
||||||
return null;
|
return MimeTypeResolver.getMimeType(filePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getRealPath(String path) {
|
public String getRealPath(String path) {
|
||||||
|
|
@ -262,4 +263,16 @@ public class MockPortletContext implements PortletContext {
|
||||||
return Collections.enumeration(this.containerRuntimeOptions);
|
return Collections.enumeration(this.containerRuntimeOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inner factory class used to just introduce a Java Activation Framework
|
||||||
|
* dependency when actually asked to resolve a MIME type.
|
||||||
|
*/
|
||||||
|
private static class MimeTypeResolver {
|
||||||
|
|
||||||
|
public static String getMimeType(String filePath) {
|
||||||
|
return FileTypeMap.getDefaultFileTypeMap().getContentType(filePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,9 +19,14 @@ package org.springframework.mock.web.portlet;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import javax.portlet.PortletContext;
|
import javax.portlet.PortletContext;
|
||||||
import javax.portlet.PortletSession;
|
import javax.portlet.PortletSession;
|
||||||
|
import javax.servlet.http.HttpSessionBindingEvent;
|
||||||
|
import javax.servlet.http.HttpSessionBindingListener;
|
||||||
|
|
||||||
|
import org.springframework.mock.web.MockHttpSession;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mock implementation of the {@link javax.portlet.PortletSession} interface.
|
* Mock implementation of the {@link javax.portlet.PortletSession} interface.
|
||||||
|
|
@ -120,14 +125,34 @@ public class MockPortletSession implements PortletSession {
|
||||||
return this.maxInactiveInterval;
|
return this.maxInactiveInterval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear all of this session's attributes.
|
||||||
|
*/
|
||||||
|
public void clearAttributes() {
|
||||||
|
doClearAttributes(this.portletAttributes);
|
||||||
|
doClearAttributes(this.applicationAttributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void doClearAttributes(Map<String, Object> attributes) {
|
||||||
|
for (Iterator<Map.Entry<String, Object>> it = attributes.entrySet().iterator(); it.hasNext();) {
|
||||||
|
Map.Entry<String, Object> entry = it.next();
|
||||||
|
String name = entry.getKey();
|
||||||
|
Object value = entry.getValue();
|
||||||
|
it.remove();
|
||||||
|
if (value instanceof HttpSessionBindingListener) {
|
||||||
|
((HttpSessionBindingListener) value).valueUnbound(
|
||||||
|
new HttpSessionBindingEvent(new MockHttpSession(), name, value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void invalidate() {
|
public void invalidate() {
|
||||||
this.invalid = true;
|
this.invalid = true;
|
||||||
this.portletAttributes.clear();
|
clearAttributes();
|
||||||
this.applicationAttributes.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isInvalid() {
|
public boolean isInvalid() {
|
||||||
return invalid;
|
return this.invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setNew(boolean value) {
|
public void setNew(boolean value) {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,145 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2002-2009 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed 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
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* 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.springframework.mock.web.portlet;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Enumeration;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import javax.portlet.PortletContext;
|
||||||
|
import javax.portlet.PortletRequestDispatcher;
|
||||||
|
import javax.servlet.ServletContext;
|
||||||
|
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mock implementation of the {@link javax.portlet.PortletContext} interface,
|
||||||
|
* wrapping an underlying {@link javax.servlet.ServletContext}.
|
||||||
|
*
|
||||||
|
* @author Juergen Hoeller
|
||||||
|
* @since 3.0
|
||||||
|
* @see MockPortletContext
|
||||||
|
*/
|
||||||
|
public class ServletWrappingPortletContext implements PortletContext {
|
||||||
|
|
||||||
|
private final ServletContext servletContext;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new PortletContext wrapping the given ServletContext.
|
||||||
|
* @param servletContext the ServletContext to wrap
|
||||||
|
*/
|
||||||
|
public ServletWrappingPortletContext(ServletContext servletContext) {
|
||||||
|
Assert.notNull(servletContext, "ServletContext must not be null");
|
||||||
|
this.servletContext = servletContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the underlying ServletContext that this PortletContext wraps.
|
||||||
|
*/
|
||||||
|
public final ServletContext getServletContext() {
|
||||||
|
return this.servletContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String getServerInfo() {
|
||||||
|
return this.servletContext.getServerInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
public PortletRequestDispatcher getRequestDispatcher(String path) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PortletRequestDispatcher getNamedDispatcher(String name) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InputStream getResourceAsStream(String path) {
|
||||||
|
return this.servletContext.getResourceAsStream(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMajorVersion() {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMinorVersion() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMimeType(String file) {
|
||||||
|
return this.servletContext.getMimeType(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRealPath(String path) {
|
||||||
|
return this.servletContext.getRealPath(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public Set<String> getResourcePaths(String path) {
|
||||||
|
return this.servletContext.getResourcePaths(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
public URL getResource(String path) throws MalformedURLException {
|
||||||
|
return this.servletContext.getResource(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getAttribute(String name) {
|
||||||
|
return this.servletContext.getAttribute(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public Enumeration<String> getAttributeNames() {
|
||||||
|
return this.servletContext.getAttributeNames();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getInitParameter(String name) {
|
||||||
|
return this.servletContext.getInitParameter(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public Enumeration<String> getInitParameterNames() {
|
||||||
|
return this.servletContext.getInitParameterNames();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void log(String msg) {
|
||||||
|
this.servletContext.log(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void log(String message, Throwable throwable) {
|
||||||
|
this.servletContext.log(message, throwable);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeAttribute(String name) {
|
||||||
|
this.servletContext.removeAttribute(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAttribute(String name, Object object) {
|
||||||
|
this.servletContext.setAttribute(name, object);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPortletContextName() {
|
||||||
|
return this.servletContext.getServletContextName();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Enumeration<String> getContainerRuntimeOptions() {
|
||||||
|
return Collections.enumeration(new HashSet<String>());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2008 the original author or authors.
|
* Copyright 2002-2009 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -143,12 +143,10 @@ public abstract class AbstractRefreshablePortletApplicationContext extends Abstr
|
||||||
beanFactory.ignoreDependencyInterface(ServletContextAware.class);
|
beanFactory.ignoreDependencyInterface(ServletContextAware.class);
|
||||||
beanFactory.ignoreDependencyInterface(PortletContextAware.class);
|
beanFactory.ignoreDependencyInterface(PortletContextAware.class);
|
||||||
beanFactory.ignoreDependencyInterface(PortletConfigAware.class);
|
beanFactory.ignoreDependencyInterface(PortletConfigAware.class);
|
||||||
beanFactory.registerResolvableDependency(ServletContext.class, this.servletContext);
|
|
||||||
beanFactory.registerResolvableDependency(PortletContext.class, this.portletContext);
|
|
||||||
beanFactory.registerResolvableDependency(PortletConfig.class, this.portletConfig);
|
|
||||||
|
|
||||||
PortletApplicationContextUtils.registerPortletApplicationScopes(beanFactory);
|
PortletApplicationContextUtils.registerPortletApplicationScopes(beanFactory, this.portletContext);
|
||||||
PortletApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.portletContext);
|
PortletApplicationContextUtils.registerEnvironmentBeans(
|
||||||
|
beanFactory, this.servletContext, this.portletContext, this.portletConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2008 the original author or authors.
|
* Copyright 2002-2009 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -43,6 +43,19 @@ import org.springframework.web.context.WebApplicationContext;
|
||||||
public interface ConfigurablePortletApplicationContext
|
public interface ConfigurablePortletApplicationContext
|
||||||
extends WebApplicationContext, ConfigurableApplicationContext {
|
extends WebApplicationContext, ConfigurableApplicationContext {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Name of the PortletContext environment bean in the factory.
|
||||||
|
* @see javax.portlet.PortletContext
|
||||||
|
*/
|
||||||
|
String PORTLET_CONTEXT_BEAN_NAME = "portletContext";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Name of the PortletConfig environment bean in the factory.
|
||||||
|
* @see javax.portlet.PortletConfig
|
||||||
|
*/
|
||||||
|
String PORTLET_CONFIG_BEAN_NAME = "portletConfig";
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the PortletContext for this portlet application context.
|
* Set the PortletContext for this portlet application context.
|
||||||
* <p>Does not cause an initialization of the context: refresh needs to be
|
* <p>Does not cause an initialization of the context: refresh needs to be
|
||||||
|
|
|
||||||
|
|
@ -20,9 +20,11 @@ import java.util.Collections;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import javax.portlet.PortletConfig;
|
||||||
import javax.portlet.PortletContext;
|
import javax.portlet.PortletContext;
|
||||||
import javax.portlet.PortletRequest;
|
import javax.portlet.PortletRequest;
|
||||||
import javax.portlet.PortletSession;
|
import javax.portlet.PortletSession;
|
||||||
|
import javax.servlet.ServletContext;
|
||||||
|
|
||||||
import org.springframework.beans.factory.ObjectFactory;
|
import org.springframework.beans.factory.ObjectFactory;
|
||||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||||
|
|
@ -102,14 +104,21 @@ public abstract class PortletApplicationContextUtils {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register portlet-specific scopes with the given BeanFactory,
|
* Register web-specific scopes ("request", "session", "globalSession")
|
||||||
* as used by the Portlet ApplicationContext.
|
* with the given BeanFactory, as used by the Portlet ApplicationContext.
|
||||||
* @param beanFactory the BeanFactory to configure
|
* @param beanFactory the BeanFactory to configure
|
||||||
|
* @param pc the PortletContext that we're running within
|
||||||
*/
|
*/
|
||||||
static void registerPortletApplicationScopes(ConfigurableListableBeanFactory beanFactory) {
|
static void registerPortletApplicationScopes(ConfigurableListableBeanFactory beanFactory, PortletContext pc) {
|
||||||
beanFactory.registerScope(WebApplicationContext.SCOPE_REQUEST, new RequestScope());
|
beanFactory.registerScope(WebApplicationContext.SCOPE_REQUEST, new RequestScope());
|
||||||
beanFactory.registerScope(WebApplicationContext.SCOPE_SESSION, new SessionScope(false));
|
beanFactory.registerScope(WebApplicationContext.SCOPE_SESSION, new SessionScope(false));
|
||||||
beanFactory.registerScope(WebApplicationContext.SCOPE_GLOBAL_SESSION, new SessionScope(true));
|
beanFactory.registerScope(WebApplicationContext.SCOPE_GLOBAL_SESSION, new SessionScope(true));
|
||||||
|
if (pc != null) {
|
||||||
|
PortletContextScope appScope = new PortletContextScope(pc);
|
||||||
|
beanFactory.registerScope(WebApplicationContext.SCOPE_APPLICATION, appScope);
|
||||||
|
// Register as PortletContext attribute, for ContextCleanupListener to detect it.
|
||||||
|
pc.setAttribute(PortletContextScope.class.getName(), appScope);
|
||||||
|
}
|
||||||
|
|
||||||
beanFactory.registerResolvableDependency(PortletRequest.class, new ObjectFactory<PortletRequest>() {
|
beanFactory.registerResolvableDependency(PortletRequest.class, new ObjectFactory<PortletRequest>() {
|
||||||
public PortletRequest getObject() {
|
public PortletRequest getObject() {
|
||||||
|
|
@ -132,13 +141,29 @@ public abstract class PortletApplicationContextUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register web-specific environment beans with the given BeanFactory,
|
* Register web-specific environment beans ("contextParameters", "contextAttributes")
|
||||||
* as used by the Portlet ApplicationContext.
|
* with the given BeanFactory, as used by the Portlet ApplicationContext.
|
||||||
* @param bf the BeanFactory to configure
|
* @param bf the BeanFactory to configure
|
||||||
|
* @param sc the ServletContext that we're running within
|
||||||
* @param pc the PortletContext that we're running within
|
* @param pc the PortletContext that we're running within
|
||||||
|
* @param config the PortletConfig of the containing Portlet
|
||||||
*/
|
*/
|
||||||
static void registerEnvironmentBeans(ConfigurableListableBeanFactory bf, PortletContext pc) {
|
static void registerEnvironmentBeans(
|
||||||
if (!bf.containsBean(WebApplicationContext.CONTEXT_PROPERTIES_BEAN_NAME)) {
|
ConfigurableListableBeanFactory bf, ServletContext sc, PortletContext pc, PortletConfig config) {
|
||||||
|
|
||||||
|
if (sc != null && !bf.containsBean(WebApplicationContext.SERVLET_CONTEXT_BEAN_NAME)) {
|
||||||
|
bf.registerSingleton(WebApplicationContext.SERVLET_CONTEXT_BEAN_NAME, sc);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pc != null && !bf.containsBean(ConfigurablePortletApplicationContext.PORTLET_CONTEXT_BEAN_NAME)) {
|
||||||
|
bf.registerSingleton(ConfigurablePortletApplicationContext.PORTLET_CONTEXT_BEAN_NAME, pc);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config != null && !bf.containsBean(ConfigurablePortletApplicationContext.PORTLET_CONFIG_BEAN_NAME)) {
|
||||||
|
bf.registerSingleton(ConfigurablePortletApplicationContext.PORTLET_CONFIG_BEAN_NAME, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!bf.containsBean(WebApplicationContext.CONTEXT_PARAMETERS_BEAN_NAME)) {
|
||||||
Map<String, String> parameterMap = new HashMap<String, String>();
|
Map<String, String> parameterMap = new HashMap<String, String>();
|
||||||
if (pc != null) {
|
if (pc != null) {
|
||||||
Enumeration paramNameEnum = pc.getInitParameterNames();
|
Enumeration paramNameEnum = pc.getInitParameterNames();
|
||||||
|
|
@ -147,7 +172,14 @@ public abstract class PortletApplicationContextUtils {
|
||||||
parameterMap.put(paramName, pc.getInitParameter(paramName));
|
parameterMap.put(paramName, pc.getInitParameter(paramName));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bf.registerSingleton(WebApplicationContext.CONTEXT_PROPERTIES_BEAN_NAME,
|
if (config != null) {
|
||||||
|
Enumeration paramNameEnum = config.getInitParameterNames();
|
||||||
|
while (paramNameEnum.hasMoreElements()) {
|
||||||
|
String paramName = (String) paramNameEnum.nextElement();
|
||||||
|
parameterMap.put(paramName, config.getInitParameter(paramName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bf.registerSingleton(WebApplicationContext.CONTEXT_PARAMETERS_BEAN_NAME,
|
||||||
Collections.unmodifiableMap(parameterMap));
|
Collections.unmodifiableMap(parameterMap));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,111 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2002-2009 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed 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
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* 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.springframework.web.portlet.context;
|
||||||
|
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import javax.portlet.PortletContext;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.DisposableBean;
|
||||||
|
import org.springframework.beans.factory.ObjectFactory;
|
||||||
|
import org.springframework.beans.factory.config.Scope;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link Scope} wrapper for a PortletContext, i.e. for global web application attributes.
|
||||||
|
*
|
||||||
|
* <p>This differs from traditional Spring singletons in that it exposes attributes in the
|
||||||
|
* PortletContext. Those attributes will get destroyed whenever the entire application
|
||||||
|
* shuts down, which might be earlier or later than the shutdown of the containing Spring
|
||||||
|
* ApplicationContext.
|
||||||
|
*
|
||||||
|
* <p>The associated destruction mechanism relies on a
|
||||||
|
* {@link org.springframework.web.context.ContextCleanupListener} being registered in
|
||||||
|
* <code>web.xml</code>. Note that {@link org.springframework.web.context.ContextLoaderListener}
|
||||||
|
* includes ContextCleanupListener's functionality.
|
||||||
|
*
|
||||||
|
* <p>This scope is registered as default scope with key
|
||||||
|
* {@link org.springframework.web.context.WebApplicationContext#SCOPE_APPLICATION "application"}.
|
||||||
|
*
|
||||||
|
* @author Juergen Hoeller
|
||||||
|
* @since 3.0
|
||||||
|
* @see org.springframework.web.context.ContextCleanupListener
|
||||||
|
*/
|
||||||
|
public class PortletContextScope implements Scope, DisposableBean {
|
||||||
|
|
||||||
|
private final PortletContext portletContext;
|
||||||
|
|
||||||
|
private final Map<String, Runnable> destructionCallbacks = new LinkedHashMap<String, Runnable>();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new Scope wrapper for the given PortletContext.
|
||||||
|
* @param PortletContext the PortletContext to wrap
|
||||||
|
*/
|
||||||
|
public PortletContextScope(PortletContext portletContext) {
|
||||||
|
Assert.notNull(portletContext, "PortletContext must not be null");
|
||||||
|
this.portletContext = portletContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Object get(String name, ObjectFactory<?> objectFactory) {
|
||||||
|
Object scopedObject = this.portletContext.getAttribute(name);
|
||||||
|
if (scopedObject == null) {
|
||||||
|
scopedObject = objectFactory.getObject();
|
||||||
|
this.portletContext.setAttribute(name, scopedObject);
|
||||||
|
}
|
||||||
|
return scopedObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object remove(String name) {
|
||||||
|
Object scopedObject = this.portletContext.getAttribute(name);
|
||||||
|
if (scopedObject != null) {
|
||||||
|
this.portletContext.removeAttribute(name);
|
||||||
|
this.destructionCallbacks.remove(name);
|
||||||
|
return scopedObject;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void registerDestructionCallback(String name, Runnable callback) {
|
||||||
|
this.destructionCallbacks.put(name, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object resolveContextualObject(String key) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getConversationId() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoke all registered destruction callbacks.
|
||||||
|
* To be called on ServletContext shutdown.
|
||||||
|
* @see org.springframework.web.context.ContextCleanupListener
|
||||||
|
*/
|
||||||
|
public void destroy() {
|
||||||
|
for (Runnable runnable : this.destructionCallbacks.values()) {
|
||||||
|
runnable.run();
|
||||||
|
}
|
||||||
|
this.destructionCallbacks.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2008 the original author or authors.
|
* Copyright 2002-2009 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -139,12 +139,10 @@ public class StaticPortletApplicationContext extends StaticApplicationContext
|
||||||
beanFactory.addBeanPostProcessor(new PortletContextAwareProcessor(this.portletContext, this.portletConfig));
|
beanFactory.addBeanPostProcessor(new PortletContextAwareProcessor(this.portletContext, this.portletConfig));
|
||||||
beanFactory.ignoreDependencyInterface(PortletContextAware.class);
|
beanFactory.ignoreDependencyInterface(PortletContextAware.class);
|
||||||
beanFactory.ignoreDependencyInterface(PortletConfigAware.class);
|
beanFactory.ignoreDependencyInterface(PortletConfigAware.class);
|
||||||
beanFactory.registerResolvableDependency(ServletContext.class, this.servletContext);
|
|
||||||
beanFactory.registerResolvableDependency(PortletContext.class, this.portletContext);
|
|
||||||
beanFactory.registerResolvableDependency(PortletConfig.class, this.portletConfig);
|
|
||||||
|
|
||||||
PortletApplicationContextUtils.registerPortletApplicationScopes(beanFactory);
|
PortletApplicationContextUtils.registerPortletApplicationScopes(beanFactory, this.portletContext);
|
||||||
PortletApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.portletContext);
|
PortletApplicationContextUtils.registerEnvironmentBeans(
|
||||||
|
beanFactory, this.servletContext, this.portletContext, this.portletConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -152,7 +152,7 @@ public class MockPortletContext implements PortletContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getMajorVersion() {
|
public int getMajorVersion() {
|
||||||
return 1;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getMinorVersion() {
|
public int getMinorVersion() {
|
||||||
|
|
|
||||||
|
|
@ -19,9 +19,14 @@ package org.springframework.mock.web.portlet;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import javax.portlet.PortletContext;
|
import javax.portlet.PortletContext;
|
||||||
import javax.portlet.PortletSession;
|
import javax.portlet.PortletSession;
|
||||||
|
import javax.servlet.http.HttpSessionBindingEvent;
|
||||||
|
import javax.servlet.http.HttpSessionBindingListener;
|
||||||
|
|
||||||
|
import org.springframework.mock.web.MockHttpSession;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mock implementation of the {@link javax.portlet.PortletSession} interface.
|
* Mock implementation of the {@link javax.portlet.PortletSession} interface.
|
||||||
|
|
@ -120,14 +125,34 @@ public class MockPortletSession implements PortletSession {
|
||||||
return this.maxInactiveInterval;
|
return this.maxInactiveInterval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear all of this session's attributes.
|
||||||
|
*/
|
||||||
|
public void clearAttributes() {
|
||||||
|
doClearAttributes(this.portletAttributes);
|
||||||
|
doClearAttributes(this.applicationAttributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void doClearAttributes(Map<String, Object> attributes) {
|
||||||
|
for (Iterator<Map.Entry<String, Object>> it = attributes.entrySet().iterator(); it.hasNext();) {
|
||||||
|
Map.Entry<String, Object> entry = it.next();
|
||||||
|
String name = entry.getKey();
|
||||||
|
Object value = entry.getValue();
|
||||||
|
it.remove();
|
||||||
|
if (value instanceof HttpSessionBindingListener) {
|
||||||
|
((HttpSessionBindingListener) value).valueUnbound(
|
||||||
|
new HttpSessionBindingEvent(new MockHttpSession(), name, value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void invalidate() {
|
public void invalidate() {
|
||||||
this.invalid = true;
|
this.invalid = true;
|
||||||
this.portletAttributes.clear();
|
clearAttributes();
|
||||||
this.applicationAttributes.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isInvalid() {
|
public boolean isInvalid() {
|
||||||
return invalid;
|
return this.invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setNew(boolean value) {
|
public void setNew(boolean value) {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,145 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2002-2009 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed 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
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* 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.springframework.mock.web.portlet;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Enumeration;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import javax.portlet.PortletContext;
|
||||||
|
import javax.portlet.PortletRequestDispatcher;
|
||||||
|
import javax.servlet.ServletContext;
|
||||||
|
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mock implementation of the {@link javax.portlet.PortletContext} interface,
|
||||||
|
* wrapping an underlying {@link javax.servlet.ServletContext}.
|
||||||
|
*
|
||||||
|
* @author Juergen Hoeller
|
||||||
|
* @since 3.0
|
||||||
|
* @see org.springframework.mock.web.portlet.MockPortletContext
|
||||||
|
*/
|
||||||
|
public class ServletWrappingPortletContext implements PortletContext {
|
||||||
|
|
||||||
|
private final ServletContext servletContext;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new PortletContext wrapping the given ServletContext.
|
||||||
|
* @param servletContext the ServletContext to wrap
|
||||||
|
*/
|
||||||
|
public ServletWrappingPortletContext(ServletContext servletContext) {
|
||||||
|
Assert.notNull(servletContext, "ServletContext must not be null");
|
||||||
|
this.servletContext = servletContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the underlying ServletContext that this PortletContext wraps.
|
||||||
|
*/
|
||||||
|
public final ServletContext getServletContext() {
|
||||||
|
return this.servletContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String getServerInfo() {
|
||||||
|
return this.servletContext.getServerInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
public PortletRequestDispatcher getRequestDispatcher(String path) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PortletRequestDispatcher getNamedDispatcher(String name) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InputStream getResourceAsStream(String path) {
|
||||||
|
return this.servletContext.getResourceAsStream(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMajorVersion() {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMinorVersion() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMimeType(String file) {
|
||||||
|
return this.servletContext.getMimeType(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRealPath(String path) {
|
||||||
|
return this.servletContext.getRealPath(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public Set<String> getResourcePaths(String path) {
|
||||||
|
return this.servletContext.getResourcePaths(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
public URL getResource(String path) throws MalformedURLException {
|
||||||
|
return this.servletContext.getResource(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getAttribute(String name) {
|
||||||
|
return this.servletContext.getAttribute(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public Enumeration<String> getAttributeNames() {
|
||||||
|
return this.servletContext.getAttributeNames();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getInitParameter(String name) {
|
||||||
|
return this.servletContext.getInitParameter(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public Enumeration<String> getInitParameterNames() {
|
||||||
|
return this.servletContext.getInitParameterNames();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void log(String msg) {
|
||||||
|
this.servletContext.log(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void log(String message, Throwable throwable) {
|
||||||
|
this.servletContext.log(message, throwable);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeAttribute(String name) {
|
||||||
|
this.servletContext.removeAttribute(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAttribute(String name, Object object) {
|
||||||
|
this.servletContext.setAttribute(name, object);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPortletContextName() {
|
||||||
|
return this.servletContext.getServletContextName();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Enumeration<String> getContainerRuntimeOptions() {
|
||||||
|
return Collections.enumeration(new HashSet<String>());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,128 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2002-2009 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed 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
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* 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.springframework.web.portlet.context;
|
||||||
|
|
||||||
|
import javax.portlet.PortletContext;
|
||||||
|
import javax.portlet.PortletSession;
|
||||||
|
import javax.servlet.ServletContextEvent;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import org.springframework.beans.DerivedTestBean;
|
||||||
|
import org.springframework.beans.factory.support.GenericBeanDefinition;
|
||||||
|
import org.springframework.mock.web.MockServletContext;
|
||||||
|
import org.springframework.mock.web.portlet.MockRenderRequest;
|
||||||
|
import org.springframework.mock.web.portlet.ServletWrappingPortletContext;
|
||||||
|
import org.springframework.web.context.ContextCleanupListener;
|
||||||
|
import org.springframework.web.context.WebApplicationContext;
|
||||||
|
import org.springframework.web.context.request.RequestContextHolder;
|
||||||
|
import org.springframework.web.context.support.GenericWebApplicationContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Juergen Hoeller
|
||||||
|
*/
|
||||||
|
public class PortletApplicationContextScopeTests {
|
||||||
|
|
||||||
|
private static final String NAME = "scoped";
|
||||||
|
|
||||||
|
|
||||||
|
private ConfigurablePortletApplicationContext initApplicationContext(String scope) {
|
||||||
|
MockServletContext sc = new MockServletContext();
|
||||||
|
GenericWebApplicationContext rac = new GenericWebApplicationContext(sc);
|
||||||
|
rac.refresh();
|
||||||
|
PortletContext pc = new ServletWrappingPortletContext(sc);
|
||||||
|
StaticPortletApplicationContext ac = new StaticPortletApplicationContext();
|
||||||
|
ac.setParent(rac);
|
||||||
|
ac.setPortletContext(pc);
|
||||||
|
GenericBeanDefinition bd = new GenericBeanDefinition();
|
||||||
|
bd.setBeanClass(DerivedTestBean.class);
|
||||||
|
bd.setScope(scope);
|
||||||
|
ac.registerBeanDefinition(NAME, bd);
|
||||||
|
ac.refresh();
|
||||||
|
return ac;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRequestScope() {
|
||||||
|
WebApplicationContext ac = initApplicationContext(WebApplicationContext.SCOPE_REQUEST);
|
||||||
|
MockRenderRequest request = new MockRenderRequest();
|
||||||
|
PortletRequestAttributes requestAttributes = new PortletRequestAttributes(request);
|
||||||
|
RequestContextHolder.setRequestAttributes(requestAttributes);
|
||||||
|
try {
|
||||||
|
assertNull(request.getAttribute(NAME));
|
||||||
|
DerivedTestBean bean = ac.getBean(NAME, DerivedTestBean.class);
|
||||||
|
assertSame(bean, request.getAttribute(NAME));
|
||||||
|
assertSame(bean, ac.getBean(NAME));
|
||||||
|
requestAttributes.requestCompleted();
|
||||||
|
assertTrue(bean.wasDestroyed());
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
RequestContextHolder.setRequestAttributes(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSessionScope() {
|
||||||
|
WebApplicationContext ac = initApplicationContext(WebApplicationContext.SCOPE_SESSION);
|
||||||
|
MockRenderRequest request = new MockRenderRequest();
|
||||||
|
PortletRequestAttributes requestAttributes = new PortletRequestAttributes(request);
|
||||||
|
RequestContextHolder.setRequestAttributes(requestAttributes);
|
||||||
|
try {
|
||||||
|
assertNull(request.getPortletSession().getAttribute(NAME));
|
||||||
|
DerivedTestBean bean = ac.getBean(NAME, DerivedTestBean.class);
|
||||||
|
assertSame(bean, request.getPortletSession().getAttribute(NAME));
|
||||||
|
assertSame(bean, ac.getBean(NAME));
|
||||||
|
request.getPortletSession().invalidate();
|
||||||
|
assertTrue(bean.wasDestroyed());
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
RequestContextHolder.setRequestAttributes(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGlobalSessionScope() {
|
||||||
|
WebApplicationContext ac = initApplicationContext(WebApplicationContext.SCOPE_GLOBAL_SESSION);
|
||||||
|
MockRenderRequest request = new MockRenderRequest();
|
||||||
|
PortletRequestAttributes requestAttributes = new PortletRequestAttributes(request);
|
||||||
|
RequestContextHolder.setRequestAttributes(requestAttributes);
|
||||||
|
try {
|
||||||
|
assertNull(request.getPortletSession().getAttribute(NAME, PortletSession.APPLICATION_SCOPE));
|
||||||
|
DerivedTestBean bean = ac.getBean(NAME, DerivedTestBean.class);
|
||||||
|
assertSame(bean, request.getPortletSession().getAttribute(NAME, PortletSession.APPLICATION_SCOPE));
|
||||||
|
assertSame(bean, ac.getBean(NAME));
|
||||||
|
request.getPortletSession().invalidate();
|
||||||
|
assertTrue(bean.wasDestroyed());
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
RequestContextHolder.setRequestAttributes(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testApplicationScope() {
|
||||||
|
ConfigurablePortletApplicationContext ac = initApplicationContext(WebApplicationContext.SCOPE_APPLICATION);
|
||||||
|
assertNull(ac.getPortletContext().getAttribute(NAME));
|
||||||
|
DerivedTestBean bean = ac.getBean(NAME, DerivedTestBean.class);
|
||||||
|
assertSame(bean, ac.getPortletContext().getAttribute(NAME));
|
||||||
|
assertSame(bean, ac.getBean(NAME));
|
||||||
|
new ContextCleanupListener().contextDestroyed(new ServletContextEvent(ac.getServletContext()));
|
||||||
|
assertTrue(bean.wasDestroyed());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2008 the original author or authors.
|
* Copyright 2002-2009 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -39,6 +39,13 @@ import org.springframework.context.ConfigurableApplicationContext;
|
||||||
*/
|
*/
|
||||||
public interface ConfigurableWebApplicationContext extends WebApplicationContext, ConfigurableApplicationContext {
|
public interface ConfigurableWebApplicationContext extends WebApplicationContext, ConfigurableApplicationContext {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Name of the ServletConfig environment bean in the factory.
|
||||||
|
* @see javax.servlet.ServletConfig
|
||||||
|
*/
|
||||||
|
String SERVLET_CONFIG_BEAN_NAME = "servletConfig";
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the ServletContext for this web application context.
|
* Set the ServletContext for this web application context.
|
||||||
* <p>Does not cause an initialization of the context: refresh needs to be
|
* <p>Does not cause an initialization of the context: refresh needs to be
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,77 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2002-2009 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed 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
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* 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.springframework.web.context;
|
||||||
|
|
||||||
|
import java.util.Enumeration;
|
||||||
|
import javax.servlet.ServletContext;
|
||||||
|
import javax.servlet.ServletContextEvent;
|
||||||
|
import javax.servlet.ServletContextListener;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.DisposableBean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Web application listener that cleans up remaining disposable attributes
|
||||||
|
* in the ServletContext, i.e. attributes which implement {@link DisposableBean}
|
||||||
|
* and haven't been removed before. This is typically used for destroying objects
|
||||||
|
* in "application" scope, for which the lifecycle implies destruction at the
|
||||||
|
* very end of the web application's shutdown phase.
|
||||||
|
*
|
||||||
|
* @author Juergen Hoeller
|
||||||
|
* @since 3.0
|
||||||
|
* @see org.springframework.web.context.support.ServletContextScope
|
||||||
|
* @see ContextLoaderListener
|
||||||
|
*/
|
||||||
|
public class ContextCleanupListener implements ServletContextListener {
|
||||||
|
|
||||||
|
private static final Log logger = LogFactory.getLog(ContextCleanupListener.class);
|
||||||
|
|
||||||
|
|
||||||
|
public void contextInitialized(ServletContextEvent event) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void contextDestroyed(ServletContextEvent event) {
|
||||||
|
cleanupAttributes(event.getServletContext());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find all ServletContext attributes which implement {@link DisposableBean}
|
||||||
|
* and destroy them, removing all affected ServletContext attributes eventually.
|
||||||
|
* @param sc the ServletContext to check
|
||||||
|
*/
|
||||||
|
static void cleanupAttributes(ServletContext sc) {
|
||||||
|
Enumeration attrNames = sc.getAttributeNames();
|
||||||
|
while (attrNames.hasMoreElements()) {
|
||||||
|
String attrName = (String) attrNames.nextElement();
|
||||||
|
if (attrName.startsWith("org.springframework.")) {
|
||||||
|
Object attrValue = sc.getAttribute(attrName);
|
||||||
|
if (attrValue instanceof DisposableBean) {
|
||||||
|
try {
|
||||||
|
((DisposableBean) attrValue).destroy();
|
||||||
|
}
|
||||||
|
catch (Throwable ex) {
|
||||||
|
logger.error("Couldn't invoke destroy method of attribute with name '" + attrName + "'", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2008 the original author or authors.
|
* Copyright 2002-2009 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -269,7 +269,7 @@ public class ContextLoader {
|
||||||
String contextClassName = servletContext.getInitParameter(CONTEXT_CLASS_PARAM);
|
String contextClassName = servletContext.getInitParameter(CONTEXT_CLASS_PARAM);
|
||||||
if (contextClassName != null) {
|
if (contextClassName != null) {
|
||||||
try {
|
try {
|
||||||
return ClassUtils.forName(contextClassName);
|
return ClassUtils.forName(contextClassName, ClassUtils.getDefaultClassLoader());
|
||||||
}
|
}
|
||||||
catch (ClassNotFoundException ex) {
|
catch (ClassNotFoundException ex) {
|
||||||
throw new ApplicationContextException(
|
throw new ApplicationContextException(
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2008 the original author or authors.
|
* Copyright 2002-2009 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -20,8 +20,8 @@ import javax.servlet.ServletContextEvent;
|
||||||
import javax.servlet.ServletContextListener;
|
import javax.servlet.ServletContextListener;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bootstrap listener to start up Spring's root {@link WebApplicationContext}.
|
* Bootstrap listener to start up and shut down Spring's root {@link WebApplicationContext}.
|
||||||
* Simply delegates to {@link ContextLoader}.
|
* Simply delegates to {@link ContextLoader} as well as to {@link ContextCleanupListener}.
|
||||||
*
|
*
|
||||||
* <p>This listener should be registered after
|
* <p>This listener should be registered after
|
||||||
* {@link org.springframework.web.util.Log4jConfigListener}
|
* {@link org.springframework.web.util.Log4jConfigListener}
|
||||||
|
|
@ -77,6 +77,7 @@ public class ContextLoaderListener extends ContextLoader implements ServletConte
|
||||||
if (this.contextLoader != null) {
|
if (this.contextLoader != null) {
|
||||||
this.contextLoader.closeWebApplicationContext(event.getServletContext());
|
this.contextLoader.closeWebApplicationContext(event.getServletContext());
|
||||||
}
|
}
|
||||||
|
ContextCleanupListener.cleanupAttributes(event.getServletContext());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2008 the original author or authors.
|
* Copyright 2002-2009 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -72,14 +72,30 @@ public interface WebApplicationContext extends ApplicationContext {
|
||||||
String SCOPE_GLOBAL_SESSION = "globalSession";
|
String SCOPE_GLOBAL_SESSION = "globalSession";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Name of the ServletContext init-params environment bean in the factory.
|
* Scope identifier for the global web application scope: "application".
|
||||||
* @see javax.servlet.ServletContext#getInitParameterNames()
|
* Supported in addition to the standard scopes "singleton" and "prototype".
|
||||||
* @see javax.servlet.ServletContext#getInitParameter(String)
|
|
||||||
*/
|
*/
|
||||||
String CONTEXT_PROPERTIES_BEAN_NAME = "contextProperties";
|
String SCOPE_APPLICATION = "application";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Name of the ServletContext attributes environment bean in the factory.
|
* Name of the ServletContext environment bean in the factory.
|
||||||
|
* @see javax.servlet.ServletContext
|
||||||
|
*/
|
||||||
|
String SERVLET_CONTEXT_BEAN_NAME = "servletContext";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Name of the ServletContext/PortletContext init-params environment bean in the factory.
|
||||||
|
* <p>Note: Possibly merged with ServletConfig/PortletConfig parameters.
|
||||||
|
* ServletConfig parameters override ServletContext parameters of the same name.
|
||||||
|
* @see javax.servlet.ServletContext#getInitParameterNames()
|
||||||
|
* @see javax.servlet.ServletContext#getInitParameter(String)
|
||||||
|
* @see javax.servlet.ServletConfig#getInitParameterNames()
|
||||||
|
* @see javax.servlet.ServletConfig#getInitParameter(String)
|
||||||
|
*/
|
||||||
|
String CONTEXT_PARAMETERS_BEAN_NAME = "contextParameters";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Name of the ServletContext/PortletContext attributes environment bean in the factory.
|
||||||
* @see javax.servlet.ServletContext#getAttributeNames()
|
* @see javax.servlet.ServletContext#getAttributeNames()
|
||||||
* @see javax.servlet.ServletContext#getAttribute(String)
|
* @see javax.servlet.ServletContext#getAttribute(String)
|
||||||
*/
|
*/
|
||||||
|
|
@ -88,6 +104,7 @@ public interface WebApplicationContext extends ApplicationContext {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the standard Servlet API ServletContext for this application.
|
* Return the standard Servlet API ServletContext for this application.
|
||||||
|
* <p>Also available for a Portlet application, in addition to the PortletContext.
|
||||||
*/
|
*/
|
||||||
ServletContext getServletContext();
|
ServletContext getServletContext();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2008 the original author or authors.
|
* Copyright 2002-2009 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -139,11 +139,9 @@ public abstract class AbstractRefreshableWebApplicationContext extends AbstractR
|
||||||
beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext, this.servletConfig));
|
beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext, this.servletConfig));
|
||||||
beanFactory.ignoreDependencyInterface(ServletContextAware.class);
|
beanFactory.ignoreDependencyInterface(ServletContextAware.class);
|
||||||
beanFactory.ignoreDependencyInterface(ServletConfigAware.class);
|
beanFactory.ignoreDependencyInterface(ServletConfigAware.class);
|
||||||
beanFactory.registerResolvableDependency(ServletContext.class, this.servletContext);
|
|
||||||
beanFactory.registerResolvableDependency(ServletConfig.class, this.servletConfig);
|
|
||||||
|
|
||||||
WebApplicationContextUtils.registerWebApplicationScopes(beanFactory);
|
WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext);
|
||||||
WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext);
|
WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext, this.servletConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2008 the original author or authors.
|
* Copyright 2002-2009 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -71,6 +71,16 @@ public class GenericWebApplicationContext extends GenericApplicationContext
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new GenericWebApplicationContext for the given ServletContext.
|
||||||
|
* @param servletContext the ServletContext to run in
|
||||||
|
* @see #registerBeanDefinition
|
||||||
|
* @see #refresh
|
||||||
|
*/
|
||||||
|
public GenericWebApplicationContext(ServletContext servletContext) {
|
||||||
|
this.servletContext = servletContext;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new GenericWebApplicationContext with the given DefaultListableBeanFactory.
|
* Create a new GenericWebApplicationContext with the given DefaultListableBeanFactory.
|
||||||
* @param beanFactory the DefaultListableBeanFactory instance to use for this context
|
* @param beanFactory the DefaultListableBeanFactory instance to use for this context
|
||||||
|
|
@ -82,6 +92,18 @@ public class GenericWebApplicationContext extends GenericApplicationContext
|
||||||
super(beanFactory);
|
super(beanFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new GenericWebApplicationContext with the given DefaultListableBeanFactory.
|
||||||
|
* @param beanFactory the DefaultListableBeanFactory instance to use for this context
|
||||||
|
* @param servletContext the ServletContext to run in
|
||||||
|
* @see #registerBeanDefinition
|
||||||
|
* @see #refresh
|
||||||
|
*/
|
||||||
|
public GenericWebApplicationContext(DefaultListableBeanFactory beanFactory, ServletContext servletContext) {
|
||||||
|
super(beanFactory);
|
||||||
|
this.servletContext = servletContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the ServletContext that this WebApplicationContext runs in.
|
* Set the ServletContext that this WebApplicationContext runs in.
|
||||||
|
|
@ -103,9 +125,8 @@ public class GenericWebApplicationContext extends GenericApplicationContext
|
||||||
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
|
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
|
||||||
beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext));
|
beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext));
|
||||||
beanFactory.ignoreDependencyInterface(ServletContextAware.class);
|
beanFactory.ignoreDependencyInterface(ServletContextAware.class);
|
||||||
beanFactory.registerResolvableDependency(ServletContext.class, this.servletContext);
|
|
||||||
|
|
||||||
WebApplicationContextUtils.registerWebApplicationScopes(beanFactory);
|
WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext);
|
||||||
WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext);
|
WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,10 +30,15 @@ import org.springframework.web.context.ServletContextAware;
|
||||||
* the startup of the Spring application context. Typically, such
|
* the startup of the Spring application context. Typically, such
|
||||||
* attributes will have been put there by third-party web frameworks.
|
* attributes will have been put there by third-party web frameworks.
|
||||||
* In a purely Spring-based web application, no such linking in of
|
* In a purely Spring-based web application, no such linking in of
|
||||||
* ServletContext attrutes will be necessary.
|
* ServletContext attributes will be necessary.
|
||||||
|
*
|
||||||
|
* <p><b>NOTE:</b> As of Spring 3.0, you may also use the "contextAttributes" default
|
||||||
|
* bean which is of type Map, and dereference it using an "#{contextAttributes.myKey}"
|
||||||
|
* expression to access a specific attribute by name.
|
||||||
*
|
*
|
||||||
* @author Juergen Hoeller
|
* @author Juergen Hoeller
|
||||||
* @since 1.1.4
|
* @since 1.1.4
|
||||||
|
* @see org.springframework.web.context.WebApplicationContext#CONTEXT_ATTRIBUTES_BEAN_NAME
|
||||||
* @see ServletContextParameterFactoryBean
|
* @see ServletContextParameterFactoryBean
|
||||||
*/
|
*/
|
||||||
public class ServletContextAttributeFactoryBean implements FactoryBean<Object>, ServletContextAware {
|
public class ServletContextAttributeFactoryBean implements FactoryBean<Object>, ServletContextAware {
|
||||||
|
|
@ -52,7 +57,7 @@ public class ServletContextAttributeFactoryBean implements FactoryBean<Object>,
|
||||||
|
|
||||||
public void setServletContext(ServletContext servletContext) {
|
public void setServletContext(ServletContext servletContext) {
|
||||||
if (this.attributeName == null) {
|
if (this.attributeName == null) {
|
||||||
throw new IllegalArgumentException("attributeName is required");
|
throw new IllegalArgumentException("Property 'attributeName' is required");
|
||||||
}
|
}
|
||||||
this.attribute = servletContext.getAttribute(this.attributeName);
|
this.attribute = servletContext.getAttribute(this.attributeName);
|
||||||
if (this.attribute == null) {
|
if (this.attribute == null) {
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,11 @@ import org.springframework.web.context.ServletContextAware;
|
||||||
* @see javax.servlet.ServletContext
|
* @see javax.servlet.ServletContext
|
||||||
* @see org.springframework.web.context.ServletContextAware
|
* @see org.springframework.web.context.ServletContextAware
|
||||||
* @see ServletContextAttributeFactoryBean
|
* @see ServletContextAttributeFactoryBean
|
||||||
|
* @see org.springframework.web.context.WebApplicationContext#SERVLET_CONTEXT_BEAN_NAME
|
||||||
|
* @deprecated as of Spring 3.0, since "servletContext" is now available
|
||||||
|
* as a default bean in every WebApplicationContext
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public class ServletContextFactoryBean implements FactoryBean<ServletContext>, ServletContextAware {
|
public class ServletContextFactoryBean implements FactoryBean<ServletContext>, ServletContextAware {
|
||||||
|
|
||||||
private ServletContext servletContext;
|
private ServletContext servletContext;
|
||||||
|
|
|
||||||
|
|
@ -27,8 +27,13 @@ import org.springframework.web.context.ServletContextAware;
|
||||||
* Exposes that ServletContext init parameter when used as bean reference,
|
* Exposes that ServletContext init parameter when used as bean reference,
|
||||||
* effectively making it available as named Spring bean instance.
|
* effectively making it available as named Spring bean instance.
|
||||||
*
|
*
|
||||||
|
* <p><b>NOTE:</b> As of Spring 3.0, you may also use the "contextParameters" default
|
||||||
|
* bean which is of type Map, and dereference it using an "#{contextParameters.myKey}"
|
||||||
|
* expression to access a specific parameter by name.
|
||||||
|
*
|
||||||
* @author Juergen Hoeller
|
* @author Juergen Hoeller
|
||||||
* @since 1.2.4
|
* @since 1.2.4
|
||||||
|
* @see org.springframework.web.context.WebApplicationContext#CONTEXT_PARAMETERS_BEAN_NAME
|
||||||
* @see ServletContextAttributeFactoryBean
|
* @see ServletContextAttributeFactoryBean
|
||||||
*/
|
*/
|
||||||
public class ServletContextParameterFactoryBean implements FactoryBean<String>, ServletContextAware {
|
public class ServletContextParameterFactoryBean implements FactoryBean<String>, ServletContextAware {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,111 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2002-2009 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed 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
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* 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.springframework.web.context.support;
|
||||||
|
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import javax.servlet.ServletContext;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.DisposableBean;
|
||||||
|
import org.springframework.beans.factory.ObjectFactory;
|
||||||
|
import org.springframework.beans.factory.config.Scope;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link Scope} wrapper for a ServletContext, i.e. for global web application attributes.
|
||||||
|
*
|
||||||
|
* <p>This differs from traditional Spring singletons in that it exposes attributes in the
|
||||||
|
* ServletContext. Those attributes will get destroyed whenever the entire application
|
||||||
|
* shuts down, which might be earlier or later than the shutdown of the containing Spring
|
||||||
|
* ApplicationContext.
|
||||||
|
*
|
||||||
|
* <p>The associated destruction mechanism relies on a
|
||||||
|
* {@link org.springframework.web.context.ContextCleanupListener} being registered in
|
||||||
|
* <code>web.xml</code>. Note that {@link org.springframework.web.context.ContextLoaderListener}
|
||||||
|
* includes ContextCleanupListener's functionality.
|
||||||
|
*
|
||||||
|
* <p>This scope is registered as default scope with key
|
||||||
|
* {@link org.springframework.web.context.WebApplicationContext#SCOPE_APPLICATION "application"}.
|
||||||
|
*
|
||||||
|
* @author Juergen Hoeller
|
||||||
|
* @since 3.0
|
||||||
|
* @see org.springframework.web.context.ContextCleanupListener
|
||||||
|
*/
|
||||||
|
public class ServletContextScope implements Scope, DisposableBean {
|
||||||
|
|
||||||
|
private final ServletContext servletContext;
|
||||||
|
|
||||||
|
private final Map<String, Runnable> destructionCallbacks = new LinkedHashMap<String, Runnable>();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new Scope wrapper for the given ServletContext.
|
||||||
|
* @param servletContext the ServletContext to wrap
|
||||||
|
*/
|
||||||
|
public ServletContextScope(ServletContext servletContext) {
|
||||||
|
Assert.notNull(servletContext, "ServletContext must not be null");
|
||||||
|
this.servletContext = servletContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Object get(String name, ObjectFactory<?> objectFactory) {
|
||||||
|
Object scopedObject = this.servletContext.getAttribute(name);
|
||||||
|
if (scopedObject == null) {
|
||||||
|
scopedObject = objectFactory.getObject();
|
||||||
|
this.servletContext.setAttribute(name, scopedObject);
|
||||||
|
}
|
||||||
|
return scopedObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object remove(String name) {
|
||||||
|
Object scopedObject = this.servletContext.getAttribute(name);
|
||||||
|
if (scopedObject != null) {
|
||||||
|
this.servletContext.removeAttribute(name);
|
||||||
|
this.destructionCallbacks.remove(name);
|
||||||
|
return scopedObject;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void registerDestructionCallback(String name, Runnable callback) {
|
||||||
|
this.destructionCallbacks.put(name, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object resolveContextualObject(String key) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getConversationId() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoke all registered destruction callbacks.
|
||||||
|
* To be called on ServletContext shutdown.
|
||||||
|
* @see org.springframework.web.context.ContextCleanupListener
|
||||||
|
*/
|
||||||
|
public void destroy() {
|
||||||
|
for (Runnable runnable : this.destructionCallbacks.values()) {
|
||||||
|
runnable.run();
|
||||||
|
}
|
||||||
|
this.destructionCallbacks.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2008 the original author or authors.
|
* Copyright 2002-2009 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -29,8 +29,6 @@ import org.springframework.ui.context.support.UiApplicationContextUtils;
|
||||||
import org.springframework.web.context.ConfigurableWebApplicationContext;
|
import org.springframework.web.context.ConfigurableWebApplicationContext;
|
||||||
import org.springframework.web.context.ServletConfigAware;
|
import org.springframework.web.context.ServletConfigAware;
|
||||||
import org.springframework.web.context.ServletContextAware;
|
import org.springframework.web.context.ServletContextAware;
|
||||||
import org.springframework.web.context.request.RequestScope;
|
|
||||||
import org.springframework.web.context.request.SessionScope;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Static {@link org.springframework.web.context.WebApplicationContext}
|
* Static {@link org.springframework.web.context.WebApplicationContext}
|
||||||
|
|
@ -137,11 +135,9 @@ public class StaticWebApplicationContext extends StaticApplicationContext
|
||||||
beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext, this.servletConfig));
|
beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext, this.servletConfig));
|
||||||
beanFactory.ignoreDependencyInterface(ServletContextAware.class);
|
beanFactory.ignoreDependencyInterface(ServletContextAware.class);
|
||||||
beanFactory.ignoreDependencyInterface(ServletConfigAware.class);
|
beanFactory.ignoreDependencyInterface(ServletConfigAware.class);
|
||||||
beanFactory.registerResolvableDependency(ServletContext.class, this.servletContext);
|
|
||||||
beanFactory.registerResolvableDependency(ServletConfig.class, this.servletConfig);
|
|
||||||
|
|
||||||
WebApplicationContextUtils.registerWebApplicationScopes(beanFactory);
|
WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext);
|
||||||
WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext);
|
WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext, this.servletConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,9 @@ import java.util.Collections;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import javax.faces.context.ExternalContext;
|
||||||
|
import javax.faces.context.FacesContext;
|
||||||
|
import javax.servlet.ServletConfig;
|
||||||
import javax.servlet.ServletContext;
|
import javax.servlet.ServletContext;
|
||||||
import javax.servlet.ServletRequest;
|
import javax.servlet.ServletRequest;
|
||||||
import javax.servlet.http.HttpSession;
|
import javax.servlet.http.HttpSession;
|
||||||
|
|
@ -27,6 +30,8 @@ import javax.servlet.http.HttpSession;
|
||||||
import org.springframework.beans.factory.ObjectFactory;
|
import org.springframework.beans.factory.ObjectFactory;
|
||||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.ClassUtils;
|
||||||
|
import org.springframework.web.context.ConfigurableWebApplicationContext;
|
||||||
import org.springframework.web.context.WebApplicationContext;
|
import org.springframework.web.context.WebApplicationContext;
|
||||||
import org.springframework.web.context.request.RequestAttributes;
|
import org.springframework.web.context.request.RequestAttributes;
|
||||||
import org.springframework.web.context.request.RequestContextHolder;
|
import org.springframework.web.context.request.RequestContextHolder;
|
||||||
|
|
@ -49,10 +54,15 @@ import org.springframework.web.context.request.SessionScope;
|
||||||
* @see org.springframework.web.servlet.FrameworkServlet
|
* @see org.springframework.web.servlet.FrameworkServlet
|
||||||
* @see org.springframework.web.servlet.DispatcherServlet
|
* @see org.springframework.web.servlet.DispatcherServlet
|
||||||
* @see org.springframework.web.jsf.FacesContextUtils
|
* @see org.springframework.web.jsf.FacesContextUtils
|
||||||
* @see org.springframework.web.jsf.DelegatingVariableResolver
|
* @see org.springframework.web.jsf.SpringBeanVariableResolver
|
||||||
|
* @see org.springframework.web.jsf.el.SpringBeanFacesELResolver
|
||||||
*/
|
*/
|
||||||
public abstract class WebApplicationContextUtils {
|
public abstract class WebApplicationContextUtils {
|
||||||
|
|
||||||
|
private static final boolean jsfPresent =
|
||||||
|
ClassUtils.isPresent("javax.faces.context.FacesContext", RequestContextHolder.class.getClassLoader());
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find the root WebApplicationContext for this web application, which is
|
* Find the root WebApplicationContext for this web application, which is
|
||||||
* typically loaded via {@link org.springframework.web.context.ContextLoaderListener}.
|
* typically loaded via {@link org.springframework.web.context.ContextLoaderListener}.
|
||||||
|
|
@ -64,7 +74,7 @@ public abstract class WebApplicationContextUtils {
|
||||||
* @see org.springframework.web.context.WebApplicationContext#ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE
|
* @see org.springframework.web.context.WebApplicationContext#ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE
|
||||||
*/
|
*/
|
||||||
public static WebApplicationContext getRequiredWebApplicationContext(ServletContext sc)
|
public static WebApplicationContext getRequiredWebApplicationContext(ServletContext sc)
|
||||||
throws IllegalStateException {
|
throws IllegalStateException {
|
||||||
|
|
||||||
WebApplicationContext wac = getWebApplicationContext(sc);
|
WebApplicationContext wac = getWebApplicationContext(sc);
|
||||||
if (wac == null) {
|
if (wac == null) {
|
||||||
|
|
@ -115,14 +125,30 @@ public abstract class WebApplicationContextUtils {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register web-specific scopes with the given BeanFactory,
|
* Register web-specific scopes ("request", "session", "globalSession")
|
||||||
* as used by the WebApplicationContext.
|
* with the given BeanFactory, as used by the WebApplicationContext.
|
||||||
* @param beanFactory the BeanFactory to configure
|
* @param beanFactory the BeanFactory to configure
|
||||||
*/
|
*/
|
||||||
public static void registerWebApplicationScopes(ConfigurableListableBeanFactory beanFactory) {
|
public static void registerWebApplicationScopes(ConfigurableListableBeanFactory beanFactory) {
|
||||||
|
registerWebApplicationScopes(beanFactory, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register web-specific scopes ("request", "session", "globalSession", "application")
|
||||||
|
* with the given BeanFactory, as used by the WebApplicationContext.
|
||||||
|
* @param beanFactory the BeanFactory to configure
|
||||||
|
* @param sc the ServletContext that we're running within
|
||||||
|
*/
|
||||||
|
public static void registerWebApplicationScopes(ConfigurableListableBeanFactory beanFactory, ServletContext sc) {
|
||||||
beanFactory.registerScope(WebApplicationContext.SCOPE_REQUEST, new RequestScope());
|
beanFactory.registerScope(WebApplicationContext.SCOPE_REQUEST, new RequestScope());
|
||||||
beanFactory.registerScope(WebApplicationContext.SCOPE_SESSION, new SessionScope(false));
|
beanFactory.registerScope(WebApplicationContext.SCOPE_SESSION, new SessionScope(false));
|
||||||
beanFactory.registerScope(WebApplicationContext.SCOPE_GLOBAL_SESSION, new SessionScope(true));
|
beanFactory.registerScope(WebApplicationContext.SCOPE_GLOBAL_SESSION, new SessionScope(true));
|
||||||
|
if (sc != null) {
|
||||||
|
ServletContextScope appScope = new ServletContextScope(sc);
|
||||||
|
beanFactory.registerScope(WebApplicationContext.SCOPE_APPLICATION, appScope);
|
||||||
|
// Register as ServletContext attribute, for ContextCleanupListener to detect it.
|
||||||
|
sc.setAttribute(ServletContextScope.class.getName(), appScope);
|
||||||
|
}
|
||||||
|
|
||||||
beanFactory.registerResolvableDependency(ServletRequest.class, new ObjectFactory<ServletRequest>() {
|
beanFactory.registerResolvableDependency(ServletRequest.class, new ObjectFactory<ServletRequest>() {
|
||||||
public ServletRequest getObject() {
|
public ServletRequest getObject() {
|
||||||
|
|
@ -142,16 +168,41 @@ public abstract class WebApplicationContextUtils {
|
||||||
return ((ServletRequestAttributes) requestAttr).getRequest().getSession();
|
return ((ServletRequestAttributes) requestAttr).getRequest().getSession();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (jsfPresent) {
|
||||||
|
FacesDependencyRegistrar.registerFacesDependencies(beanFactory);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register web-specific environment beans with the given BeanFactory,
|
* Register web-specific environment beans ("contextParameters", "contextAttributes")
|
||||||
* as used by the WebApplicationContext.
|
* with the given BeanFactory, as used by the WebApplicationContext.
|
||||||
* @param bf the BeanFactory to configure
|
* @param bf the BeanFactory to configure
|
||||||
* @param sc the ServletContext that we're running within
|
* @param sc the ServletContext that we're running within
|
||||||
*/
|
*/
|
||||||
static void registerEnvironmentBeans(ConfigurableListableBeanFactory bf, ServletContext sc) {
|
public static void registerEnvironmentBeans(ConfigurableListableBeanFactory bf, ServletContext sc) {
|
||||||
if (!bf.containsBean(WebApplicationContext.CONTEXT_PROPERTIES_BEAN_NAME)) {
|
registerEnvironmentBeans(bf, sc, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register web-specific environment beans ("contextParameters", "contextAttributes")
|
||||||
|
* with the given BeanFactory, as used by the WebApplicationContext.
|
||||||
|
* @param bf the BeanFactory to configure
|
||||||
|
* @param sc the ServletContext that we're running within
|
||||||
|
* @param config the ServletConfig of the containing Portlet
|
||||||
|
*/
|
||||||
|
public static void registerEnvironmentBeans(
|
||||||
|
ConfigurableListableBeanFactory bf, ServletContext sc, ServletConfig config) {
|
||||||
|
|
||||||
|
if (sc != null && !bf.containsBean(WebApplicationContext.SERVLET_CONTEXT_BEAN_NAME)) {
|
||||||
|
bf.registerSingleton(WebApplicationContext.SERVLET_CONTEXT_BEAN_NAME, sc);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config != null && !bf.containsBean(ConfigurableWebApplicationContext.SERVLET_CONFIG_BEAN_NAME)) {
|
||||||
|
bf.registerSingleton(ConfigurableWebApplicationContext.SERVLET_CONFIG_BEAN_NAME, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!bf.containsBean(WebApplicationContext.CONTEXT_PARAMETERS_BEAN_NAME)) {
|
||||||
Map<String, String> parameterMap = new HashMap<String, String>();
|
Map<String, String> parameterMap = new HashMap<String, String>();
|
||||||
if (sc != null) {
|
if (sc != null) {
|
||||||
Enumeration paramNameEnum = sc.getInitParameterNames();
|
Enumeration paramNameEnum = sc.getInitParameterNames();
|
||||||
|
|
@ -160,7 +211,14 @@ public abstract class WebApplicationContextUtils {
|
||||||
parameterMap.put(paramName, sc.getInitParameter(paramName));
|
parameterMap.put(paramName, sc.getInitParameter(paramName));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bf.registerSingleton(WebApplicationContext.CONTEXT_PROPERTIES_BEAN_NAME,
|
if (config != null) {
|
||||||
|
Enumeration paramNameEnum = config.getInitParameterNames();
|
||||||
|
while (paramNameEnum.hasMoreElements()) {
|
||||||
|
String paramName = (String) paramNameEnum.nextElement();
|
||||||
|
parameterMap.put(paramName, config.getInitParameter(paramName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bf.registerSingleton(WebApplicationContext.CONTEXT_PARAMETERS_BEAN_NAME,
|
||||||
Collections.unmodifiableMap(parameterMap));
|
Collections.unmodifiableMap(parameterMap));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -178,4 +236,24 @@ public abstract class WebApplicationContextUtils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inner class to avoid hard-coded JSF dependency.
|
||||||
|
*/
|
||||||
|
private static class FacesDependencyRegistrar {
|
||||||
|
|
||||||
|
public static void registerFacesDependencies(ConfigurableListableBeanFactory beanFactory) {
|
||||||
|
beanFactory.registerResolvableDependency(FacesContext.class, new ObjectFactory<FacesContext>() {
|
||||||
|
public FacesContext getObject() {
|
||||||
|
return FacesContext.getCurrentInstance();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
beanFactory.registerResolvableDependency(ExternalContext.class, new ObjectFactory<ExternalContext>() {
|
||||||
|
public ExternalContext getObject() {
|
||||||
|
return FacesContext.getCurrentInstance().getExternalContext();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,100 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2002-2009 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed 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
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* 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.springframework.web.context.request;
|
||||||
|
|
||||||
|
import javax.servlet.ServletContextEvent;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import org.springframework.beans.DerivedTestBean;
|
||||||
|
import org.springframework.beans.factory.support.GenericBeanDefinition;
|
||||||
|
import org.springframework.mock.web.MockHttpServletRequest;
|
||||||
|
import org.springframework.mock.web.MockServletContext;
|
||||||
|
import org.springframework.web.context.ContextCleanupListener;
|
||||||
|
import org.springframework.web.context.WebApplicationContext;
|
||||||
|
import org.springframework.web.context.support.GenericWebApplicationContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Juergen Hoeller
|
||||||
|
*/
|
||||||
|
public class WebApplicationContextScopeTests {
|
||||||
|
|
||||||
|
private static final String NAME = "scoped";
|
||||||
|
|
||||||
|
|
||||||
|
private WebApplicationContext initApplicationContext(String scope) {
|
||||||
|
MockServletContext sc = new MockServletContext();
|
||||||
|
GenericWebApplicationContext ac = new GenericWebApplicationContext(sc);
|
||||||
|
GenericBeanDefinition bd = new GenericBeanDefinition();
|
||||||
|
bd.setBeanClass(DerivedTestBean.class);
|
||||||
|
bd.setScope(scope);
|
||||||
|
ac.registerBeanDefinition(NAME, bd);
|
||||||
|
ac.refresh();
|
||||||
|
return ac;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRequestScope() {
|
||||||
|
WebApplicationContext ac = initApplicationContext(WebApplicationContext.SCOPE_REQUEST);
|
||||||
|
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||||
|
ServletRequestAttributes requestAttributes = new ServletRequestAttributes(request);
|
||||||
|
RequestContextHolder.setRequestAttributes(requestAttributes);
|
||||||
|
try {
|
||||||
|
assertNull(request.getAttribute(NAME));
|
||||||
|
DerivedTestBean bean = ac.getBean(NAME, DerivedTestBean.class);
|
||||||
|
assertSame(bean, request.getAttribute(NAME));
|
||||||
|
assertSame(bean, ac.getBean(NAME));
|
||||||
|
requestAttributes.requestCompleted();
|
||||||
|
assertTrue(bean.wasDestroyed());
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
RequestContextHolder.setRequestAttributes(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSessionScope() {
|
||||||
|
WebApplicationContext ac = initApplicationContext(WebApplicationContext.SCOPE_SESSION);
|
||||||
|
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||||
|
ServletRequestAttributes requestAttributes = new ServletRequestAttributes(request);
|
||||||
|
RequestContextHolder.setRequestAttributes(requestAttributes);
|
||||||
|
try {
|
||||||
|
assertNull(request.getSession().getAttribute(NAME));
|
||||||
|
DerivedTestBean bean = ac.getBean(NAME, DerivedTestBean.class);
|
||||||
|
assertSame(bean, request.getSession().getAttribute(NAME));
|
||||||
|
assertSame(bean, ac.getBean(NAME));
|
||||||
|
request.getSession().invalidate();
|
||||||
|
assertTrue(bean.wasDestroyed());
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
RequestContextHolder.setRequestAttributes(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testApplicationScope() {
|
||||||
|
WebApplicationContext ac = initApplicationContext(WebApplicationContext.SCOPE_APPLICATION);
|
||||||
|
assertNull(ac.getServletContext().getAttribute(NAME));
|
||||||
|
DerivedTestBean bean = ac.getBean(NAME, DerivedTestBean.class);
|
||||||
|
assertSame(bean, ac.getServletContext().getAttribute(NAME));
|
||||||
|
assertSame(bean, ac.getBean(NAME));
|
||||||
|
new ContextCleanupListener().contextDestroyed(new ServletContextEvent(ac.getServletContext()));
|
||||||
|
assertTrue(bean.wasDestroyed());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue