SPR-6236: Reintroduce Struts support

This commit is contained in:
Arjen Poutsma 2009-10-15 10:31:47 +00:00
parent e24e768054
commit 7fa9105096
33 changed files with 3931 additions and 0 deletions

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="org.springframework.web.struts">
<property file="${basedir}/../build.properties"/>
<import file="${basedir}/../build-spring-framework/package-bundle.xml"/>
<import file="${basedir}/../spring-build/standard/default.xml"/>
</project>

View File

@ -0,0 +1,92 @@
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="http://ivyrep.jayasoft.org/ivy-doc.xsl"?>
<ivy-module
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://incubator.apache.org/ivy/schemas/ivy.xsd"
version="1.3">
<info organisation="org.springframework" module="${ant.project.name}">
<license name="Apache 2.0" url="http://www.apache.org/licenses/LICENSE-2.0"/>
</info>
<configurations>
<include file="${spring.build.dir}/common/default-ivy-configurations.xml"/>
<conf name="tiles" extends="runtime" description="JARs neeeded to create beans for Tiles"/>
</configurations>
<publications>
<artifact name="${ant.project.name}"/>
<artifact name="${ant.project.name}-sources" type="src" ext="jar"/>
</publications>
<dependencies>
<dependency org="javax.servlet" name="com.springsource.javax.servlet" rev="2.5.0" conf="provided->compile"/>
<dependency org="org.apache.commons" name="com.springsource.org.apache.commons.logging" rev="1.1.1"
conf="compile->compile"/>
<dependency org="org.apache.commons" name="com.springsource.org.apache.commons.beanutils" rev="1.7.0"
conf="compile->compile"/>
<dependency org="org.apache.struts" name="com.springsource.org.apache.struts" rev="1.2.9" />
<dependency org="org.springframework" name="org.springframework.beans" rev="latest.integration"
conf="compile->compile"/>
<dependency org="org.springframework" name="org.springframework.context" rev="latest.integration"
conf="compile->compile"/>
<dependency org="org.springframework" name="org.springframework.core" rev="latest.integration"
conf="compile->compile"/>
<dependency org="org.springframework" name="org.springframework.web" rev="latest.integration"
conf="compile->compile"/>
<dependency org="org.springframework" name="org.springframework.web.servlet" rev="latest.integration"
conf="optional, tiles->compile"/>
<!--
<dependency org="com.sun.syndication" name="com.springsource.com.sun.syndication" rev="1.0.0"
conf="optional, feed->compile"/>
<dependency org="com.lowagie.text" name="com.springsource.com.lowagie.text" rev="2.0.8"
conf="optional, itext->compile"/>
<dependency org="org.freemarker" name="com.springsource.freemarker" rev="2.3.15"
conf="optional, freemarker->compile"/>
<dependency org="javax.el" name="com.springsource.javax.el" rev="1.0.0" conf="provided->compile"/>
<dependency org="javax.servlet" name="com.springsource.javax.servlet.jsp" rev="2.1.0" conf="provided->compile"/>
<dependency org="javax.servlet" name="com.springsource.javax.servlet.jsp.jstl" rev="1.1.2"
conf="provided->compile"/>
<dependency org="net.sourceforge.jexcelapi" name="com.springsource.jxl" rev="2.6.6"
conf="optional, jexcelapi->compile"/>
<dependency org="net.sourceforge.jasperreports" name="com.springsource.net.sf.jasperreports" rev="2.0.5"
conf="optional, jasper-reports->compile"/>
<dependency org="org.apache.commons" name="com.springsource.org.apache.commons.logging" rev="1.1.1"
conf="compile->compile"/>
<dependency org="org.apache.poi" name="com.springsource.org.apache.poi" rev="3.0.2.FINAL"
conf="optional, poi->compile"/>
<dependency org="org.apache.tiles" name="com.springsource.org.apache.tiles" rev="2.1.2.osgi"
conf="optional, tiles->compile"/>
<dependency org="org.apache.tiles" name="com.springsource.org.apache.tiles.core" rev="2.1.2.osgi"
conf="optional, tiles->compile"/>
<dependency org="org.apache.tiles" name="com.springsource.org.apache.tiles.jsp" rev="2.1.2"
conf="optional, tiles->compile"/>
<dependency org="org.apache.tiles" name="com.springsource.org.apache.tiles.servlet" rev="2.1.2"
conf="optional, tiles->compile"/>
<dependency org="org.apache.velocity" name="com.springsource.org.apache.velocity" rev="1.5.0"
conf="optional, velocity->compile"/>
<dependency org="org.apache.velocity" name="com.springsource.org.apache.velocity.tools.view" rev="1.4.0"
conf="optional, velocity->compile"/>
<dependency org="org.codehaus.jackson" name="com.springsource.org.codehaus.jackson.mapper" rev="1.0.0"
conf="optional, jackson->compile"/>
<dependency org="org.springframework" name="org.springframework.beans" rev="latest.integration"
conf="compile->compile"/>
<dependency org="org.springframework" name="org.springframework.context" rev="latest.integration"
conf="compile->compile"/>
<dependency org="org.springframework" name="org.springframework.context.support" rev="latest.integration"
conf="optional, velocity, freemarker, jasper-reports->compile"/>
<dependency org="org.springframework" name="org.springframework.core" rev="latest.integration"
conf="compile->compile"/>
<dependency org="org.springframework" name="org.springframework.oxm" rev="latest.integration"
conf="optional, oxm->compile"/>
-->
<!-- test dependencies -->
<dependency org="org.junit" name="com.springsource.org.junit" rev="4.7.0" conf="test->runtime"/>
<dependency org="org.easymock" name="com.springsource.org.easymock" rev="2.5.1" conf="test->compile"/>
<dependency org="org.springframework" name="org.springframework.test" rev="latest.integration"
conf="test->compile"/>
<dependency org="javax.servlet" name="com.springsource.javax.servlet.jsp.jstl" rev="1.1.2"
conf="test->compile"/>
</dependencies>
</ivy-module>

View File

@ -0,0 +1,180 @@
/*
* Copyright 2002-2008 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.servlet.view.tiles;
import java.io.File;
import java.io.IOException;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.tiles.ComponentContext;
import org.apache.struts.tiles.ControllerSupport;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.support.RequestContextUtils;
import org.springframework.web.util.NestedServletException;
import org.springframework.web.util.WebUtils;
/**
* Convenience class for Spring-aware Tiles component controllers.
* Provides a reference to the current Spring application context,
* e.g. for bean lookup or resource loading.
*
* <p>Derives from the Tiles {@link ControllerSupport} class rather than
* implementing the Tiles {@link org.apache.struts.tiles.Controller} interface
* in order to be compatible with Struts 1.1 and 1.2. Implements both Struts 1.1's
* <code>perform</code> and Struts 1.2's <code>execute</code> method accordingly.
*
* @author Juergen Hoeller
* @author Alef Arendsen
* @since 22.08.2003
* @see org.springframework.web.context.support.WebApplicationObjectSupport
* @deprecated as of Spring 3.0
*/
@Deprecated
public abstract class ComponentControllerSupport extends ControllerSupport {
private WebApplicationContext webApplicationContext;
private MessageSourceAccessor messageSourceAccessor;
/**
* This implementation delegates to <code>execute</code>,
* converting non-Servlet/IO Exceptions to ServletException.
* <p>This is the only execution method available in Struts 1.1.
* @see #execute
*/
@Override
public final void perform(
ComponentContext componentContext, HttpServletRequest request,
HttpServletResponse response, ServletContext servletContext)
throws ServletException, IOException {
try {
execute(componentContext, request, response, servletContext);
}
catch (ServletException ex) {
throw ex;
}
catch (IOException ex) {
throw ex;
}
catch (Throwable ex) {
throw new NestedServletException("Execution of component controller failed", ex);
}
}
/**
* This implementation delegates to <code>doPerform</code>,
* lazy-initializing the application context reference if necessary.
* <p>This is the preferred execution method in Struts 1.2.
* When running with Struts 1.1, it will be called by <code>perform</code>.
* @see #perform
* @see #doPerform
*/
@Override
public final void execute(
ComponentContext componentContext, HttpServletRequest request,
HttpServletResponse response, ServletContext servletContext)
throws Exception {
synchronized (this) {
if (this.webApplicationContext == null) {
this.webApplicationContext = RequestContextUtils.getWebApplicationContext(request, servletContext);
this.messageSourceAccessor = new MessageSourceAccessor(this.webApplicationContext);
}
}
doPerform(componentContext, request, response);
}
/**
* Subclasses can override this for custom initialization behavior.
* Gets called on initialization of the context for this controller.
* @throws org.springframework.context.ApplicationContextException in case of initialization errors
* @throws org.springframework.beans.BeansException if thrown by application context methods
*/
protected void initApplicationContext() throws BeansException {
}
/**
* Return the current Spring ApplicationContext.
*/
protected final ApplicationContext getApplicationContext() {
return this.webApplicationContext;
}
/**
* Return the current Spring WebApplicationContext.
*/
protected final WebApplicationContext getWebApplicationContext() {
return this.webApplicationContext;
}
/**
* Return a MessageSourceAccessor for the application context
* used by this object, for easy message access.
*/
protected final MessageSourceAccessor getMessageSourceAccessor() {
return this.messageSourceAccessor;
}
/**
* Return the current ServletContext.
*/
protected final ServletContext getServletContext() {
return this.webApplicationContext.getServletContext();
}
/**
* Return the temporary directory for the current web application,
* as provided by the servlet container.
* @return the File representing the temporary directory
*/
protected final File getTempDir() {
return WebUtils.getTempDir(getServletContext());
}
/**
* Perform the preparation for the component, allowing for any Exception to be thrown.
* The ServletContext can be retrieved via getServletContext, if necessary.
* The Spring WebApplicationContext can be accessed via getWebApplicationContext.
* <p>This method will be called both in the Struts 1.1 and Struts 1.2 case,
* by <code>perform</code> or <code>execute</code>, respectively.
* @param componentContext current Tiles component context
* @param request current HTTP request
* @param response current HTTP response
* @throws Exception in case of errors
* @see org.apache.struts.tiles.Controller#perform
* @see #getServletContext
* @see #getWebApplicationContext
* @see #perform
* @see #execute
*/
protected abstract void doPerform(
ComponentContext componentContext, HttpServletRequest request, HttpServletResponse response)
throws Exception;
}

View File

@ -0,0 +1,149 @@
/*
* Copyright 2002-2007 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.servlet.view.tiles;
import org.apache.struts.tiles.DefinitionsFactory;
import org.apache.struts.tiles.DefinitionsFactoryConfig;
import org.apache.struts.tiles.DefinitionsFactoryException;
import org.apache.struts.tiles.TilesUtil;
import org.apache.struts.tiles.xmlDefinition.I18nFactorySet;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.StringUtils;
import org.springframework.web.context.support.WebApplicationObjectSupport;
/**
* Helper class to configure Tiles 1.x for the Spring Framework. See
* <a href="http://struts.apache.org">http://struts.apache.org</a>
* for more information about Struts Tiles, which basically is a templating
* mechanism for JSP-based web applications.
*
* <p><b>NOTE:</b> This TilesConfigurer class supports Tiles 1.x,
* a.k.a. "Struts Tiles", which comes as part of Struts 1.x.
* For Tiles 2.x support, check out
* {@link org.springframework.web.servlet.view.tiles2.TilesConfigurer}.
*
* <p>The TilesConfigurer simply configures a Tiles DefinitionsFactory using
* a set of files containing definitions, to be accessed by {@link TilesView}
* instances.
*
* <p>TilesViews can be managed by any {@link org.springframework.web.servlet.ViewResolver}.
* For simple convention-based view resolution, consider using
* {@link org.springframework.web.servlet.view.UrlBasedViewResolver} with the
* "viewClass" property set to "org.springframework.web.servlet.view.tiles.TilesView".
*
* <p>A typical TilesConfigurer bean definition looks as follows:
*
* <pre>
* &lt;bean id="tilesConfigurer" class="org.springframework.web.servlet.view.tiles.TilesConfigurer">
* &lt;property name="definitions">
* &lt;list>
* &lt;value>/WEB-INF/defs/general.xml&lt;/value>
* &lt;value>/WEB-INF/defs/widgets.xml&lt;/value>
* &lt;value>/WEB-INF/defs/administrator.xml&lt;/value>
* &lt;value>/WEB-INF/defs/customer.xml&lt;/value>
* &lt;value>/WEB-INF/defs/templates.xml&lt;/value>
* &lt;/list>
* &lt;/property>
* &lt;/bean></pre>
*
* The values in the list are the actual files containing the definitions.
*
* @author Alef Arendsen
* @author Juergen Hoeller
* @see TilesView
* @see org.springframework.web.servlet.view.UrlBasedViewResolver
* @deprecated as of Spring 3.0
*/
@Deprecated
public class TilesConfigurer extends WebApplicationObjectSupport implements InitializingBean {
/** Definition URLs mapped to descriptions */
private String[] definitions;
/** Validate the Tiles definitions? */
private boolean validateDefinitions = true;
/** Factory class for Tiles */
private Class factoryClass = I18nFactorySet.class;
/**
* Set the Tiles definitions, i.e. the list of files containing the definitions.
*/
public void setDefinitions(String[] definitions) {
this.definitions = definitions;
}
/**
* Set whether to validate the Tiles XML definitions. Default is "true".
*/
public void setValidateDefinitions(boolean validateDefinitions) {
this.validateDefinitions = validateDefinitions;
}
/**
* Set the factory class for Tiles. Default is I18nFactorySet.
* @see org.apache.struts.tiles.xmlDefinition.I18nFactorySet
*/
public void setFactoryClass(Class factoryClass) {
this.factoryClass = factoryClass;
}
/**
* Initialize the Tiles definition factory.
* Delegates to createDefinitionsFactory for the actual creation.
* @throws DefinitionsFactoryException if an error occurs
* @see #createDefinitionsFactory
*/
public void afterPropertiesSet() throws DefinitionsFactoryException {
logger.debug("TilesConfigurer: initializion started");
// initialize the configuration for the definitions factory
DefinitionsFactoryConfig factoryConfig = new DefinitionsFactoryConfig();
factoryConfig.setFactoryName("");
factoryConfig.setFactoryClassname(this.factoryClass.getName());
factoryConfig.setParserValidate(this.validateDefinitions);
if (this.definitions != null) {
String defs = StringUtils.arrayToCommaDelimitedString(this.definitions);
if (logger.isInfoEnabled()) {
logger.info("TilesConfigurer: adding definitions [" + defs + "]");
}
factoryConfig.setDefinitionConfigFiles(defs);
}
// initialize the definitions factory
createDefinitionsFactory(factoryConfig);
logger.debug("TilesConfigurer: initialization completed");
}
/**
* Create the Tiles DefinitionsFactory and expose it to the ServletContext.
* @param factoryConfig the configuration for the DefinitionsFactory
* @return the DefinitionsFactory
* @throws DefinitionsFactoryException if an error occurs
*/
protected DefinitionsFactory createDefinitionsFactory(DefinitionsFactoryConfig factoryConfig)
throws DefinitionsFactoryException {
return TilesUtil.createDefinitionsFactory(getServletContext(), factoryConfig);
}
}

View File

