/*
* 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.mvc;
import java.util.Enumeration;
import java.util.Properties;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.web.servlet.ModelAndView;
/**
* Spring Controller implementation that wraps a servlet instance which it manages
* internally. Such a wrapped servlet is not known outside of this controller;
* its entire lifecycle is covered here (in contrast to {@link ServletForwardingController}).
*
* <p>Useful to invoke an existing servlet via Spring's dispatching infrastructure,
* for example to apply Spring HandlerInterceptors to its requests.
*
* <p>Note that Struts has a special requirement in that it parses <code>web.xml</code>
* to find its servlet mapping. Therefore, you need to specify the DispatcherServlet's
* servlet name as "servletName" on this controller, so that Struts finds the
* DispatcherServlet's mapping (thinking that it refers to the ActionServlet).
*
* <p><b>Example:</b> a DispatcherServlet XML context, forwarding "*.do" to the Struts
* ActionServlet wrapped by a ServletWrappingController. All such requests will go
* through the configured HandlerInterceptor chain (e.g. an OpenSessionInViewInterceptor).
* From the Struts point of view, everything will work as usual.
*
* <pre>
* <bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
* <property name="interceptors">
* <list>
* <ref bean="openSessionInViewInterceptor"/>
* </list>
* </property>
* <property name="mappings">
* <props>
* <prop key="*.do">strutsWrappingController</prop>
* </props>
* </property>
* </bean>
*
* <bean id="strutsWrappingController" class="org.springframework.web.servlet.mvc.ServletWrappingController">
* <property name="servletClass">
* <value>org.apache.struts.action.ActionServlet</value>
* </property>
* <property name="servletName">
* <value>action</value>
* </property>
* <property name="initParameters">
* <props>
* <prop key="config">/WEB-INF/struts-config.xml</prop>
* </props>
* </property>
* </bean></pre>
*
* @author Juergen Hoeller
* @since 1.1.1
* @see ServletForwardingController
* @see org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor
* @see org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
* @see org.springframework.orm.jdo.support.OpenPersistenceManagerInViewInterceptor
* @see org.springframework.orm.jdo.support.OpenPersistenceManagerInViewFilter
*/
public class ServletWrappingController extends AbstractController
implements BeanNameAware, InitializingBean, DisposableBean {
private Class servletClass;
private String servletName;
private Properties initParameters = new Properties();
private String beanName;
private Servlet servletInstance;
/**
* Set the class of the servlet to wrap.
* Needs to implement <code>javax.servlet.Servlet</code>.
* @see javax.servlet.Servlet
*/
public void setServletClass(Class servletClass) {
this.servletClass = servletClass;
}
/**
* Set the name of the servlet to wrap.
* Default is the bean name of this controller.
*/
public void setServletName(String servletName) {
this.servletName = servletName;
}
/**
* Specify init parameters for the servlet to wrap,
* as name-value pairs.
*/
public void setInitParameters(Properties initParameters) {
this.initParameters = initParameters;
}
public void setBeanName(String name) {
this.beanName = name;
}
/**
* Initialize the wrapped Servlet instance.
* @see javax.servlet.Servlet#init(javax.servlet.ServletConfig)
*/
public void afterPropertiesSet() throws Exception {
if (this.servletClass == null) {
throw new IllegalArgumentException("servletClass is required");
}
if (!Servlet.class.isAssignableFrom(this.servletClass)) {
throw new IllegalArgumentException("servletClass [" + this.servletClass.getName() +
"] needs to implement interface [javax.servlet.Servlet]");
}
if (this.servletName == null) {
this.servletName = this.beanName;
}
this.servletInstance = (Servlet) this.servletClass.newInstance();
this.servletInstance.init(new DelegatingServletConfig());
}
/**
* Invoke the the wrapped Servlet instance.
* @see javax.servlet.Servlet#service(javax.servlet.ServletRequest, javax.servlet.ServletResponse)
*/
@Override
protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response)
throws Exception {
this.servletInstance.service(request, response);
return null;
}
/**
* Destroy the wrapped Servlet instance.
* @see javax.servlet.Servlet#destroy()
*/
public void destroy() {
this.servletInstance.destroy();
}
/**
* Internal implementation of the ServletConfig interface, to be passed
* to the wrapped servlet. Delegates to ServletWrappingController fields
* and methods to provide init parameters and other environment info.
*/
private class DelegatingServletConfig implements ServletConfig {
public String getServletName() {
return servletName;
}
public ServletContext getServletContext() {
return ServletWrappingController.this.getServletContext();
}
public String getInitParameter(String paramName) {
return initParameters.getProperty(paramName);
}
public Enumeration getInitParameterNames() {
return initParameters.keys();
}
}
}
|