/* * This program is free software; you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software * Foundation. * * You should have received a copy of the GNU Lesser General Public License along with this * program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html * or from the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Lesser General Public License for more details. * * Copyright 2005 - 2009 Pentaho Corporation. All rights reserved. * */ package org.pentaho.platform.web.servlet; import java.io.IOException; import java.util.Map; import javax.servlet.Servlet; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.BeanFactoryUtils; import org.springframework.context.ApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; /** * Delegates Servlet requests to a Spring-managed bean. Based in <code>FilterToBeanProxy</code>. * * @author mlowery * @see */ public class ServletToBeanProxy implements Servlet { // ~ Static fields/initializers ====================================================================================== private static final long serialVersionUID = 2934977002901688130L; private static final Log logger = LogFactory.getLog(ServletToBeanProxy.class); // ~ Instance fields ================================================================================================= protected Servlet delegate; private ServletConfig servletConfig; private boolean initialized = false; private boolean servletContainerManaged = false; // ~ Constructors ==================================================================================================== public ServletToBeanProxy() { super(); } // ~ Methods ========================================================================================================= public void destroy() { if (ServletToBeanProxy.logger.isDebugEnabled()) { ServletToBeanProxy.logger.debug("[destroy]"); } if ((delegate != null) && servletContainerManaged) { if (ServletToBeanProxy.logger.isDebugEnabled()) { ServletToBeanProxy.logger.debug("servletContainerManaged=true so calling destroy"); } delegate.destroy(); } } public void service(final ServletRequest req, final ServletResponse res) throws ServletException, IOException { if (!initialized) { doInit(); } if (ServletToBeanProxy.logger.isDebugEnabled()) { ServletToBeanProxy.logger.debug("[service]"); } delegate.service(req, res); } private synchronized void doInit() throws ServletException { if (initialized) { // already initialized, so don't re-initialize return; } if (ServletToBeanProxy.logger.isDebugEnabled()) { ServletToBeanProxy.logger.debug("[doInit]"); } String targetBean = servletConfig.getInitParameter("targetBean"); //$NON-NLS-1$ if (ServletToBeanProxy.logger.isDebugEnabled()) { ServletToBeanProxy.logger.debug("targetBean=" + targetBean); } if ("".equals(targetBean)) { //$NON-NLS-1$ targetBean = null; } String lifecycle = servletConfig.getInitParameter("lifecycle"); //$NON-NLS-1$ if (ServletToBeanProxy.logger.isDebugEnabled()) { ServletToBeanProxy.logger.debug("lifecycle=" + lifecycle); } if ("servlet-container-managed".equals(lifecycle)) { //$NON-NLS-1$ servletContainerManaged = true; } ApplicationContext ctx = this.getContext(servletConfig); String beanName = null; if ((targetBean != null) && ctx.containsBean(targetBean)) { if (ServletToBeanProxy.logger.isDebugEnabled()) { ServletToBeanProxy.logger.debug("using targetBean"); } beanName = targetBean; } else if (targetBean != null) { throw new ServletException("targetBean '" + targetBean + "' not found in context"); } else { if (ServletToBeanProxy.logger.isDebugEnabled()) { ServletToBeanProxy.logger.debug("using targetClass"); } String targetClassString = servletConfig.getInitParameter("targetClass"); //$NON-NLS-1$ if ((targetClassString == null) || "".equals(targetClassString)) { //$NON-NLS-1$ throw new ServletException("targetClass or targetBean must be specified"); } Class targetClass; try { targetClass = Thread.currentThread().getContextClassLoader().loadClass(targetClassString); } catch (ClassNotFoundException ex) { throw new ServletException("Class of type " + targetClassString + " not found in classloader"); } Map beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(ctx, targetClass, true, true); if (beans.size() == 0) { throw new ServletException("Bean context must contain at least one bean of type " + targetClassString); } beanName = (String) beans.keySet().iterator().next(); } Object object = ctx.getBean(beanName); if (ServletToBeanProxy.logger.isDebugEnabled()) { ServletToBeanProxy.logger.debug("got bean=" + object); } if (!(object instanceof Servlet)) { throw new ServletException("Bean '" + beanName + "' does not implement javax.servlet.Servlet"); } delegate = (Servlet) object; if (servletContainerManaged) { if (ServletToBeanProxy.logger.isDebugEnabled()) { ServletToBeanProxy.logger.debug("servletContainerManaged=true so calling init"); } delegate.init(servletConfig); } // Set initialized to true at the end of the synchronized method, so // that invocations of service() before this method has completed will not // cause NullPointerException initialized = true; } public ServletConfig getServletConfig() { return delegate.getServletConfig(); } public String getServletInfo() { return delegate.getServletInfo(); } protected ApplicationContext getContext(final ServletConfig config) { return WebApplicationContextUtils.getRequiredWebApplicationContext(config.getServletContext()); } public void init(final ServletConfig config) throws ServletException { this.servletConfig = config; if (ServletToBeanProxy.logger.isDebugEnabled()) { ServletToBeanProxy.logger.debug("[init]"); } String strategy = servletConfig.getInitParameter("init"); //$NON-NLS-1$ if (ServletToBeanProxy.logger.isDebugEnabled()) { ServletToBeanProxy.logger.debug("init (strategy)=" + strategy); } if ((strategy != null) && strategy.toLowerCase().equals("lazy")) { //$NON-NLS-1$ if (ServletToBeanProxy.logger.isDebugEnabled()) { ServletToBeanProxy.logger.debug("strategy=lazy so deferring init"); } return; } doInit(); } }