@ -0,0 +1,53 @@
/*
* Copyright 2002-2008 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.servlet.view.tiles;
import javax.servlet.http.HttpServletRequest;
import org.springframework.web.servlet.support.JstlUtils;
import org.springframework.web.servlet.support.RequestContext;
/**
* Specialization of {@link TilesView} for JSTL pages,
* i.e. Tiles pages that use the JSP Standard Tag Library.
*
* <p><b>NOTE:</b> This TilesJstlView class supports Tiles 1.x,
* a.k.a. "Struts Tiles", which comes as part of Struts 1.x.
* For Tiles 2.x support, check out
* {@link org.springframework.web.servlet.view.tiles2.TilesView}.
*
* <p>Exposes JSTL-specific request attributes specifying locale
* and resource bundle for JSTL's formatting and message tags,
* using Spring's locale and message source.
*
* <p>This is a separate class mainly to avoid JSTL dependencies
* in TilesView itself.
*
* @author Juergen Hoeller
* @since 20.08.2003
* @see org.springframework.web.servlet.support.JstlUtils#exposeLocalizationContext
* @deprecated as of Spring 3.0
*/
@Deprecated
public class TilesJstlView extends TilesView {
@Override
protected void exposeHelpers(HttpServletRequest request) throws Exception {
JstlUtils.exposeLocalizationContext(new RequestContext(request, getServletContext()));
}
}

View File

@ -0,0 +1,209 @@
/*
* Copyright 2002-2007 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.servlet.view.tiles;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.tiles.ComponentContext;
import org.apache.struts.tiles.ComponentDefinition;
import org.apache.struts.tiles.Controller;
import org.apache.struts.tiles.DefinitionsFactory;
import org.apache.struts.tiles.TilesUtilImpl;
import org.springframework.context.ApplicationContextException;
import org.springframework.web.servlet.view.InternalResourceView;
/**
* View implementation that retrieves a Tiles definition.
* The "url" property is interpreted as name of a Tiles definition.
*
* <p>{@link TilesJstlView} with JSTL support is a separate class,
* mainly to avoid JSTL dependencies in this class.
*
* <p><b>NOTE:</b> This TilesView class supports Tiles 1.x,
* a.k.a. "Struts Tiles", which comes as part of Struts 1.x.
* For Tiles 2.x support, check out
* {@link org.springframework.web.servlet.view.tiles2.TilesView}.
*
* <p>Depends on a Tiles DefinitionsFactory which must be available
* in the ServletContext. This factory is typically set up via a
* {@link TilesConfigurer} bean definition in the application context.
*
* <p>Check out {@link ComponentControllerSupport} which provides
* a convenient base class for Spring-aware component controllers,
* allowing convenient access to the Spring ApplicationContext.
*
* @author Alef Arendsen
* @author Juergen Hoeller
* @see #setUrl
* @see TilesJstlView
* @see TilesConfigurer
* @see ComponentControllerSupport
* @deprecated as of Spring 3.0
*/
@Deprecated
public class TilesView extends InternalResourceView {
/**
* Name of the attribute that will override the path of the layout page
* to render. A Tiles component controller can set such an attribute
* to dynamically switch the look and feel of a Tiles page.
* @see #setPath
*/
public static final String PATH_ATTRIBUTE = TilesView.class.getName() + ".PATH";
/**
* Set the path of the layout page to render.
* @param request current HTTP request
* @param path the path of the layout page
* @see #PATH_ATTRIBUTE
*/
public static void setPath(HttpServletRequest request, String path) {
request.setAttribute(PATH_ATTRIBUTE, path);
}
private DefinitionsFactory definitionsFactory;
@Override
protected void initApplicationContext() throws ApplicationContextException {
super.initApplicationContext();
// get definitions factory
this.definitionsFactory =
(DefinitionsFactory) getServletContext().getAttribute(TilesUtilImpl.DEFINITIONS_FACTORY);
if (this.definitionsFactory == null) {
throw new ApplicationContextException("Tiles definitions factory not found: TilesConfigurer not defined?");
}
}
/**
* Prepare for rendering the Tiles definition: Execute the associated
* component controller if any, and determine the request dispatcher path.
*/
@Override
protected String prepareForRendering(HttpServletRequest request, HttpServletResponse response)
throws Exception {
// get component definition
ComponentDefinition definition = getComponentDefinition(this.definitionsFactory, request);
if (definition == null) {
throw new ServletException("No Tiles definition found for name '" + getUrl() + "'");
}
// get current component context
ComponentContext context = getComponentContext(definition, request);
// execute component controller associated with definition, if any
Controller controller = getController(definition, request);
if (controller != null) {
if (logger.isDebugEnabled()) {
logger.debug("Executing Tiles controller [" + controller + "]");
}
executeController(controller, context, request, response);
}
// determine the path of the definition
String path = getDispatcherPath(definition, request);
if (path == null) {
throw new ServletException(
"Could not determine a path for Tiles definition '" + definition.getName() + "'");
}
return path;
}
/**
* Determine the Tiles component definition for the given Tiles
* definitions factory.
* @param factory the Tiles definitions factory
* @param request current HTTP request
* @return the component definition
*/
protected ComponentDefinition getComponentDefinition(DefinitionsFactory factory, HttpServletRequest request)
throws Exception {
return factory.getDefinition(getUrl(), request, getServletContext());
}
/**
* Determine the Tiles component context for the given Tiles definition.
* @param definition the Tiles definition to render
* @param request current HTTP request
* @return the component context
* @throws Exception if preparations failed
*/
protected ComponentContext getComponentContext(ComponentDefinition definition, HttpServletRequest request)
throws Exception {
ComponentContext context = ComponentContext.getContext(request);
if (context == null) {
context = new ComponentContext(definition.getAttributes());
ComponentContext.setContext(context, request);
}
else {
context.addMissing(definition.getAttributes());
}
return context;
}
/**
* Determine and initialize the Tiles component controller for the
* given Tiles definition, if any.
* @param definition the Tiles definition to render
* @param request current HTTP request
* @return the component controller to execute, or <code>null</code> if none
* @throws Exception if preparations failed
*/
protected Controller getController(ComponentDefinition definition, HttpServletRequest request)
throws Exception {
return definition.getOrCreateController();
}
/**
* Execute the given Tiles controller.
* @param controller the component controller to execute
* @param context the component context
* @param request current HTTP request
* @param response current HTTP response
* @throws Exception if controller execution failed
*/
protected void executeController(
Controller controller, ComponentContext context, HttpServletRequest request, HttpServletResponse response)
throws Exception {
controller.perform(context, request, response, getServletContext());
}
/**
* Determine the dispatcher path for the given Tiles definition,
* i.e. the request dispatcher path of the layout page.
* @param definition the Tiles definition to render
* @param request current HTTP request
* @return the path of the layout page to render
* @throws Exception if preparations failed
*/
protected String getDispatcherPath(ComponentDefinition definition, HttpServletRequest request)
throws Exception {
Object pathAttr = request.getAttribute(PATH_ATTRIBUTE);
return (pathAttr != null ? pathAttr.toString() : definition.getPath());
}
}

View File

@ -0,0 +1,10 @@
<html>
<body>
Support classes for the integration of
<a href="http://www.lifl.fr/~dumoulin/tiles">Tiles</a>
(included in Struts) as Spring web view technology.
Contains a View implementation for Tiles definitions.
</body>
</html>

View File

@ -0,0 +1,72 @@
/*
* Copyright 2002-2007 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.struts;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionServlet;
import org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor;
/**
* {@link org.springframework.beans.factory.config.BeanPostProcessor}
* implementation that passes the ActionServlet to beans that extend
* the Struts {@link org.apache.struts.action.Action} class.
* Invokes <code>Action.setServlet</code> with <code>null</dode> on
* bean destruction, providing the same lifecycle handling as the
* native Struts ActionServlet.
*
* <p>ContextLoaderPlugIn automatically registers this processor
* with the underlying bean factory of its WebApplicationContext.
*
* @author Juergen Hoeller
* @since 1.0.1
* @see ContextLoaderPlugIn
* @see org.apache.struts.action.Action#setServlet
* @deprecated as of Spring 3.0
*/
@Deprecated
class ActionServletAwareProcessor implements DestructionAwareBeanPostProcessor {
private final ActionServlet actionServlet;
/**
* Create a new ActionServletAwareProcessor for the given servlet.
*/
public ActionServletAwareProcessor(ActionServlet actionServlet) {
this.actionServlet = actionServlet;
}
public Object postProcessBeforeInitialization(Object bean, String beanName) {
if (bean instanceof Action) {
((Action) bean).setServlet(this.actionServlet);
}
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName) {
return bean;
}
public void postProcessBeforeDestruction(Object bean, String beanName) {
if (bean instanceof Action) {
((Action) bean).setServlet(null);
}
}
}

View File

@ -0,0 +1,151 @@
/*
* Copyright 2002-2005 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.struts;
import java.io.File;
import javax.servlet.ServletContext;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionServlet;
import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.util.WebUtils;
/**
* Convenience class for Spring-aware Struts 1.1+ Actions.
*
* <p>Provides a reference to the current Spring application context, e.g.
* for bean lookup or resource loading. Auto-detects a ContextLoaderPlugIn
* context, falling back to the root WebApplicationContext. For typical
* usage, i.e. accessing middle tier beans, use a root WebApplicationContext.
*
* <p>For Struts DispatchActions or Lookup/MappingDispatchActions, use the
* analogous {@link DispatchActionSupport DispatchActionSupport} or
* {@link LookupDispatchActionSupport LookupDispatchActionSupport} /
* {@link MappingDispatchActionSupport MappingDispatchActionSupport} class,
* respectively.
*
* <p>As an alternative approach, you can wire your Struts Actions themselves
* as Spring beans, passing references to them via IoC rather than looking
* up references in a programmatic fashion. Check out
* {@link DelegatingActionProxy DelegatingActionProxy} and
* {@link DelegatingRequestProcessor DelegatingRequestProcessor}.
*
* @author Juergen Hoeller
* @since 1.0.1
* @see ContextLoaderPlugIn#SERVLET_CONTEXT_PREFIX
* @see org.springframework.web.context.WebApplicationContext#ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE
* @see org.springframework.web.context.ContextLoaderListener
* @see org.springframework.web.context.ContextLoaderServlet
* @see DispatchActionSupport
* @see LookupDispatchActionSupport
* @see MappingDispatchActionSupport
* @see DelegatingActionProxy
* @see DelegatingRequestProcessor
* @deprecated as of Spring 3.0
*/
@Deprecated
public abstract class ActionSupport extends Action {
private WebApplicationContext webApplicationContext;
private MessageSourceAccessor messageSourceAccessor;
/**
* Initialize the WebApplicationContext for this Action.
* Invokes onInit after successful initialization of the context.
* @see #initWebApplicationContext
* @see #onInit
*/
@Override
public void setServlet(ActionServlet actionServlet) {
super.setServlet(actionServlet);
if (actionServlet != null) {
this.webApplicationContext = initWebApplicationContext(actionServlet);
this.messageSourceAccessor = new MessageSourceAccessor(this.webApplicationContext);
onInit();
}
else {
onDestroy();
}
}
/**
* Fetch ContextLoaderPlugIn's WebApplicationContext from the ServletContext,
* falling back to the root WebApplicationContext (the usual case).
* @param actionServlet the associated ActionServlet
* @return the WebApplicationContext
* @throws IllegalStateException if no WebApplicationContext could be found
* @see DelegatingActionUtils#findRequiredWebApplicationContext
*/
protected WebApplicationContext initWebApplicationContext(ActionServlet actionServlet)
throws IllegalStateException {
return DelegatingActionUtils.findRequiredWebApplicationContext(actionServlet, null);
}
/**
* Return the current Spring WebApplicationContext.
*/
protected final WebApplicationContext getWebApplicationContext() {
return this.webApplicationContext;
}
/**
* Return a MessageSourceAccessor for the application context
* used by this object, for easy message access.
*/
protected final MessageSourceAccessor getMessageSourceAccessor() {
return this.messageSourceAccessor;
}
/**
* Return the current ServletContext.
*/
protected final ServletContext getServletContext() {
return this.webApplicationContext.getServletContext();
}
/**
* Return the temporary directory for the current web application,
* as provided by the servlet container.
* @return the File representing the temporary directory
*/
protected final File getTempDir() {
return WebUtils.getTempDir(getServletContext());
}
/**
* Callback for custom initialization after the context has been set up.
* @see #setServlet
*/
protected void onInit() {
}
/**
* Callback for custom destruction when the ActionServlet shuts down.
* @see #setServlet
*/
protected void onDestroy() {
}
}

View File

@ -0,0 +1,187 @@
/*
* Copyright 2002-2006 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.struts;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionServlet;
import org.apache.struts.action.RequestProcessor;
import org.apache.struts.config.ModuleConfig;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.web.context.WebApplicationContext;
/**
* Subclass of Struts's default RequestProcessor that autowires Struts Actions
* with Spring beans defined in ContextLoaderPlugIn's WebApplicationContext
* or - in case of general service layer beans - in the root WebApplicationContext.
*
* <p>In the Struts config file, you simply continue to specify the original
* Action class. The instance created for that class will automatically get
* wired with matching service layer beans, that is, bean property setters
* will automatically be called if a service layer bean matches the property.
*
* <pre>
* &lt;action path="/login" type="myapp.MyAction"/&gt;</pre>
*
* There are two autowire modes available: "byType" and "byName". The default
* is "byType", matching service layer beans with the Action's bean property
* argument types. This behavior can be changed through specifying an "autowire"
* init-param for the Struts ActionServlet with the value "byName", which will
* match service layer bean names with the Action's bean property <i>names</i>.
*
* <p>Dependency checking is turned off by default: If no matching service
* layer bean can be found, the setter in question will simply not get invoked.
* To enforce matching service layer beans, consider specify the "dependencyCheck"
* init-param for the Struts ActionServlet with the value "true".
*
* <p>If you also need the Tiles setup functionality of the original
* TilesRequestProcessor, use AutowiringTilesRequestProcessor. As there's just
* a single central class to customize in Struts, we have to provide another
* subclass here, covering both the Tiles and the Spring delegation aspect.
*
* <p>The default implementation delegates to the DelegatingActionUtils
* class as fas as possible, to reuse as much code as possible despite
* the need to provide two RequestProcessor subclasses. If you need to
* subclass yet another RequestProcessor, take this class as a template,
* delegating to DelegatingActionUtils just like it.
*
* @author Juergen Hoeller
* @since 2.0
* @see AutowiringTilesRequestProcessor
* @see ContextLoaderPlugIn
* @see DelegatingActionUtils
* @deprecated as of Spring 3.0
*/
@Deprecated
public class AutowiringRequestProcessor extends RequestProcessor {
private WebApplicationContext webApplicationContext;
private int autowireMode = AutowireCapableBeanFactory.AUTOWIRE_NO;
private boolean dependencyCheck = false;
@Override
public void init(ActionServlet actionServlet, ModuleConfig moduleConfig) throws ServletException {
super.init(actionServlet, moduleConfig);
if (actionServlet != null) {
this.webApplicationContext = initWebApplicationContext(actionServlet, moduleConfig);
this.autowireMode = initAutowireMode(actionServlet, moduleConfig);
this.dependencyCheck = initDependencyCheck(actionServlet, moduleConfig);
}
}
/**
* Fetch ContextLoaderPlugIn's WebApplicationContext from the ServletContext,
* falling back to the root WebApplicationContext. This context is supposed
* to contain the service layer beans to wire the Struts Actions with.
* @param actionServlet the associated ActionServlet
* @param moduleConfig the associated ModuleConfig
* @return the WebApplicationContext
* @throws IllegalStateException if no WebApplicationContext could be found
* @see DelegatingActionUtils#findRequiredWebApplicationContext
* @see ContextLoaderPlugIn#SERVLET_CONTEXT_PREFIX
*/
protected WebApplicationContext initWebApplicationContext(
ActionServlet actionServlet, ModuleConfig moduleConfig) throws IllegalStateException {
WebApplicationContext wac =
DelegatingActionUtils.findRequiredWebApplicationContext(actionServlet, moduleConfig);
if (wac instanceof ConfigurableApplicationContext) {
((ConfigurableApplicationContext) wac).getBeanFactory().ignoreDependencyType(ActionServlet.class);
}
return wac;
}
/**
* Determine the autowire mode to use for wiring Struts Actions.
* <p>The default implementation checks the "autowire" init-param of the
* Struts ActionServlet, falling back to "AUTOWIRE_BY_TYPE" as default.
* @param actionServlet the associated ActionServlet
* @param moduleConfig the associated ModuleConfig
* @return the autowire mode to use
* @see DelegatingActionUtils#getAutowireMode
* @see org.springframework.beans.factory.config.AutowireCapableBeanFactory#autowireBeanProperties
* @see org.springframework.beans.factory.config.AutowireCapableBeanFactory#AUTOWIRE_BY_TYPE
* @see org.springframework.beans.factory.config.AutowireCapableBeanFactory#AUTOWIRE_BY_NAME
*/
protected int initAutowireMode(ActionServlet actionServlet, ModuleConfig moduleConfig) {
return DelegatingActionUtils.getAutowireMode(actionServlet);
}
/**
* Determine whether to apply a dependency check after wiring Struts Actions.
* <p>The default implementation checks the "dependencyCheck" init-param of the
* Struts ActionServlet, falling back to no dependency check as default.
* @param actionServlet the associated ActionServlet
* @param moduleConfig the associated ModuleConfig
* @return whether to enforce a dependency check or not
* @see DelegatingActionUtils#getDependencyCheck
* @see org.springframework.beans.factory.config.AutowireCapableBeanFactory#autowireBeanProperties
*/
protected boolean initDependencyCheck(ActionServlet actionServlet, ModuleConfig moduleConfig) {
return DelegatingActionUtils.getDependencyCheck(actionServlet);
}
/**
* Return the current Spring WebApplicationContext.
*/
protected final WebApplicationContext getWebApplicationContext() {
return this.webApplicationContext;
}
/**
* Return the autowire mode to use for wiring Struts Actions.
*/
protected final int getAutowireMode() {
return autowireMode;
}
/**
* Return whether to apply a dependency check after wiring Struts Actions.
*/
protected final boolean getDependencyCheck() {
return dependencyCheck;
}
/**
* Extend the base class method to autowire each created Action instance.
* @see org.springframework.beans.factory.config.AutowireCapableBeanFactory#autowireBeanProperties
*/
@Override
protected Action processActionCreate(
HttpServletRequest request, HttpServletResponse response, ActionMapping mapping)
throws IOException {
Action action = super.processActionCreate(request, response, mapping);
getWebApplicationContext().getAutowireCapableBeanFactory().autowireBeanProperties(
action, getAutowireMode(), getDependencyCheck());
return action;
}
}

View File

@ -0,0 +1,169 @@
/*
* Copyright 2002-2006 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.struts;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionServlet;
import org.apache.struts.config.ModuleConfig;
import org.apache.struts.tiles.TilesRequestProcessor;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.web.context.WebApplicationContext;
/**
* Subclass of Struts's TilesRequestProcessor that autowires Struts Actions
* with Spring beans defined in ContextLoaderPlugIn's WebApplicationContext
* or - in case of general service layer beans - in the root WebApplicationContext.
*
* <p>Behaves like
* {@link AutowiringRequestProcessor AutowiringRequestProcessor},
* but also provides the Tiles functionality of the original TilesRequestProcessor.
* As there's just a single central class to customize in Struts, we have to provide
* another subclass here, covering both the Tiles and the Spring delegation aspect.
*
* <p>The default implementation delegates to the DelegatingActionUtils
* class as fas as possible, to reuse as much code as possible despite
* the need to provide two RequestProcessor subclasses. If you need to
* subclass yet another RequestProcessor, take this class as a template,
* delegating to DelegatingActionUtils just like it.
*
* @author Juergen Hoeller
* @since 2.0
* @see AutowiringRequestProcessor
* @see ContextLoaderPlugIn
* @see DelegatingActionUtils
* @deprecated as of Spring 3.0
*/
@Deprecated
public class AutowiringTilesRequestProcessor extends TilesRequestProcessor {
private WebApplicationContext webApplicationContext;
private int autowireMode = AutowireCapableBeanFactory.AUTOWIRE_NO;
private boolean dependencyCheck = false;
@Override
public void init(ActionServlet actionServlet, ModuleConfig moduleConfig) throws ServletException {
super.init(actionServlet, moduleConfig);
if (actionServlet != null) {
this.webApplicationContext = initWebApplicationContext(actionServlet, moduleConfig);
this.autowireMode = initAutowireMode(actionServlet, moduleConfig);
this.dependencyCheck = initDependencyCheck(actionServlet, moduleConfig);
}
}
/**
* Fetch ContextLoaderPlugIn's WebApplicationContext from the ServletContext,
* falling back to the root WebApplicationContext. This context is supposed
* to contain the service layer beans to wire the Struts Actions with.
* @param actionServlet the associated ActionServlet
* @param moduleConfig the associated ModuleConfig
* @return the WebApplicationContext
* @throws IllegalStateException if no WebApplicationContext could be found
* @see DelegatingActionUtils#findRequiredWebApplicationContext
* @see ContextLoaderPlugIn#SERVLET_CONTEXT_PREFIX
*/
protected WebApplicationContext initWebApplicationContext(
ActionServlet actionServlet, ModuleConfig moduleConfig) throws IllegalStateException {
WebApplicationContext wac =
DelegatingActionUtils.findRequiredWebApplicationContext(actionServlet, moduleConfig);
if (wac instanceof ConfigurableApplicationContext) {
((ConfigurableApplicationContext) wac).getBeanFactory().ignoreDependencyType(ActionServlet.class);
}
return wac;
}
/**
* Determine the autowire mode to use for wiring Struts Actions.
* <p>The default implementation checks the "autowire" init-param of the
* Struts ActionServlet, falling back to "AUTOWIRE_BY_TYPE" as default.
* @param actionServlet the associated ActionServlet
* @param moduleConfig the associated ModuleConfig
* @return the autowire mode to use
* @see DelegatingActionUtils#getAutowireMode
* @see org.springframework.beans.factory.config.AutowireCapableBeanFactory#autowireBeanProperties
* @see org.springframework.beans.factory.config.AutowireCapableBeanFactory#AUTOWIRE_BY_TYPE
* @see org.springframework.beans.factory.config.AutowireCapableBeanFactory#AUTOWIRE_BY_NAME
*/
protected int initAutowireMode(ActionServlet actionServlet, ModuleConfig moduleConfig) {
return DelegatingActionUtils.getAutowireMode(actionServlet);
}
/**
* Determine whether to apply a dependency check after wiring Struts Actions.
* <p>The default implementation checks the "dependencyCheck" init-param of the
* Struts ActionServlet, falling back to no dependency check as default.
* @param actionServlet the associated ActionServlet
* @param moduleConfig the associated ModuleConfig
* @return whether to enforce a dependency check or not
* @see DelegatingActionUtils#getDependencyCheck
* @see org.springframework.beans.factory.config.AutowireCapableBeanFactory#autowireBeanProperties
*/
protected boolean initDependencyCheck(ActionServlet actionServlet, ModuleConfig moduleConfig) {
return DelegatingActionUtils.getDependencyCheck(actionServlet);
}
/**
* Return the current Spring WebApplicationContext.
*/
protected final WebApplicationContext getWebApplicationContext() {
return this.webApplicationContext;
}
/**
* Return the autowire mode to use for wiring Struts Actions.
*/
protected final int getAutowireMode() {
return autowireMode;
}
/**
* Return whether to apply a dependency check after wiring Struts Actions.
*/
protected final boolean getDependencyCheck() {
return dependencyCheck;
}
/**
* Extend the base class method to autowire each created Action instance.
* @see org.springframework.beans.factory.config.AutowireCapableBeanFactory#autowireBeanProperties
*/
@Override
protected Action processActionCreate(
HttpServletRequest request, HttpServletResponse response, ActionMapping mapping)
throws IOException {
Action action = super.processActionCreate(request, response, mapping);
getWebApplicationContext().getAutowireCapableBeanFactory().autowireBeanProperties(
action, getAutowireMode(), getDependencyCheck());
return action;
}
}

View File

@ -0,0 +1,397 @@
/*
* Copyright 2002-2007 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.struts;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts.action.ActionServlet;
import org.apache.struts.action.PlugIn;
import org.apache.struts.config.ModuleConfig;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.ApplicationContextException;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.context.ConfigurableWebApplicationContext;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.context.support.XmlWebApplicationContext;
/**
* Struts 1.1+ PlugIn that loads a Spring application context for the Struts
* ActionServlet. This context will automatically refer to the root
* WebApplicationContext (loaded by ContextLoaderListener/Servlet) as parent.
*
* <p>The default namespace of the WebApplicationContext is the name of the
* Struts ActionServlet, suffixed with "-servlet" (e.g. "action-servlet").
* The default location of the XmlWebApplicationContext configuration file
* is therefore "/WEB-INF/action-servlet.xml".
*
* <pre>
* &lt;plug-in className="org.springframework.web.struts.ContextLoaderPlugIn"/&gt;</pre>
*
* The location of the context configuration files can be customized
* through the "contextConfigLocation" setting, analogous to the root
* WebApplicationContext and FrameworkServlet contexts.
*
* <pre>
* &lt;plug-in className="org.springframework.web.struts.ContextLoaderPlugIn"&gt;
* &lt;set-property property="contextConfigLocation" value="/WEB-INF/action-servlet.xml /WEB-INF/myContext.xml"/&gt;
* &lt;/plug-in&gt;</pre>
*
* Beans defined in the ContextLoaderPlugIn context can be accessed
* from conventional Struts Actions, via fetching the WebApplicationContext
* reference from the ServletContext. ActionSupport and DispatchActionSupport
* are pre-built convenience classes that provide easy access to the context.
*
* <p>It is normally preferable to access Spring's root WebApplicationContext
* in such scenarios, though: A shared middle tier should be defined there
* rather than in a ContextLoaderPlugin context, for access by any web component.
* ActionSupport and DispatchActionSupport autodetect the root context too.
*
* <p>A special usage of this PlugIn is to define Struts Actions themselves
* as beans, typically wiring them with middle tier components defined in the
* root context. Such Actions will then be delegated to by proxy definitions
* in the Struts configuration, using the DelegatingActionProxy class or
* the DelegatingRequestProcessor.
*
* <p>Note that you can use a single ContextLoaderPlugIn for all Struts modules.
* That context can in turn be loaded from multiple XML files, for example split
* according to Struts modules. Alternatively, define one ContextLoaderPlugIn per
* Struts module, specifying appropriate "contextConfigLocation" parameters.
*
* <p>Note: The idea of delegating to Spring-managed Struts Actions originated in
* Don Brown's <a href="http://struts.sourceforge.net/struts-spring">Spring Struts Plugin</a>.
* ContextLoaderPlugIn and DelegatingActionProxy constitute a clean-room
* implementation of the same idea, essentially superseding the original plugin.
* Many thanks to Don Brown and Matt Raible for the original work and for the
* agreement to reimplement the idea in Spring proper!
*
* @author Juergen Hoeller
* @since 1.0.1
* @see #SERVLET_CONTEXT_PREFIX
* @see ActionSupport
* @see DispatchActionSupport
* @see DelegatingActionProxy
* @see DelegatingRequestProcessor
* @see DelegatingTilesRequestProcessor
* @see org.springframework.web.context.ContextLoaderListener
* @see org.springframework.web.context.ContextLoaderServlet
* @see org.springframework.web.servlet.FrameworkServlet
* @deprecated as of Spring 3.0
*/
@Deprecated
public class ContextLoaderPlugIn implements PlugIn {
/**
* Suffix for WebApplicationContext namespaces. If a Struts ActionServlet is
* given the name "action" in a context, the namespace used by this PlugIn will
* resolve to "action-servlet".
*/
public static final String DEFAULT_NAMESPACE_SUFFIX = "-servlet";
/**
* Default context class for ContextLoaderPlugIn.
* @see org.springframework.web.context.support.XmlWebApplicationContext
*/
public static final Class DEFAULT_CONTEXT_CLASS = XmlWebApplicationContext.class;
/**
* Prefix for the ServletContext attribute for the WebApplicationContext.
* The completion is the Struts module name.
*/
public static final String SERVLET_CONTEXT_PREFIX = ContextLoaderPlugIn.class.getName() + ".CONTEXT.";
protected final Log logger = LogFactory.getLog(getClass());
/** Custom WebApplicationContext class */
private Class contextClass = DEFAULT_CONTEXT_CLASS;
/** Namespace for this servlet */
private String namespace;
/** Explicit context config location */
private String contextConfigLocation;
/** The Struts ActionServlet that this PlugIn is registered with */
private ActionServlet actionServlet;
/** The Struts ModuleConfig that this PlugIn is registered with */
private ModuleConfig moduleConfig;
/** WebApplicationContext for the ActionServlet */
private WebApplicationContext webApplicationContext;
/**
* Set a custom context class by name. This class must be of type WebApplicationContext,
* when using the default ContextLoaderPlugIn implementation, the context class
* must also implement ConfigurableWebApplicationContext.
* @see #createWebApplicationContext
*/
public void setContextClassName(String contextClassName) throws ClassNotFoundException {
this.contextClass = ClassUtils.forName(contextClassName);
}
/**
* Set a custom context class. This class must be of type WebApplicationContext,
* when using the default ContextLoaderPlugIn implementation, the context class
* must also implement ConfigurableWebApplicationContext.
* @see #createWebApplicationContext
*/
public void setContextClass(Class contextClass) {
this.contextClass = contextClass;
}
/**
* Return the custom context class.
*/
public Class getContextClass() {
return this.contextClass;
}
/**
* Set a custom namespace for the ActionServlet,
* to be used for building a default context config location.
*/
public void setNamespace(String namespace) {
this.namespace = namespace;
}
/**
* Return the namespace for the ActionServlet, falling back to default scheme if
* no custom namespace was set: e.g. "test-servlet" for a servlet named "test".
*/
public String getNamespace() {
if (this.namespace != null) {
return this.namespace;
}
if (this.actionServlet != null) {
return this.actionServlet.getServletName() + DEFAULT_NAMESPACE_SUFFIX;
}
return null;
}
/**
* Set the context config location explicitly, instead of relying on the default
* location built from the namespace. This location string can consist of
* multiple locations separated by any number of commas and spaces.
*/
public void setContextConfigLocation(String contextConfigLocation) {
this.contextConfigLocation = contextConfigLocation;
}
/**
* Return the explicit context config location, if any.
*/
public String getContextConfigLocation() {
return this.contextConfigLocation;
}
/**
* Create the ActionServlet's WebApplicationContext.
*/
public final void init(ActionServlet actionServlet, ModuleConfig moduleConfig) throws ServletException {
long startTime = System.currentTimeMillis();
if (logger.isInfoEnabled()) {
logger.info("ContextLoaderPlugIn for Struts ActionServlet '" + actionServlet.getServletName() +
", module '" + moduleConfig.getPrefix() + "': initialization started");
}
this.actionServlet = actionServlet;
this.moduleConfig = moduleConfig;
try {
this.webApplicationContext = initWebApplicationContext();
onInit();
}
catch (RuntimeException ex) {
logger.error("Context initialization failed", ex);
throw ex;
}
if (logger.isInfoEnabled()) {
long elapsedTime = System.currentTimeMillis() - startTime;
logger.info("ContextLoaderPlugIn for Struts ActionServlet '" + actionServlet.getServletName() +
"', module '" + moduleConfig.getPrefix() + "': initialization completed in " + elapsedTime + " ms");
}
}
/**
* Return the Struts ActionServlet that this PlugIn is associated with.
*/
public final ActionServlet getActionServlet() {
return actionServlet;
}
/**
* Return the name of the ActionServlet that this PlugIn is associated with.
*/
public final String getServletName() {
return this.actionServlet.getServletName();
}
/**
* Return the ServletContext that this PlugIn is associated with.
*/
public final ServletContext getServletContext() {
return this.actionServlet.getServletContext();
}
/**
* Return the Struts ModuleConfig that this PlugIn is associated with.
*/
public final ModuleConfig getModuleConfig() {
return this.moduleConfig;
}
/**
* Return the prefix of the ModuleConfig that this PlugIn is associated with.
* @see org.apache.struts.config.ModuleConfig#getPrefix
*/
public final String getModulePrefix() {
return this.moduleConfig.getPrefix();
}
/**
* Initialize and publish the WebApplicationContext for the ActionServlet.
* <p>Delegates to {@link #createWebApplicationContext} for actual creation.
* <p>Can be overridden in subclasses. Call <code>getActionServlet()</code>
* and/or <code>getModuleConfig()</code> to access the Struts configuration
* that this PlugIn is associated with.
* @throws org.springframework.beans.BeansException if the context couldn't be initialized
* @throws IllegalStateException if there is already a context for the Struts ActionServlet
* @see #getActionServlet()
* @see #getServletName()
* @see #getServletContext()
* @see #getModuleConfig()
* @see #getModulePrefix()
*/
protected WebApplicationContext initWebApplicationContext() throws BeansException, IllegalStateException {
getServletContext().log("Initializing WebApplicationContext for Struts ActionServlet '" +
getServletName() + "', module '" + getModulePrefix() + "'");
WebApplicationContext parent = WebApplicationContextUtils.getWebApplicationContext(getServletContext());
WebApplicationContext wac = createWebApplicationContext(parent);
if (logger.isInfoEnabled()) {
logger.info("Using context class '" + wac.getClass().getName() + "' for servlet '" + getServletName() + "'");
}
// Publish the context as a servlet context attribute.
String attrName = getServletContextAttributeName();
getServletContext().setAttribute(attrName, wac);
if (logger.isDebugEnabled()) {
logger.debug("Published WebApplicationContext of Struts ActionServlet '" + getServletName() +
"', module '" + getModulePrefix() + "' as ServletContext attribute with name [" + attrName + "]");
}
return wac;
}
/**
* Instantiate the WebApplicationContext for the ActionServlet, either a default
* XmlWebApplicationContext or a custom context class if set.
* <p>This implementation expects custom contexts to implement ConfigurableWebApplicationContext.
* Can be overridden in subclasses.
* @throws org.springframework.beans.BeansException if the context couldn't be initialized
* @see #setContextClass
* @see org.springframework.web.context.support.XmlWebApplicationContext
*/
protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent)
throws BeansException {
if (logger.isDebugEnabled()) {
logger.debug("ContextLoaderPlugIn for Struts ActionServlet '" + getServletName() +
"', module '" + getModulePrefix() + "' will try to create custom WebApplicationContext " +
"context of class '" + getContextClass().getName() + "', using parent context [" + parent + "]");
}
if (!ConfigurableWebApplicationContext.class.isAssignableFrom(getContextClass())) {
throw new ApplicationContextException(
"Fatal initialization error in ContextLoaderPlugIn for Struts ActionServlet '" + getServletName() +
"', module '" + getModulePrefix() + "': custom WebApplicationContext class [" +
getContextClass().getName() + "] is not of type ConfigurableWebApplicationContext");
}
ConfigurableWebApplicationContext wac =
(ConfigurableWebApplicationContext) BeanUtils.instantiateClass(getContextClass());
wac.setParent(parent);
wac.setServletContext(getServletContext());
wac.setNamespace(getNamespace());
if (getContextConfigLocation() != null) {
wac.setConfigLocations(
StringUtils.tokenizeToStringArray(
getContextConfigLocation(), ConfigurableWebApplicationContext.CONFIG_LOCATION_DELIMITERS));
}
wac.addBeanFactoryPostProcessor(
new BeanFactoryPostProcessor() {
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
beanFactory.addBeanPostProcessor(new ActionServletAwareProcessor(getActionServlet()));
beanFactory.ignoreDependencyType(ActionServlet.class);
}
}
);
wac.refresh();
return wac;
}
/**
* Return the ServletContext attribute name for this PlugIn's WebApplicationContext.
* <p>The default implementation returns SERVLET_CONTEXT_PREFIX + module prefix.
* @see #SERVLET_CONTEXT_PREFIX
* @see #getModulePrefix()
*/
public String getServletContextAttributeName() {
return SERVLET_CONTEXT_PREFIX + getModulePrefix();
}
/**
* Return this PlugIn's WebApplicationContext.
*/
public final WebApplicationContext getWebApplicationContext() {
return webApplicationContext;
}
/**
* Callback for custom initialization after the context has been set up.
* @throws ServletException if initialization failed
*/
protected void onInit() throws ServletException {
}
/**
* Close the WebApplicationContext of the ActionServlet.
* @see org.springframework.context.ConfigurableApplicationContext#close()
*/
public void destroy() {
getServletContext().log("Closing WebApplicationContext of Struts ActionServlet '" +
getServletName() + "', module '" + getModulePrefix() + "'");
if (getWebApplicationContext() instanceof ConfigurableApplicationContext) {
((ConfigurableApplicationContext) getWebApplicationContext()).close();
}
}
}

View File

@ -0,0 +1,170 @@
/*
* Copyright 2002-2007 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.struts;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionServlet;
import org.apache.struts.config.ModuleConfig;
import org.springframework.beans.BeansException;
import org.springframework.web.context.WebApplicationContext;
/**
* Proxy for a Spring-managed Struts <code>Action</code> that is defined in
* {@link ContextLoaderPlugIn ContextLoaderPlugIn's}
* {@link WebApplicationContext}.
*
* <p>The proxy is defined in the Struts config file, specifying this
* class as the action class. This class will delegate to a Struts
* <code>Action</code> bean in the <code>ContextLoaderPlugIn</code> context.
*
* <pre class="code">&lt;action path="/login" type="org.springframework.web.struts.DelegatingActionProxy"/&gt;</pre>
*
* The name of the <code>Action</code> bean in the
* <code>WebApplicationContext</code> will be determined from the mapping
* path and module prefix. This can be customized by overriding the
* <code>determineActionBeanName</code> method.
*
* <p>Example:
* <ul>
* <li>mapping path "/login" -> bean name "/login"<br>
* <li>mapping path "/login", module prefix "/mymodule" ->
* bean name "/mymodule/login"
* </ul>
*
* <p>A corresponding bean definition in the <code>ContextLoaderPlugin</code>
* context would look as follows; notice that the <code>Action</code> is now
* able to leverage fully Spring's configuration facilities:
*
* <pre class="code">
* &lt;bean name="/login" class="myapp.MyAction"&gt;
* &lt;property name="..."&gt;...&lt;/property&gt;
* &lt;/bean&gt;</pre>
*
* Note that you can use a single <code>ContextLoaderPlugIn</code> for all
* Struts modules. That context can in turn be loaded from multiple XML files,
* for example split according to Struts modules. Alternatively, define one
* <code>ContextLoaderPlugIn</code> per Struts module, specifying appropriate
* "contextConfigLocation" parameters. In both cases, the Spring bean name
* has to include the module prefix.
*
* <p>If you want to avoid having to specify <code>DelegatingActionProxy</code>
* as the <code>Action</code> type in your struts-config file (for example to
* be able to generate your Struts config file with XDoclet) consider using the
* {@link DelegatingRequestProcessor DelegatingRequestProcessor}.
* The latter's disadvantage is that it might conflict with the need
* for a different <code>RequestProcessor</code> subclass.
*
* <p>The default implementation delegates to the {@link DelegatingActionUtils}
* class as much as possible, to reuse as much code as possible with
* <code>DelegatingRequestProcessor</code> and
* {@link DelegatingTilesRequestProcessor}.
*
* <p>Note: The idea of delegating to Spring-managed Struts Actions originated in
* Don Brown's <a href="http://struts.sourceforge.net/struts-spring">Spring Struts Plugin</a>.
* <code>ContextLoaderPlugIn</code> and <code>DelegatingActionProxy</code>
* constitute a clean-room implementation of the same idea, essentially
* superseding the original plugin. Many thanks to Don Brown and Matt Raible
* for the original work and for the agreement to reimplement the idea in
* Spring proper!
*
* @author Juergen Hoeller
* @since 1.0.1
* @see #determineActionBeanName
* @see DelegatingRequestProcessor
* @see DelegatingTilesRequestProcessor
* @see DelegatingActionUtils
* @see ContextLoaderPlugIn
* @deprecated as of Spring 3.0
*/
@Deprecated
public class DelegatingActionProxy extends Action {
/**
* Pass the execute call on to the Spring-managed delegate <code>Action</code>.
* @see #getDelegateAction
*/
@Override
public ActionForward execute(
ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response)
throws Exception {
Action delegateAction = getDelegateAction(mapping);
return delegateAction.execute(mapping, form, request, response);
}
/**
* Return the delegate <code>Action</code> for the given <code>mapping</code>.
* <p>The default implementation determines a bean name from the
* given <code>ActionMapping</code> and looks up the corresponding bean in
* the {@link WebApplicationContext}.
* @param mapping the Struts <code>ActionMapping</code>
* @return the delegate <code>Action</code>
* @throws BeansException if thrown by <code>WebApplicationContext</code> methods
* @see #determineActionBeanName
*/
protected Action getDelegateAction(ActionMapping mapping) throws BeansException {
WebApplicationContext wac = getWebApplicationContext(getServlet(), mapping.getModuleConfig());
String beanName = determineActionBeanName(mapping);
return (Action) wac.getBean(beanName, Action.class);
}
/**
* Fetch ContextLoaderPlugIn's {@link WebApplicationContext} from the
* <code>ServletContext</code>, falling back to the root
* <code>WebApplicationContext</code>.
* <p>This context is supposed to contain the Struts <code>Action</code>
* beans to delegate to.
* @param actionServlet the associated <code>ActionServlet</code>
* @param moduleConfig the associated <code>ModuleConfig</code>
* @return the <code>WebApplicationContext</code>
* @throws IllegalStateException if no <code>WebApplicationContext</code> could be found
* @see DelegatingActionUtils#findRequiredWebApplicationContext
* @see ContextLoaderPlugIn#SERVLET_CONTEXT_PREFIX
*/
protected WebApplicationContext getWebApplicationContext(
ActionServlet actionServlet, ModuleConfig moduleConfig) throws IllegalStateException {
return DelegatingActionUtils.findRequiredWebApplicationContext(actionServlet, moduleConfig);
}
/**
* Determine the name of the <code>Action</code> bean, to be looked up in
* the <code>WebApplicationContext</code>.
* <p>The default implementation takes the
* {@link org.apache.struts.action.ActionMapping#getPath mapping path} and
* prepends the
* {@link org.apache.struts.config.ModuleConfig#getPrefix module prefix},
* if any.
* @param mapping the Struts <code>ActionMapping</code>
* @return the name of the Action bean
* @see DelegatingActionUtils#determineActionBeanName
* @see org.apache.struts.action.ActionMapping#getPath
* @see org.apache.struts.config.ModuleConfig#getPrefix
*/
protected String determineActionBeanName(ActionMapping mapping) {
return DelegatingActionUtils.determineActionBeanName(mapping);
}
}

View File

@ -0,0 +1,212 @@
/*
* Copyright 2002-2006 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.struts;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionServlet;
import org.apache.struts.config.ModuleConfig;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
/**
* Common methods for letting Struts Actions work with a
* Spring WebApplicationContext.
*
* <p>As everything in Struts is based on concrete inheritance,
* we have to provide an Action subclass (DelegatingActionProxy) and
* two RequestProcessor subclasses (DelegatingRequestProcessor and
* DelegatingTilesRequestProcessor). The only way to share common
* functionality is a utility class like this one.
*
* @author Juergen Hoeller
* @since 1.0.2
* @see DelegatingActionProxy
* @see DelegatingRequestProcessor
* @see DelegatingTilesRequestProcessor
* @deprecated as of Spring 3.0
*/
@Deprecated
public abstract class DelegatingActionUtils {
/**
* The name of the autowire init-param specified on the Struts ActionServlet:
* "spring.autowire"
*/
public static final String PARAM_AUTOWIRE = "spring.autowire";
/**
* The name of the dependency check init-param specified on the Struts ActionServlet:
* "spring.dependencyCheck"
*/
public static final String PARAM_DEPENDENCY_CHECK = "spring.dependencyCheck";
/**
* Value of the autowire init-param that indicates autowiring by name:
* "byName"
*/
public static final String AUTOWIRE_BY_NAME = "byName";
/**
* Value of the autowire init-param that indicates autowiring by type:
* "byType"
*/
public static final String AUTOWIRE_BY_TYPE = "byType";
private static final Log logger = LogFactory.getLog(DelegatingActionUtils.class);
/**
* Fetch ContextLoaderPlugIn's WebApplicationContext from the ServletContext.
* <p>Checks for a module-specific context first, falling back to the
* context for the default module else.
* @param actionServlet the associated ActionServlet
* @param moduleConfig the associated ModuleConfig (can be <code>null</code>)
* @return the WebApplicationContext, or <code>null</code> if none
* @see ContextLoaderPlugIn#SERVLET_CONTEXT_PREFIX
*/
public static WebApplicationContext getWebApplicationContext(
ActionServlet actionServlet, ModuleConfig moduleConfig) {
WebApplicationContext wac = null;
String modulePrefix = null;
// Try module-specific attribute.
if (moduleConfig != null) {
modulePrefix = moduleConfig.getPrefix();
wac = (WebApplicationContext) actionServlet.getServletContext().getAttribute(
ContextLoaderPlugIn.SERVLET_CONTEXT_PREFIX + modulePrefix);
}
// If not found, try attribute for default module.
if (wac == null && !"".equals(modulePrefix)) {
wac = (WebApplicationContext) actionServlet.getServletContext().getAttribute(
ContextLoaderPlugIn.SERVLET_CONTEXT_PREFIX);
}
return wac;
}
/**
* Fetch ContextLoaderPlugIn's WebApplicationContext from the ServletContext.
* <p>Checks for a module-specific context first, falling back to the
* context for the default module else.
* @param actionServlet the associated ActionServlet
* @param moduleConfig the associated ModuleConfig (can be <code>null</code>)
* @return the WebApplicationContext
* @throws IllegalStateException if no WebApplicationContext could be found
* @see ContextLoaderPlugIn#SERVLET_CONTEXT_PREFIX
*/
public static WebApplicationContext getRequiredWebApplicationContext(
ActionServlet actionServlet, ModuleConfig moduleConfig) throws IllegalStateException {
WebApplicationContext wac = getWebApplicationContext(actionServlet, moduleConfig);
// If no Struts-specific context found, throw an exception.
if (wac == null) {
throw new IllegalStateException(
"Could not find ContextLoaderPlugIn's WebApplicationContext as ServletContext attribute [" +
ContextLoaderPlugIn.SERVLET_CONTEXT_PREFIX + "]: Did you register [" +
ContextLoaderPlugIn.class.getName() + "]?");
}
return wac;
}
/**
* Find most specific context available: check ContextLoaderPlugIn's
* WebApplicationContext first, fall back to root WebApplicationContext else.
* <p>When checking the ContextLoaderPlugIn context: checks for a module-specific
* context first, falling back to the context for the default module else.
* @param actionServlet the associated ActionServlet
* @param moduleConfig the associated ModuleConfig (can be <code>null</code>)
* @return the WebApplicationContext
* @throws IllegalStateException if no WebApplicationContext could be found
* @see #getWebApplicationContext
* @see org.springframework.web.context.support.WebApplicationContextUtils#getRequiredWebApplicationContext
*/
public static WebApplicationContext findRequiredWebApplicationContext(
ActionServlet actionServlet, ModuleConfig moduleConfig) throws IllegalStateException {
WebApplicationContext wac = getWebApplicationContext(actionServlet, moduleConfig);
// If no Struts-specific context found, fall back to root context.
if (wac == null) {
wac = WebApplicationContextUtils.getRequiredWebApplicationContext(actionServlet.getServletContext());
}
return wac;
}
/**
* Default implementation of Action bean determination, taking
* the mapping path and prepending the module prefix, if any.
* @param mapping the Struts ActionMapping
* @return the name of the Action bean
* @see org.apache.struts.action.ActionMapping#getPath
* @see org.apache.struts.config.ModuleConfig#getPrefix
*/
public static String determineActionBeanName(ActionMapping mapping) {
String prefix = mapping.getModuleConfig().getPrefix();
String path = mapping.getPath();
String beanName = prefix + path;
if (logger.isDebugEnabled()) {
logger.debug("DelegatingActionProxy with mapping path '" + path + "' and module prefix '" +
prefix + "' delegating to Spring bean with name [" + beanName + "]");
}
return beanName;
}
/**
* Determine the autowire mode from the "autowire" init-param of the
* Struts ActionServlet, falling back to "AUTOWIRE_BY_TYPE" as default.
* @param actionServlet the Struts ActionServlet
* @return the autowire mode to use
* @see #PARAM_AUTOWIRE
* @see #AUTOWIRE_BY_NAME
* @see #AUTOWIRE_BY_TYPE
* @see org.springframework.beans.factory.config.AutowireCapableBeanFactory#autowireBeanProperties
* @see org.springframework.beans.factory.config.AutowireCapableBeanFactory#AUTOWIRE_BY_TYPE
* @see org.springframework.beans.factory.config.AutowireCapableBeanFactory#AUTOWIRE_BY_NAME
*/
public static int getAutowireMode(ActionServlet actionServlet) {
String autowire = actionServlet.getInitParameter(PARAM_AUTOWIRE);
if (autowire != null) {
if (AUTOWIRE_BY_NAME.equals(autowire)) {
return AutowireCapableBeanFactory.AUTOWIRE_BY_NAME;
}
else if (!AUTOWIRE_BY_TYPE.equals(autowire)) {
throw new IllegalArgumentException("ActionServlet 'autowire' parameter must be 'byName' or 'byType'");
}
}
return AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE;
}
/**
* Determine the dependency check to use from the "dependencyCheck" init-param
* of the Struts ActionServlet, falling back to no dependency check as default.
* @param actionServlet the Struts ActionServlet
* @return whether to enforce a dependency check or not
* @see #PARAM_DEPENDENCY_CHECK
* @see org.springframework.beans.factory.config.AutowireCapableBeanFactory#autowireBeanProperties
*/
public static boolean getDependencyCheck(ActionServlet actionServlet) {
String dependencyCheck = actionServlet.getInitParameter(PARAM_DEPENDENCY_CHECK);
return Boolean.valueOf(dependencyCheck).booleanValue();
}
}

View File

@ -0,0 +1,201 @@
/*
* Copyright 2002-2007 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.struts;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionServlet;
import org.apache.struts.action.RequestProcessor;
import org.apache.struts.config.ModuleConfig;
import org.springframework.beans.BeansException;
import org.springframework.web.context.WebApplicationContext;
/**
* Subclass of Struts's default {@link RequestProcessor} that looks up
* Spring-managed Struts {@link Action Actions} defined in
* {@link ContextLoaderPlugIn ContextLoaderPlugIn's} {@link WebApplicationContext}
* (or, as a fallback, in the root <code>WebApplicationContext</code>).
*
* <p>In the Struts config file, you can either specify the original
* <code>Action</code> class (as when generated by XDoclet), or no
* <code>Action</code> class at all. In any case, Struts will delegate to an
* <code>Action</code> bean in the <code>ContextLoaderPlugIn</code> context.
*
* <pre class="code">&lt;action path="/login" type="myapp.MyAction"/&gt;</pre>
*
* or
*
* <pre class="code">&lt;action path="/login"/&gt;</pre>
*
* The name of the <code>Action</code> bean in the
* <code>WebApplicationContext</code> will be determined from the mapping path
* and module prefix. This can be customized by overriding the
* {@link #determineActionBeanName} method.
*
* <p>Example:
* <ul>
* <li>mapping path "/login" -> bean name "/login"<br>
* <li>mapping path "/login", module prefix "/mymodule" ->
* bean name "/mymodule/login"
* </ul>
*
* <p>A corresponding bean definition in the <code>ContextLoaderPlugin</code>
* context would look as follows; notice that the <code>Action</code> is now
* able to leverage fully Spring's configuration facilities:
*
* <pre class="code">
* &lt;bean name="/login" class="myapp.MyAction"&gt;
* &lt;property name="..."&gt;...&lt;/property&gt;
* &lt;/bean&gt;</pre>
*
* Note that you can use a single <code>ContextLoaderPlugIn</code> for all
* Struts modules. That context can in turn be loaded from multiple XML files,
* for example split according to Struts modules. Alternatively, define one
* <code>ContextLoaderPlugIn</code> per Struts module, specifying appropriate
* "contextConfigLocation" parameters. In both cases, the Spring bean name has
* to include the module prefix.
*
* <p>If you also need the Tiles setup functionality of the original
* <code>TilesRequestProcessor</code>, use
* <code>DelegatingTilesRequestProcessor</code>. As there is just a
* single central class to customize in Struts, we have to provide another
* subclass here, covering both the Tiles and the Spring delegation aspect.
*
* <p>If this <code>RequestProcessor</code> conflicts with the need for a
* different <code>RequestProcessor</code> subclass (other than
* <code>TilesRequestProcessor</code>), consider using
* {@link DelegatingActionProxy} as the Struts <code>Action</code> type in
* your struts-config file.
*
* <p>The default implementation delegates to the
* <code>DelegatingActionUtils</code> class as much as possible, to reuse as
* much code as possible despite the need to provide two
* <code>RequestProcessor</code> subclasses. If you need to subclass yet
* another <code>RequestProcessor</code>, take this class as a template,
* delegating to <code>DelegatingActionUtils</code> just like it.
*
* @author Juergen Hoeller
* @since 1.0.2
* @see #determineActionBeanName
* @see DelegatingTilesRequestProcessor
* @see DelegatingActionProxy
* @see DelegatingActionUtils
* @see ContextLoaderPlugIn
* @deprecated as of Spring 3.0
*/
@Deprecated
public class DelegatingRequestProcessor extends RequestProcessor {
private WebApplicationContext webApplicationContext;
@Override
public void init(ActionServlet actionServlet, ModuleConfig moduleConfig) throws ServletException {
super.init(actionServlet, moduleConfig);
if (actionServlet != null) {
this.webApplicationContext = initWebApplicationContext(actionServlet, moduleConfig);
}
}
/**
* Fetch ContextLoaderPlugIn's {@link WebApplicationContext} from the
* <code>ServletContext</code>, falling back to the root
* <code>WebApplicationContext</code>.
* <p>This context is supposed to contain the Struts <code>Action</code>
* beans to delegate to.
* @param actionServlet the associated <code>ActionServlet</code>
* @param moduleConfig the associated <code>ModuleConfig</code>
* @return the <code>WebApplicationContext</code>
* @throws IllegalStateException if no <code>WebApplicationContext</code> could be found
* @see DelegatingActionUtils#findRequiredWebApplicationContext
* @see ContextLoaderPlugIn#SERVLET_CONTEXT_PREFIX
*/
protected WebApplicationContext initWebApplicationContext(
ActionServlet actionServlet, ModuleConfig moduleConfig) throws IllegalStateException {
return DelegatingActionUtils.findRequiredWebApplicationContext(actionServlet, moduleConfig);
}
/**
* Return the <code>WebApplicationContext</code> that this processor
* delegates to.
*/
protected final WebApplicationContext getWebApplicationContext() {
return this.webApplicationContext;
}
/**
* Override the base class method to return the delegate action.
* @see #getDelegateAction
*/
@Override
protected Action processActionCreate(
HttpServletRequest request, HttpServletResponse response, ActionMapping mapping)
throws IOException {
Action action = getDelegateAction(mapping);
if (action != null) {
return action;
}
return super.processActionCreate(request, response, mapping);
}
/**
* Return the delegate <code>Action</code> for the given mapping.
* <p>The default implementation determines a bean name from the
* given <code>ActionMapping</code> and looks up the corresponding
* bean in the <code>WebApplicationContext</code>.
* @param mapping the Struts <code>ActionMapping</code>
* @return the delegate <code>Action</code>, or <code>null</code> if none found
* @throws BeansException if thrown by <code>WebApplicationContext</code> methods
* @see #determineActionBeanName
*/
protected Action getDelegateAction(ActionMapping mapping) throws BeansException {
String beanName = determineActionBeanName(mapping);
if (!getWebApplicationContext().containsBean(beanName)) {
return null;
}
return (Action) getWebApplicationContext().getBean(beanName, Action.class);
}
/**
* Determine the name of the <code>Action</code> bean, to be looked up in
* the <code>WebApplicationContext</code>.
* <p>The default implementation takes the
* {@link org.apache.struts.action.ActionMapping#getPath mapping path} and
* prepends the
* {@link org.apache.struts.config.ModuleConfig#getPrefix module prefix},
* if any.
* @param mapping the Struts <code>ActionMapping</code>
* @return the name of the Action bean
* @see DelegatingActionUtils#determineActionBeanName
* @see org.apache.struts.action.ActionMapping#getPath
* @see org.apache.struts.config.ModuleConfig#getPrefix
*/
protected String determineActionBeanName(ActionMapping mapping) {
return DelegatingActionUtils.determineActionBeanName(mapping);
}
}

View File

@ -0,0 +1,147 @@
/*
* Copyright 2002-2006 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.struts;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionServlet;
import org.apache.struts.config.ModuleConfig;
import org.apache.struts.tiles.TilesRequestProcessor;
import org.springframework.beans.BeansException;
import org.springframework.web.context.WebApplicationContext;
/**
* Subclass of Struts's TilesRequestProcessor that autowires
* Struts Actions defined in ContextLoaderPlugIn's WebApplicationContext
* (or, as a fallback, in the root WebApplicationContext).
*
* <p>Behaves like
* {@link DelegatingRequestProcessor DelegatingRequestProcessor},
* but also provides the Tiles functionality of the original TilesRequestProcessor.
* As there's just a single central class to customize in Struts, we have to provide
* another subclass here, covering both the Tiles and the Spring delegation aspect.
*
* <p>The default implementation delegates to the DelegatingActionUtils
* class as fas as possible, to reuse as much code as possible despite
* the need to provide two RequestProcessor subclasses. If you need to
* subclass yet another RequestProcessor, take this class as a template,
* delegating to DelegatingActionUtils just like it.
*
* @author Juergen Hoeller
* @since 1.0.2
* @see DelegatingRequestProcessor
* @see DelegatingActionProxy
* @see DelegatingActionUtils
* @see ContextLoaderPlugIn
* @deprecated as of Spring 3.0
*/
@Deprecated
public class DelegatingTilesRequestProcessor extends TilesRequestProcessor {
private WebApplicationContext webApplicationContext;
@Override
public void init(ActionServlet actionServlet, ModuleConfig moduleConfig) throws ServletException {
super.init(actionServlet, moduleConfig);
if (actionServlet != null) {
this.webApplicationContext = initWebApplicationContext(actionServlet, moduleConfig);
}
}
/**
* Fetch ContextLoaderPlugIn's WebApplicationContext from the ServletContext,
* falling back to the root WebApplicationContext. This context is supposed
* to contain the Struts Action beans to delegate to.
* @param actionServlet the associated ActionServlet
* @param moduleConfig the associated ModuleConfig
* @return the WebApplicationContext
* @throws IllegalStateException if no WebApplicationContext could be found
* @see DelegatingActionUtils#findRequiredWebApplicationContext
* @see ContextLoaderPlugIn#SERVLET_CONTEXT_PREFIX
*/
protected WebApplicationContext initWebApplicationContext(
ActionServlet actionServlet, ModuleConfig moduleConfig) throws IllegalStateException {
return DelegatingActionUtils.findRequiredWebApplicationContext(actionServlet, moduleConfig);
}
/**
* Return the WebApplicationContext that this processor delegates to.
*/
protected final WebApplicationContext getWebApplicationContext() {
return webApplicationContext;
}
/**
* Override the base class method to return the delegate action.
* @see #getDelegateAction
*/
@Override
protected Action processActionCreate(
HttpServletRequest request, HttpServletResponse response, ActionMapping mapping)
throws IOException {
Action action = getDelegateAction(mapping);
if (action != null) {
return action;
}
return super.processActionCreate(request, response, mapping);
}
/**
* Return the delegate Action for the given mapping.
* <p>The default implementation determines a bean name from the
* given ActionMapping and looks up the corresponding bean in the
* WebApplicationContext.
* @param mapping the Struts ActionMapping
* @return the delegate Action, or <code>null</code> if none found
* @throws BeansException if thrown by WebApplicationContext methods
* @see #determineActionBeanName
*/
protected Action getDelegateAction(ActionMapping mapping) throws BeansException {
String beanName = determineActionBeanName(mapping);
if (!getWebApplicationContext().containsBean(beanName)) {
return null;
}
return (Action) getWebApplicationContext().getBean(beanName, Action.class);
}
/**
* Determine the name of the Action bean, to be looked up in
* the WebApplicationContext.
* <p>The default implementation takes the mapping path and
* prepends the module prefix, if any.
* @param mapping the Struts ActionMapping
* @return the name of the Action bean
* @see DelegatingActionUtils#determineActionBeanName
* @see ActionMapping#getPath
* @see ModuleConfig#getPrefix
*/
protected String determineActionBeanName(ActionMapping mapping) {
return DelegatingActionUtils.determineActionBeanName(mapping);
}
}

View File

@ -0,0 +1,151 @@
/*
* Copyright 2002-2005 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.struts;
import java.io.File;
import javax.servlet.ServletContext;
import org.apache.struts.action.ActionServlet;
import org.apache.struts.actions.DispatchAction;
import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.util.WebUtils;
/**
* Convenience class for Spring-aware Struts 1.1+ DispatchActions.
*
* <p>Provides a reference to the current Spring application context, e.g.
* for bean lookup or resource loading. Auto-detects a ContextLoaderPlugIn
* context, falling back to the root WebApplicationContext. For typical
* usage, i.e. accessing middle tier beans, use a root WebApplicationContext.
*
* <p>For classic Struts Actions or Lookup/MappingDispatchActions, use the
* analogous {@link ActionSupport ActionSupport} or
* {@link LookupDispatchActionSupport LookupDispatchActionSupport} /
* {@link MappingDispatchActionSupport MappingDispatchActionSupport} class,
* respectively.
*
* <p>As an alternative approach, you can wire your Struts Actions themselves
* as Spring beans, passing references to them via IoC rather than looking
* up references in a programmatic fashion. Check out
* {@link DelegatingActionProxy DelegatingActionProxy} and
* {@link DelegatingRequestProcessor DelegatingRequestProcessor}.
*
* @author Juergen Hoeller
* @since 1.0.1
* @see ContextLoaderPlugIn#SERVLET_CONTEXT_PREFIX
* @see org.springframework.web.context.WebApplicationContext#ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE
* @see org.springframework.web.context.ContextLoaderListener
* @see org.springframework.web.context.ContextLoaderServlet
* @see ActionSupport
* @see LookupDispatchActionSupport
* @see MappingDispatchActionSupport
* @see DelegatingActionProxy
* @see DelegatingRequestProcessor
* @deprecated as of Spring 3.0
*/
@Deprecated
public abstract class DispatchActionSupport extends DispatchAction {
private WebApplicationContext webApplicationContext;
private MessageSourceAccessor messageSourceAccessor;
/**
* Initialize the WebApplicationContext for this Action.
* Invokes onInit after successful initialization of the context.
* @see #initWebApplicationContext
* @see #onInit
*/
@Override
public void setServlet(ActionServlet actionServlet) {
super.setServlet(actionServlet);
if (actionServlet != null) {
this.webApplicationContext = initWebApplicationContext(actionServlet);
this.messageSourceAccessor = new MessageSourceAccessor(this.webApplicationContext);
onInit();
}
else {
onDestroy();
}
}
/**
* Fetch ContextLoaderPlugIn's WebApplicationContext from the ServletContext,
* falling back to the root WebApplicationContext (the usual case).
* @param actionServlet the associated ActionServlet
* @return the WebApplicationContext
* @throws IllegalStateException if no WebApplicationContext could be found
* @see DelegatingActionUtils#findRequiredWebApplicationContext
*/
protected WebApplicationContext initWebApplicationContext(ActionServlet actionServlet)
throws IllegalStateException {
return DelegatingActionUtils.findRequiredWebApplicationContext(actionServlet, null);
}
/**
* Return the current Spring WebApplicationContext.
*/
protected final WebApplicationContext getWebApplicationContext() {
return this.webApplicationContext;
}
/**
* Return a MessageSourceAccessor for the application context
* used by this object, for easy message access.
*/
protected final MessageSourceAccessor getMessageSourceAccessor() {
return this.messageSourceAccessor;
}
/**
* Return the current ServletContext.
*/
protected final ServletContext getServletContext() {
return this.webApplicationContext.getServletContext();
}
/**
* Return the temporary directory for the current web application,
* as provided by the servlet container.
* @return the File representing the temporary directory
*/
protected final File getTempDir() {
return WebUtils.getTempDir(getServletContext());
}
/**
* Callback for custom initialization after the context has been set up.
* @see #setServlet
*/
protected void onInit() {
}
/**
* Callback for custom destruction when the ActionServlet shuts down.
* @see #setServlet
*/
protected void onDestroy() {
}
}

View File

@ -0,0 +1,150 @@
/*
* Copyright 2002-2005 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.struts;
import java.io.File;
import javax.servlet.ServletContext;
import org.apache.struts.action.ActionServlet;
import org.apache.struts.actions.LookupDispatchAction;
import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.util.WebUtils;
/**
* Convenience class for Spring-aware Struts 1.1+ LookupDispatchActions.
*
* <p>Provides a reference to the current Spring application context, e.g.
* for bean lookup or resource loading. Auto-detects a ContextLoaderPlugIn
* context, falling back to the root WebApplicationContext. For typical
* usage, i.e. accessing middle tier beans, use a root WebApplicationContext.
*
* <p>For classic Struts Actions, DispatchActions or MappingDispatchActions,
* use the analogous {@link ActionSupport ActionSupport} or
* {@link DispatchActionSupport DispatchActionSupport} /
* {@link MappingDispatchActionSupport MappingDispatchActionSupport} class.
*
* <p>As an alternative approach, you can wire your Struts Actions themselves
* as Spring beans, passing references to them via IoC rather than looking
* up references in a programmatic fashion. Check out
* {@link DelegatingActionProxy DelegatingActionProxy} and
* {@link DelegatingRequestProcessor DelegatingRequestProcessor}.
*
* @author Juergen Hoeller
* @since 1.1
* @see ContextLoaderPlugIn#SERVLET_CONTEXT_PREFIX
* @see WebApplicationContext#ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE
* @see org.springframework.web.context.ContextLoaderListener
* @see org.springframework.web.context.ContextLoaderServlet
* @see ActionSupport
* @see DispatchActionSupport
* @see MappingDispatchActionSupport
* @see DelegatingActionProxy
* @see DelegatingRequestProcessor
* @deprecated as of Spring 3.0
*/
@Deprecated
public abstract class LookupDispatchActionSupport extends LookupDispatchAction {
private WebApplicationContext webApplicationContext;
private MessageSourceAccessor messageSourceAccessor;
/**
* Initialize the WebApplicationContext for this Action.
* Invokes onInit after successful initialization of the context.
* @see #initWebApplicationContext
* @see #onInit
*/
@Override
public void setServlet(ActionServlet actionServlet) {
super.setServlet(actionServlet);
if (actionServlet != null) {
this.webApplicationContext = initWebApplicationContext(actionServlet);
this.messageSourceAccessor = new MessageSourceAccessor(this.webApplicationContext);
onInit();
}
else {
onDestroy();
}
}
/**
* Fetch ContextLoaderPlugIn's WebApplicationContext from the ServletContext,
* falling back to the root WebApplicationContext (the usual case).
* @param actionServlet the associated ActionServlet
* @return the WebApplicationContext
* @throws IllegalStateException if no WebApplicationContext could be found
* @see DelegatingActionUtils#findRequiredWebApplicationContext
*/
protected WebApplicationContext initWebApplicationContext(ActionServlet actionServlet)
throws IllegalStateException {
return DelegatingActionUtils.findRequiredWebApplicationContext(actionServlet, null);
}
/**
* Return the current Spring WebApplicationContext.
*/
protected final WebApplicationContext getWebApplicationContext() {
return this.webApplicationContext;
}
/**
* Return a MessageSourceAccessor for the application context
* used by this object, for easy message access.
*/
protected final MessageSourceAccessor getMessageSourceAccessor() {
return this.messageSourceAccessor;
}
/**
* Return the current ServletContext.
*/
protected final ServletContext getServletContext() {
return this.webApplicationContext.getServletContext();
}
/**
* Return the temporary directory for the current web application,
* as provided by the servlet container.
* @return the File representing the temporary directory
*/
protected final File getTempDir() {
return WebUtils.getTempDir(getServletContext());
}
/**
* Callback for custom initialization after the context has been set up.
* @see #setServlet
*/
protected void onInit() {
}
/**
* Callback for custom destruction when the ActionServlet shuts down.
* @see #setServlet
*/
protected void onDestroy() {
}
}

View File

@ -0,0 +1,150 @@
/*
* Copyright 2002-2005 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.struts;
import java.io.File;
import javax.servlet.ServletContext;
import org.apache.struts.action.ActionServlet;
import org.apache.struts.actions.MappingDispatchAction;
import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.util.WebUtils;
/**
* Convenience class for Spring-aware Struts 1.2 MappingDispatchActions.
*
* <p>Provides a reference to the current Spring application context, e.g.
* for bean lookup or resource loading. Auto-detects a ContextLoaderPlugIn
* context, falling back to the root WebApplicationContext. For typical
* usage, i.e. accessing middle tier beans, use a root WebApplicationContext.
*
* <p>For classic Struts Actions, DispatchActions or LookupDispatchActions,
* use the analogous {@link ActionSupport ActionSupport} or
* {@link DispatchActionSupport DispatchActionSupport} /
* {@link LookupDispatchActionSupport LookupDispatchActionSupport} class.
*
* <p>As an alternative approach, you can wire your Struts Actions themselves
* as Spring beans, passing references to them via IoC rather than looking
* up references in a programmatic fashion. Check out
* {@link DelegatingActionProxy DelegatingActionProxy} and
* {@link DelegatingRequestProcessor DelegatingRequestProcessor}.
*
* @author Juergen Hoeller
* @since 1.1.3
* @see ContextLoaderPlugIn#SERVLET_CONTEXT_PREFIX
* @see WebApplicationContext#ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE
* @see org.springframework.web.context.ContextLoaderListener
* @see org.springframework.web.context.ContextLoaderServlet
* @see ActionSupport
* @see DispatchActionSupport
* @see LookupDispatchActionSupport
* @see DelegatingActionProxy
* @see DelegatingRequestProcessor
* @deprecated as of Spring 3.0
*/
@Deprecated
public abstract class MappingDispatchActionSupport extends MappingDispatchAction {
private WebApplicationContext webApplicationContext;
private MessageSourceAccessor messageSourceAccessor;
/**
* Initialize the WebApplicationContext for this Action.
* Invokes onInit after successful initialization of the context.
* @see #initWebApplicationContext
* @see #onInit
*/
@Override
public void setServlet(ActionServlet actionServlet) {
super.setServlet(actionServlet);
if (actionServlet != null) {
this.webApplicationContext = initWebApplicationContext(actionServlet);
this.messageSourceAccessor = new MessageSourceAccessor(this.webApplicationContext);
onInit();
}
else {
onDestroy();
}
}
/**
* Fetch ContextLoaderPlugIn's WebApplicationContext from the ServletContext,
* falling back to the root WebApplicationContext (the usual case).
* @param actionServlet the associated ActionServlet
* @return the WebApplicationContext
* @throws IllegalStateException if no WebApplicationContext could be found
* @see DelegatingActionUtils#findRequiredWebApplicationContext
*/
protected WebApplicationContext initWebApplicationContext(ActionServlet actionServlet)
throws IllegalStateException {
return DelegatingActionUtils.findRequiredWebApplicationContext(actionServlet, null);
}
/**
* Return the current Spring WebApplicationContext.
*/
protected final WebApplicationContext getWebApplicationContext() {
return this.webApplicationContext;
}
/**
* Return a MessageSourceAccessor for the application context
* used by this object, for easy message access.
*/
protected final MessageSourceAccessor getMessageSourceAccessor() {
return this.messageSourceAccessor;
}
/**
* Return the current ServletContext.
*/
protected final ServletContext getServletContext() {
return this.webApplicationContext.getServletContext();
}
/**
* Return the temporary directory for the current web application,
* as provided by the servlet container.
* @return the File representing the temporary directory
*/
protected final File getTempDir() {
return WebUtils.getTempDir(getServletContext());
}
/**
* Callback for custom initialization after the context has been set up.
* @see #setServlet
*/
protected void onInit() {
}
/**
* Callback for custom destruction when the ActionServlet shuts down.
* @see #setServlet
*/
protected void onDestroy() {
}
}

View File

@ -0,0 +1,288 @@
/*
* Copyright 2002-2006 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.struts;
import java.lang.reflect.InvocationTargetException;
import java.util.Iterator;
import java.util.Locale;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.beanutils.BeanUtilsBean;
import org.apache.commons.beanutils.ConvertUtilsBean;
import org.apache.commons.beanutils.PropertyUtilsBean;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts.Globals;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionMessages;
import org.apache.struts.util.MessageResources;
import org.springframework.context.MessageSourceResolvable;
import org.springframework.validation.Errors;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
/**
* A thin Struts ActionForm adapter that delegates to Spring's more complete
* and advanced data binder and Errors object underneath the covers to bind
* to POJOs and manage rejected values.
*
* <p>Exposes Spring-managed errors to the standard Struts view tags, through
* exposing a corresponding Struts ActionMessages object as request attribute.
* Also exposes current field values in a Struts-compliant fashion, including
* rejected values (which Spring's binding keeps even for non-String fields).
*
* <p>Consequently, Struts views can be written in a completely traditional
* fashion (with standard <code>html:form</code>, <code>html:errors</code>, etc),
* seamlessly accessing a Spring-bound POJO form object underneath.
*
* <p>Note this ActionForm is designed explicitly for use in <i>request scope</i>.
* It expects to receive an <code>expose</code> call from the Action, passing
* in the Errors object to expose plus the current HttpServletRequest.
*
* <p>Example definition in <code>struts-config.xml</code>:
*
* <pre>
* &lt;form-beans&gt;
* &lt;form-bean name="actionForm" type="org.springframework.web.struts.SpringBindingActionForm"/&gt;
* &lt;/form-beans&gt;</pre>
*
* Example code in a custom Struts <code>Action</code>:
*
* <pre>
* public ActionForward execute(ActionMapping actionMapping, ActionForm actionForm, HttpServletRequest request, HttpServletResponse response) throws Exception {
* SpringBindingActionForm form = (SpringBindingActionForm) actionForm;
* MyPojoBean bean = ...;
* ServletRequestDataBinder binder = new ServletRequestDataBinder(bean, "myPojo");
* binder.bind(request);
* form.expose(binder.getBindingResult(), request);
* return actionMapping.findForward("success");
* }</pre>
*
* This class is compatible with both Struts 1.2.x and Struts 1.1.
* On Struts 1.2, default messages registered with Spring binding errors
* are exposed when none of the error codes could be resolved.
* On Struts 1.1, this is not possible due to a limitation in the Struts
* message facility; hence, we expose the plain default error code there.
*
* @author Keith Donald
* @author Juergen Hoeller
* @since 1.2.2
* @see #expose(org.springframework.validation.Errors, javax.servlet.http.HttpServletRequest)
* @deprecated as of Spring 3.0
*/
@Deprecated
public class SpringBindingActionForm extends ActionForm {
private static final Log logger = LogFactory.getLog(SpringBindingActionForm.class);
private static boolean defaultActionMessageAvailable = true;
static {
// Register special PropertyUtilsBean subclass that knows how to
// extract field values from a SpringBindingActionForm.
// As a consequence of the static nature of Commons BeanUtils,
// we have to resort to this initialization hack here.
ConvertUtilsBean convUtils = new ConvertUtilsBean();
PropertyUtilsBean propUtils = new SpringBindingAwarePropertyUtilsBean();
BeanUtilsBean beanUtils = new BeanUtilsBean(convUtils, propUtils);
BeanUtilsBean.setInstance(beanUtils);
// Determine whether the Struts 1.2 support for default messages
// is available on ActionMessage: ActionMessage(String, boolean)
// with "false" to be passed into the boolean flag.
try {
ActionMessage.class.getConstructor(new Class[] {String.class, boolean.class});
}
catch (NoSuchMethodException ex) {
defaultActionMessageAvailable = false;
}
}
private Errors errors;
private Locale locale;
private MessageResources messageResources;
/**
* Set the Errors object that this SpringBindingActionForm is supposed
* to wrap. The contained field values and errors will be exposed
* to the view, accessible through Struts standard tags.
* @param errors the Spring Errors object to wrap, usually taken from
* a DataBinder that has been used for populating a POJO form object
* @param request the HttpServletRequest to retrieve the attributes from
* @see org.springframework.validation.DataBinder#getBindingResult()
*/
public void expose(Errors errors, HttpServletRequest request) {
this.errors = errors;
// Obtain the locale from Struts well-known location.
this.locale = (Locale) request.getSession().getAttribute(Globals.LOCALE_KEY);
// Obtain the MessageResources from Struts' well-known location.
this.messageResources = (MessageResources) request.getAttribute(Globals.MESSAGES_KEY);
if (errors != null && errors.hasErrors()) {
// Add global ActionError instances from the Spring Errors object.
ActionMessages actionMessages = (ActionMessages) request.getAttribute(Globals.ERROR_KEY);
if (actionMessages == null) {
request.setAttribute(Globals.ERROR_KEY, getActionMessages());
}
else {
actionMessages.add(getActionMessages());
}
}
}
/**
* Return an ActionMessages representation of this SpringBindingActionForm,
* exposing all errors contained in the underlying Spring Errors object.
* @see org.springframework.validation.Errors#getAllErrors()
*/
private ActionMessages getActionMessages() {
ActionMessages actionMessages = new ActionMessages();
Iterator it = this.errors.getAllErrors().iterator();
while (it.hasNext()) {
ObjectError objectError = (ObjectError) it.next();
String effectiveMessageKey = findEffectiveMessageKey(objectError);
if (effectiveMessageKey == null && !defaultActionMessageAvailable) {
// Need to specify default code despite it not being resolvable:
// Struts 1.1 ActionMessage doesn't support default messages.
effectiveMessageKey = objectError.getCode();
}
ActionMessage message = (effectiveMessageKey != null) ?
new ActionMessage(effectiveMessageKey, resolveArguments(objectError.getArguments())) :
new ActionMessage(objectError.getDefaultMessage(), false);
if (objectError instanceof FieldError) {
FieldError fieldError = (FieldError) objectError;
actionMessages.add(fieldError.getField(), message);
}
else {
actionMessages.add(ActionMessages.GLOBAL_MESSAGE, message);
}
}
if (logger.isDebugEnabled()) {
logger.debug("Final ActionMessages used for binding: " + actionMessages);
}
return actionMessages;
}
private Object[] resolveArguments(Object[] arguments) {
if (arguments == null || arguments.length == 0) {
return arguments;
}
for (int i = 0; i < arguments.length; i++) {
Object arg = arguments[i];
if (arg instanceof MessageSourceResolvable) {
MessageSourceResolvable resolvable = (MessageSourceResolvable)arg;
String[] codes = resolvable.getCodes();
boolean resolved = false;
if (this.messageResources != null) {
for (int j = 0; j < codes.length; j++) {
String code = codes[j];
if (this.messageResources.isPresent(this.locale, code)) {
arguments[i] = this.messageResources.getMessage(
this.locale, code, resolveArguments(resolvable.getArguments()));
resolved = true;
break;
}
}
}
if (!resolved) {
arguments[i] = resolvable.getDefaultMessage();
}
}
}
return arguments;
}
/**
* Find the most specific message key for the given error.
* @param error the ObjectError to find a message key for
* @return the most specific message key found
*/
private String findEffectiveMessageKey(ObjectError error) {
if (this.messageResources != null) {
String[] possibleMatches = error.getCodes();
for (int i = 0; i < possibleMatches.length; i++) {
if (logger.isDebugEnabled()) {
logger.debug("Looking for error code '" + possibleMatches[i] + "'");
}
if (this.messageResources.isPresent(this.locale, possibleMatches[i])) {
if (logger.isDebugEnabled()) {
logger.debug("Found error code '" + possibleMatches[i] + "' in resource bundle");
}
return possibleMatches[i];
}
}
}
if (logger.isDebugEnabled()) {
logger.debug("Could not find a suitable message error code, returning default message");
}
return null;
}
/**
* Get the formatted value for the property at the provided path.
* The formatted value is a string value for display, converted
* via a registered property editor.
* @param propertyPath the property path
* @return the formatted property value
* @throws NoSuchMethodException if called during Struts binding
* (without Spring Errors object being exposed), to indicate no
* available property to Struts
*/
private Object getFieldValue(String propertyPath) throws NoSuchMethodException {
if (this.errors == null) {
throw new NoSuchMethodException(
"No bean properties exposed to Struts binding - performing Spring binding later on");
}
return this.errors.getFieldValue(propertyPath);
}
/**
* Special subclass of PropertyUtilsBean that it is aware of SpringBindingActionForm
* and uses it for retrieving field values. The field values will be taken from
* the underlying POJO form object that the Spring Errors object was created for.
*/
private static class SpringBindingAwarePropertyUtilsBean extends PropertyUtilsBean {
@Override
public Object getNestedProperty(Object bean, String propertyPath)
throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
// Extract Spring-managed field value in case of SpringBindingActionForm.
if (bean instanceof SpringBindingActionForm) {
SpringBindingActionForm form = (SpringBindingActionForm) bean;
return form.getFieldValue(propertyPath);
}
// Else fall back to default PropertyUtils behavior.
return super.getNestedProperty(bean, propertyPath);
}
}
}

View File

@ -0,0 +1,28 @@
/**
* Support classes for integrating a Struts web tier with a Spring middle
* tier which is typically hosted in a Spring root WebApplicationContext.
*
* <p>Supports easy access to the Spring root WebApplicationContext
* from Struts Actions via the ActionSupport and DispatchActionSupport
* classes. Actions have full access to Spring's WebApplicationContext
* facilities in this case, and explicitly look up Spring-managed beans.
*
* <p>Also supports wiring Struts Actions as Spring-managed beans in
* a ContextLoaderPlugIn context, passing middle tier references to them
* via bean references, using the Action path as bean name. There are two
* ways to make Struts delegate Action lookup to the ContextLoaderPlugIn:
*
* <ul>
* <li>Use DelegationActionProxy as Action "type" in struts-config.
* There's no further setup necessary; you can choose any RequestProcessor.
* Each such proxy will automatically delegate to the corresponding
* Spring-managed Action bean in the ContextLoaderPlugIn context.
*
* <li>Configure DelegatingRequestProcessor as "processorClass" in
* struts-config, using the original Action "type" (possibly generated
* by XDoclet) or no "type" at all. To also use Tiles, configure
* DelegatingTilesRequestProcessor instead.
* </ul>
*/
@Deprecated
package org.springframework.web.struts;

View File

@ -0,0 +1,36 @@
/*
* Copyright 2002-2005 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.servlet.view.tiles;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.tiles.ComponentContext;
/**
* @author Juergen Hoeller
* @since 22.08.2003
*/
public class TestComponentController extends ComponentControllerSupport {
@Override
protected void doPerform(ComponentContext componentContext, HttpServletRequest request, HttpServletResponse response) {
request.setAttribute("testAttr", "testVal");
TilesView.setPath(request, "/WEB-INF/jsp/layout.jsp");
}
}

View File

@ -0,0 +1,181 @@
/*
* Copyright 2002-2008 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.servlet.view.tiles;
import java.util.HashMap;
import java.util.Locale;
import javax.servlet.jsp.jstl.core.Config;
import javax.servlet.jsp.jstl.fmt.LocalizationContext;
import org.apache.struts.taglib.tiles.ComponentConstants;
import org.apache.struts.tiles.ComponentContext;
import org.apache.struts.tiles.PathAttribute;
import static org.junit.Assert.*;
import org.junit.Test;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.mock.web.MockServletContext;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.StaticWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver;
import org.springframework.web.servlet.i18n.FixedLocaleResolver;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
/**
* @author Alef Arendsen
* @author Juergen Hoeller
*/
public class TilesViewTests {
protected StaticWebApplicationContext prepareWebApplicationContext() throws Exception {
StaticWebApplicationContext wac = new StaticWebApplicationContext();
MockServletContext sc = new MockServletContext("/org/springframework/web/servlet/view/tiles/");
wac.setServletContext(sc);
wac.refresh();
TilesConfigurer tc = new TilesConfigurer();
tc.setDefinitions(new String[] {"tiles-test.xml"});
tc.setValidateDefinitions(true);
tc.setApplicationContext(wac);
tc.afterPropertiesSet();
return wac;
}
@Test
public void tilesView() throws Exception {
WebApplicationContext wac = prepareWebApplicationContext();
InternalResourceViewResolver irvr = new InternalResourceViewResolver();
irvr.setApplicationContext(wac);
irvr.setViewClass(TilesView.class);
View view = irvr.resolveViewName("testTile", new Locale("nl", ""));
MockHttpServletRequest request = new MockHttpServletRequest(wac.getServletContext());
MockHttpServletResponse response = new MockHttpServletResponse();
request.setAttribute(DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE, wac);
request.setAttribute(DispatcherServlet.LOCALE_RESOLVER_ATTRIBUTE, new AcceptHeaderLocaleResolver());
view.render(new HashMap<String, Object>(), request, response);
assertEquals("/WEB-INF/jsp/layout.jsp", response.getForwardedUrl());
ComponentContext cc = (ComponentContext) request.getAttribute(ComponentConstants.COMPONENT_CONTEXT);
assertNotNull(cc);
PathAttribute attr = (PathAttribute) cc.getAttribute("content");
assertEquals("/WEB-INF/jsp/content.jsp", attr.getValue());
view.render(new HashMap<String, Object>(), request, response);
assertEquals("/WEB-INF/jsp/layout.jsp", response.getForwardedUrl());
cc = (ComponentContext) request.getAttribute(ComponentConstants.COMPONENT_CONTEXT);
assertNotNull(cc);
attr = (PathAttribute) cc.getAttribute("content");
assertEquals("/WEB-INF/jsp/content.jsp", attr.getValue());
}
@Test
public void tilesJstlView() throws Exception {
Locale locale = !Locale.GERMAN.equals(Locale.getDefault()) ? Locale.GERMAN : Locale.FRENCH;
StaticWebApplicationContext wac = prepareWebApplicationContext();
InternalResourceViewResolver irvr = new InternalResourceViewResolver();
irvr.setApplicationContext(wac);
irvr.setViewClass(TilesJstlView.class);
View view = irvr.resolveViewName("testTile", new Locale("nl", ""));
MockHttpServletRequest request = new MockHttpServletRequest(wac.getServletContext());
MockHttpServletResponse response = new MockHttpServletResponse();
request.setAttribute(DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE, wac);
request.setAttribute(DispatcherServlet.LOCALE_RESOLVER_ATTRIBUTE, new FixedLocaleResolver(locale));
wac.addMessage("code1", locale, "messageX");
view.render(new HashMap<String, Object>(), request, response);
assertEquals("/WEB-INF/jsp/layout.jsp", response.getForwardedUrl());
ComponentContext cc = (ComponentContext) request.getAttribute(ComponentConstants.COMPONENT_CONTEXT);
assertNotNull(cc);
PathAttribute attr = (PathAttribute) cc.getAttribute("content");
assertEquals("/WEB-INF/jsp/content.jsp", attr.getValue());
assertEquals(locale, Config.get(request, Config.FMT_LOCALE));
LocalizationContext lc = (LocalizationContext) Config.get(request, Config.FMT_LOCALIZATION_CONTEXT);
assertEquals("messageX", lc.getResourceBundle().getString("code1"));
}
@Test
public void tilesJstlViewWithContextParam() throws Exception {
Locale locale = !Locale.GERMAN.equals(Locale.getDefault()) ? Locale.GERMAN : Locale.FRENCH;
StaticWebApplicationContext wac = prepareWebApplicationContext();
((MockServletContext) wac.getServletContext()).addInitParameter(
Config.FMT_LOCALIZATION_CONTEXT, "org/springframework/web/servlet/view/tiles/context-messages");
InternalResourceViewResolver irvr = new InternalResourceViewResolver();
irvr.setApplicationContext(wac);
irvr.setViewClass(TilesJstlView.class);
View view = irvr.resolveViewName("testTile", new Locale("nl", ""));
MockHttpServletRequest request = new MockHttpServletRequest(wac.getServletContext());
MockHttpServletResponse response = new MockHttpServletResponse();
wac.addMessage("code1", locale, "messageX");
request.setAttribute(DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE, wac);
request.setAttribute(DispatcherServlet.LOCALE_RESOLVER_ATTRIBUTE, new FixedLocaleResolver(locale));
view.render(new HashMap<String, Object>(), request, response);
assertEquals("/WEB-INF/jsp/layout.jsp", response.getForwardedUrl());
ComponentContext cc = (ComponentContext) request.getAttribute(ComponentConstants.COMPONENT_CONTEXT);
assertNotNull(cc);
PathAttribute attr = (PathAttribute) cc.getAttribute("content");
assertEquals("/WEB-INF/jsp/content.jsp", attr.getValue());
LocalizationContext lc = (LocalizationContext) Config.get(request, Config.FMT_LOCALIZATION_CONTEXT);
assertEquals("message1", lc.getResourceBundle().getString("code1"));
assertEquals("message2", lc.getResourceBundle().getString("code2"));
}
@Test
public void tilesViewWithController() throws Exception {
WebApplicationContext wac = prepareWebApplicationContext();
InternalResourceViewResolver irvr = new InternalResourceViewResolver();
irvr.setApplicationContext(wac);
irvr.setViewClass(TilesView.class);
View view = irvr.resolveViewName("testTileWithController", new Locale("nl", ""));
MockHttpServletRequest request = new MockHttpServletRequest(wac.getServletContext());
MockHttpServletResponse response = new MockHttpServletResponse();
request.setAttribute(DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE, wac);
request.setAttribute(DispatcherServlet.LOCALE_RESOLVER_ATTRIBUTE, new AcceptHeaderLocaleResolver());
view.render(new HashMap<String, Object>(), request, response);
assertEquals("/WEB-INF/jsp/layout.jsp", response.getForwardedUrl());
ComponentContext cc = (ComponentContext) request.getAttribute(ComponentConstants.COMPONENT_CONTEXT);
assertNotNull(cc);
PathAttribute attr = (PathAttribute) cc.getAttribute("content");
assertEquals("/WEB-INF/jsp/otherContent.jsp", attr.getValue());
assertEquals("testVal", request.getAttribute("testAttr"));
view.render(new HashMap<String, Object>(), request, response);
assertEquals("/WEB-INF/jsp/layout.jsp", response.getForwardedUrl());
cc = (ComponentContext) request.getAttribute(ComponentConstants.COMPONENT_CONTEXT);
assertNotNull(cc);
attr = (PathAttribute) cc.getAttribute("content");
assertEquals("/WEB-INF/jsp/otherContent.jsp", attr.getValue());
assertEquals("testVal", request.getAttribute("testAttr"));
}
}

View File

@ -0,0 +1,337 @@
/*
* Copyright 2002-2005 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.struts;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionServlet;
import org.apache.struts.config.ModuleConfig;
import static org.easymock.EasyMock.*;
import static org.junit.Assert.*;
import org.junit.Test;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.mock.web.MockServletContext;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.StaticWebApplicationContext;
/**
* @author Juergen Hoeller
* @since 09.04.2004
*/
public class StrutsSupportTests {
@Test
public void actionSupportWithContextLoaderPlugIn() throws ServletException {
StaticWebApplicationContext wac = new StaticWebApplicationContext();
wac.addMessage("test", Locale.getDefault(), "testmessage");
final ServletContext servletContext = new MockServletContext();
wac.setServletContext(servletContext);
wac.refresh();
servletContext.setAttribute(ContextLoaderPlugIn.SERVLET_CONTEXT_PREFIX, wac);
ActionServlet actionServlet = new ActionServlet() {
@Override
public ServletContext getServletContext() {
return servletContext;
}
};
ActionSupport action = new ActionSupport() {
};
action.setServlet(actionServlet);
assertEquals(wac, action.getWebApplicationContext());
assertEquals(servletContext, action.getServletContext());
assertEquals("testmessage", action.getMessageSourceAccessor().getMessage("test"));
action.setServlet(null);
}
@Test
public void actionSupportWithRootContext() throws ServletException {
StaticWebApplicationContext wac = new StaticWebApplicationContext();
wac.addMessage("test", Locale.getDefault(), "testmessage");
final ServletContext servletContext = new MockServletContext();
wac.setServletContext(servletContext);
wac.refresh();
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, wac);
ActionServlet actionServlet = new ActionServlet() {
@Override
public ServletContext getServletContext() {
return servletContext;
}
};
ActionSupport action = new ActionSupport() {
};
action.setServlet(actionServlet);
assertEquals(wac, action.getWebApplicationContext());
assertEquals(servletContext, action.getServletContext());
assertEquals("testmessage", action.getMessageSourceAccessor().getMessage("test"));
action.setServlet(null);
}
@Test
public void dispatchActionSupportWithContextLoaderPlugIn() throws ServletException {
StaticWebApplicationContext wac = new StaticWebApplicationContext();
wac.addMessage("test", Locale.getDefault(), "testmessage");
final ServletContext servletContext = new MockServletContext();
wac.setServletContext(servletContext);
wac.refresh();
servletContext.setAttribute(ContextLoaderPlugIn.SERVLET_CONTEXT_PREFIX, wac);
ActionServlet actionServlet = new ActionServlet() {
@Override
public ServletContext getServletContext() {
return servletContext;
}
};
DispatchActionSupport action = new DispatchActionSupport() {
};
action.setServlet(actionServlet);
assertEquals(wac, action.getWebApplicationContext());
assertEquals(servletContext, action.getServletContext());
assertEquals("testmessage", action.getMessageSourceAccessor().getMessage("test"));
action.setServlet(null);
}
@Test
public void dispatchActionSupportWithRootContext() throws ServletException {
StaticWebApplicationContext wac = new StaticWebApplicationContext();
wac.addMessage("test", Locale.getDefault(), "testmessage");
final ServletContext servletContext = new MockServletContext();
wac.setServletContext(servletContext);
wac.refresh();
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, wac);
ActionServlet actionServlet = new ActionServlet() {
@Override
public ServletContext getServletContext() {
return servletContext;
}
};
DispatchActionSupport action = new DispatchActionSupport() {
};
action.setServlet(actionServlet);
assertEquals(wac, action.getWebApplicationContext());
assertEquals(servletContext, action.getServletContext());
assertEquals("testmessage", action.getMessageSourceAccessor().getMessage("test"));
action.setServlet(null);
}
@Test
public void lookupDispatchActionSupportWithContextLoaderPlugIn() throws ServletException {
StaticWebApplicationContext wac = new StaticWebApplicationContext();
wac.addMessage("test", Locale.getDefault(), "testmessage");
final ServletContext servletContext = new MockServletContext();
wac.setServletContext(servletContext);
wac.refresh();
servletContext.setAttribute(ContextLoaderPlugIn.SERVLET_CONTEXT_PREFIX, wac);
ActionServlet actionServlet = new ActionServlet() {
@Override
public ServletContext getServletContext() {
return servletContext;
}
};
LookupDispatchActionSupport action = new LookupDispatchActionSupport() {
@Override
protected Map getKeyMethodMap() {
return new HashMap();
}
};
action.setServlet(actionServlet);
assertEquals(wac, action.getWebApplicationContext());
assertEquals(servletContext, action.getServletContext());
assertEquals("testmessage", action.getMessageSourceAccessor().getMessage("test"));
action.setServlet(null);
}
@Test
public void lookupDispatchActionSupportWithRootContext() throws ServletException {
StaticWebApplicationContext wac = new StaticWebApplicationContext();
wac.addMessage("test", Locale.getDefault(), "testmessage");
final ServletContext servletContext = new MockServletContext();
wac.setServletContext(servletContext);
wac.refresh();
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, wac);
ActionServlet actionServlet = new ActionServlet() {
@Override
public ServletContext getServletContext() {
return servletContext;
}
};
LookupDispatchActionSupport action = new LookupDispatchActionSupport() {
@Override
protected Map getKeyMethodMap() {
return new HashMap();
}
};
action.setServlet(actionServlet);
assertEquals(wac, action.getWebApplicationContext());
assertEquals(servletContext, action.getServletContext());
assertEquals("testmessage", action.getMessageSourceAccessor().getMessage("test"));
action.setServlet(null);
}
@Test
public void testDelegatingActionProxy() throws Exception {
final MockServletContext servletContext = new MockServletContext("/org/springframework/web/struts/");
ContextLoaderPlugIn plugin = new ContextLoaderPlugIn();
ActionServlet actionServlet = new ActionServlet() {
@Override
public String getServletName() {
return "action";
}
@Override
public ServletContext getServletContext() {
return servletContext;
}
};
ModuleConfig moduleConfig = createMock(ModuleConfig.class);
expect(moduleConfig.getPrefix()).andReturn("").anyTimes();
replay(moduleConfig);
plugin.init(actionServlet, moduleConfig);
assertTrue(servletContext.getAttribute(ContextLoaderPlugIn.SERVLET_CONTEXT_PREFIX) != null);
DelegatingActionProxy proxy = new DelegatingActionProxy();
proxy.setServlet(actionServlet);
ActionMapping mapping = new ActionMapping();
mapping.setPath("/test");
mapping.setModuleConfig(moduleConfig);
ActionForward forward = proxy.execute(
mapping, null, new MockHttpServletRequest(servletContext), new MockHttpServletResponse());
assertEquals("/test", forward.getPath());
TestAction testAction = (TestAction) plugin.getWebApplicationContext().getBean("/test");
assertTrue(testAction.getServlet() != null);
proxy.setServlet(null);
plugin.destroy();
assertTrue(testAction.getServlet() == null);
verify(moduleConfig);
}
@Test
public void delegatingActionProxyWithModule() throws Exception {
final MockServletContext servletContext = new MockServletContext("/org/springframework/web/struts/WEB-INF");
ContextLoaderPlugIn plugin = new ContextLoaderPlugIn();
plugin.setContextConfigLocation("action-servlet.xml");
ActionServlet actionServlet = new ActionServlet() {
@Override
public String getServletName() {
return "action";
}
@Override
public ServletContext getServletContext() {
return servletContext;
}
};
ModuleConfig moduleConfig = createMock(ModuleConfig.class);
expect(moduleConfig.getPrefix()).andReturn("/module").anyTimes();
replay(moduleConfig);
plugin.init(actionServlet, moduleConfig);
assertTrue(servletContext.getAttribute(ContextLoaderPlugIn.SERVLET_CONTEXT_PREFIX) == null);
assertTrue(servletContext.getAttribute(ContextLoaderPlugIn.SERVLET_CONTEXT_PREFIX + "/module") != null);
DelegatingActionProxy proxy = new DelegatingActionProxy();
proxy.setServlet(actionServlet);
ActionMapping mapping = new ActionMapping();
mapping.setPath("/test2");
mapping.setModuleConfig(moduleConfig);
ActionForward forward = proxy.execute(
mapping, null, new MockHttpServletRequest(servletContext), new MockHttpServletResponse());
assertEquals("/module/test2", forward.getPath());
TestAction testAction = (TestAction) plugin.getWebApplicationContext().getBean("/module/test2");
assertTrue(testAction.getServlet() != null);
proxy.setServlet(null);
plugin.destroy();
assertTrue(testAction.getServlet() == null);
verify(moduleConfig);
}
@Test
public void delegatingActionProxyWithModuleAndDefaultContext() throws Exception {
final MockServletContext servletContext = new MockServletContext("/org/springframework/web/struts/WEB-INF");
ContextLoaderPlugIn plugin = new ContextLoaderPlugIn();
plugin.setContextConfigLocation("action-servlet.xml");
ActionServlet actionServlet = new ActionServlet() {
@Override
public String getServletName() {
return "action";
}
@Override
public ServletContext getServletContext() {
return servletContext;
}
};
ModuleConfig defaultModuleConfig = createMock(ModuleConfig.class);
expect(defaultModuleConfig.getPrefix()).andReturn("").anyTimes();
ModuleConfig moduleConfig = createMock(ModuleConfig.class);
expect(moduleConfig.getPrefix()).andReturn("/module").anyTimes();
replay(defaultModuleConfig, moduleConfig);
plugin.init(actionServlet, defaultModuleConfig);
assertTrue(servletContext.getAttribute(ContextLoaderPlugIn.SERVLET_CONTEXT_PREFIX) != null);
assertTrue(servletContext.getAttribute(ContextLoaderPlugIn.SERVLET_CONTEXT_PREFIX + "/module") == null);
DelegatingActionProxy proxy = new DelegatingActionProxy();
proxy.setServlet(actionServlet);
ActionMapping mapping = new ActionMapping();
mapping.setPath("/test2");
mapping.setModuleConfig(moduleConfig);
ActionForward forward = proxy.execute(
mapping, null, new MockHttpServletRequest(servletContext), new MockHttpServletResponse());
assertEquals("/module/test2", forward.getPath());
TestAction testAction = (TestAction) plugin.getWebApplicationContext().getBean("/module/test2");
assertTrue(testAction.getServlet() != null);
proxy.setServlet(null);
plugin.destroy();
assertTrue(testAction.getServlet() == null);
verify(defaultModuleConfig, moduleConfig);
}
}

View File

@ -0,0 +1,48 @@
/*
* Copyright 2002-2006 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.struts;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.springframework.beans.factory.BeanNameAware;
/**
* @author Juergen Hoeller
* @since 09.04.2004
*/
public class TestAction extends Action implements BeanNameAware {
private String beanName;
public void setBeanName(String beanName) {
this.beanName = beanName;
}
@Override
public ActionForward execute(
ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response){
return new ActionForward(this.beanName);
}
}

View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<!-- Appenders -->
<appender name="console" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%-5p: %c - %m%n" />
</layout>
</appender>
<logger name="org.springframework.beans">
<level value="warn" />
</logger>
<logger name="org.springframework.binding">
<level value="debug" />
</logger>
<!-- Root Logger -->
<root>
<priority value="warn" />
<appender-ref ref="console" />
</root>
</log4j:configuration>

View File

@ -0,0 +1,6 @@
code1=message1
code2=message2
# Example taken from the javadocs for the java.text.MessageFormat class
message.format.example1=At '{1,time}' on "{1,date}", there was "{2}" on planet {0,number,integer}.
message.format.example2=This is a test message in the message catalog with no args.

View File

@ -0,0 +1,2 @@
# Example taken from the javadocs for the java.text.MessageFormat class
message.format.example1=At '{1,time}' on "{1,date}", there was "{2}" on station number {0,number,integer}.

View File

@ -0,0 +1,5 @@
code1=message1
# Example taken from the javadocs for the java.text.MessageFormat class
message.format.example1=At '{1,time}' on "{1,date}", there was "{2}" on planet {0,number,integer}.
message.format.example2=This is a test message in the message catalog with no args.

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE tiles-definitions PUBLIC
"-//Apache Software Foundation//DTD Tiles Configuration 1.1//EN"
"http://jakarta.apache.org/struts/dtds/tiles-config_1_1.dtd">
<tiles-definitions>
<definition name="testTile" path="/WEB-INF/jsp/layout.jsp">
<put name="content" value="/WEB-INF/jsp/content.jsp" type="page"/>
</definition>
<definition name="testTileWithController" controllerClass="org.springframework.web.servlet.view.tiles.TestComponentController">
<put name="content" value="/WEB-INF/jsp/otherContent.jsp" type="page"/>
</definition>
</tiles-definitions>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
<bean name="/test" class="org.springframework.web.struts.TestAction"/>
<bean name="/module/test2" class="org.springframework.web.struts.TestAction"/>
</beans>

View File

@ -0,0 +1,19 @@
Bundle-SymbolicName: org.springframework.web.struts
Bundle-Name: Spring Web Struts
Bundle-Vendor: SpringSource
Bundle-ManifestVersion: 2
Import-Template:
javax.servlet.*;version="[2.4.0, 3.0.0)",
org.apache.commons.beanutils.*;version="[1.7.0, 2.0.0)",
org.apache.commons.logging.*;version="[1.0.4, 2.0.0)",
org.apache.struts.*;version="[1.2.9, 2.0.0)",
org.springframework.beans.*;version="[3.0.0, 3.0.1)",
org.springframework.context.*;version="[3.0.0, 3.0.1)",
org.springframework.util.*;version="[3.0.0, 3.0.1)",
org.springframework.validation.*;version="[3.0.0, 3.0.1)",
org.springframework.web.*;version="[3.0.0, 3.0.1)"
Ignored-Existing-Headers:
Bnd-LastModified,
Import-Package,
Export-Package,
Tool

View File

@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8"?>
<module relativePaths="true" type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/resources" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="beans" />
<orderEntry type="module" module-name="context" />
<orderEntry type="module" module-name="core" />
<orderEntry type="module" module-name="test" />
<orderEntry type="module" module-name="web" />
<orderEntry type="library" name="Commons Logging" level="project" />
<orderEntry type="library" name="javax.servlet" level="project" />
<orderEntry type="module-library">
<library>
<CLASSES>
<root url="jar://$IVY_CACHE$/org.apache.struts/com.springsource.org.apache.struts/1.2.9/com.springsource.org.apache.struts-1.2.9.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$IVY_CACHE$/org.apache.struts/com.springsource.org.apache.struts/1.2.9/com.springsource.org.apache.struts-sources-1.2.9.jar!/" />
</SOURCES>
</library>
</orderEntry>
<orderEntry type="library" name="JUnit" level="project" />
<orderEntry type="module-library">
<library>
<CLASSES>
<root url="jar://$IVY_CACHE$/org.apache.commons/com.springsource.org.apache.commons.beanutils/1.7.0/com.springsource.org.apache.commons.beanutils-1.7.0.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$IVY_CACHE$/org.apache.commons/com.springsource.org.apache.commons.beanutils/1.7.0/com.springsource.org.apache.commons.beanutils-sources-1.7.0.jar!/" />
</SOURCES>
</library>
</orderEntry>
<orderEntry type="library" name="EasyMock" level="project" />
<orderEntry type="module" module-name="web-servlet" />
<orderEntry type="module-library">
<library>
<CLASSES>
<root url="jar://$IVY_CACHE$/javax.servlet/com.springsource.javax.servlet.jsp.jstl/1.1.2/com.springsource.javax.servlet.jsp.jstl-1.1.2.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$IVY_CACHE$/javax.servlet/com.springsource.javax.servlet.jsp.jstl/1.1.2/com.springsource.javax.servlet.jsp.jstl-sources-1.1.2.jar!/" />
</SOURCES>
</library>
</orderEntry>
<orderEntry type="module-library">
<library>
<CLASSES>
<root url="jar://$IVY_CACHE$/javax.servlet/com.springsource.javax.servlet.jsp/2.1.0/com.springsource.javax.servlet.jsp-2.1.0.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$IVY_CACHE$/javax.servlet/com.springsource.javax.servlet.jsp/2.1.0/com.springsource.javax.servlet.jsp-sources-2.1.0.jar!/" />
</SOURCES>
</library>
</orderEntry>
</component>
</module>