/* * Copyright 2012 The Solmix Project * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software 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. * * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.gnu.org/licenses/ * or see the FSF site: http://www.fsf.org. */ package org.solmix.launch.base.web; import java.io.IOException; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; import javax.servlet.GenericServlet; import javax.servlet.Servlet; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletResponse; import org.apache.felix.http.proxy.ProxyServlet; import org.osgi.framework.BundleException; import org.solmix.launch.base.internal.Solmix; import org.solmix.launch.base.shared.LaunchConstants; import org.solmix.launch.base.shared.Launcher; import org.solmix.launch.base.shared.Notifiable; /** * <code>ServletDelegate</code>作为solmix框架servlet入口的基本类,它主要完成下列一些操作: * * @author ffz * @version 110035 2012-3-16 */ @SuppressWarnings("serial") public class ServletDelegate extends GenericServlet implements Launcher { private String solmixHome; private Servlet delegatee; private Notifiable notifiable; private boolean servletDestroyed = false; private Map<String, String> properties; private OsgiBridge bridge; @Override public final void init() throws ServletException { Servlet tmpDelegatee = null; OsgiBridge tmpBridge = null; try { // read the default parameters Map<String, String> props = loadConfigProperties(solmixHome); tmpBridge = new OsgiBridge(notifiable, props, getServletContext()); // set up the OSGi HttpService proxy servlet tmpDelegatee = new ProxyServlet(); tmpDelegatee.init(getServletConfig()); if (servletDestroyed) { log("Servlet Delegatee destroyed while starting framework."); } else { this.bridge = tmpBridge; this.delegatee = tmpDelegatee; tmpBridge = null; tmpDelegatee = null; log("Started osgi framework sucess."); } } catch (BundleException e) { throw new ServletException("Failed to start Solmix internal OSGI framework in " + solmixHome, e); } catch (ServletException se) { throw new ServletException("Failed to start bridge servlet for solmix ", se); } catch (Throwable t) { throw new ServletException("Uncaught Failure starting solmix", t); } finally { // clean up temporary fields if (tmpDelegatee != null) { tmpDelegatee.destroy(); } if (tmpBridge != null) { tmpBridge.destroy(); } } } /** * @param solmixHome * @return configuration properties. */ private Map<String, String> loadConfigProperties(String solmixHome) { // The config properties file is either specified by a system // property or it is in the etc config directory。. // Try to load it from one of these places. Map<String, String> props = new HashMap<String, String>(); // The following property must start with a comma! final String servletVersion = getServletContext().getMajorVersion() + "." + getServletContext().getMinorVersion(); props.put(Solmix.PROP_SYSTEM_PACKAGES, ",javax.servlet;javax.servlet.http;javax.servlet.resources; version=" + servletVersion); if (this.properties != null) { props.putAll(this.properties); } else { // copy context init parameters @SuppressWarnings("unchecked") Enumeration<String> cpe = getServletContext().getInitParameterNames(); while (cpe.hasMoreElements()) { String name = cpe.nextElement(); props.put(name, getServletContext().getInitParameter(name)); } // copy servlet init parameters @SuppressWarnings("unchecked") Enumeration<String> pe = getInitParameterNames(); while (pe.hasMoreElements()) { String name = pe.nextElement(); props.put(name, getInitParameter(name)); } } // TODO add bundles repo. // set solmix home props.put(LaunchConstants.SOLMIX_HOME, solmixHome); if (!props.containsKey(LaunchConstants.SOLMIX_BASE)) { props.put(LaunchConstants.SOLMIX_BASE, solmixHome); } return props; } /** * @return the delegatee */ public Servlet getDelegatee() { return delegatee; } @Override public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { // delegate the request to the registered delegatee servlet Servlet delegatee = getDelegatee(); if (delegatee == null) { ((HttpServletResponse) res).sendError(HttpServletResponse.SC_NOT_FOUND); } else { delegatee.service(req, res); } } @Override public boolean start() { return false; } @Override public void stop() { destroy(); } /** * {@inheritDoc} * * @see org.solmix.loaders.shared.Launcher#setSolmixHome(java.lang.String) */ @Override public void setSolmixHome(String solmixHome) { this.solmixHome = solmixHome; } /** * {@inheritDoc} * * @see org.solmix.loaders.shared.Launcher#setNotifiable(org.solmix.loaders.shared.Notifiable) */ @Override public void setNotifiable(Notifiable notifiable) { this.notifiable = notifiable; } /** * Properties form servletcontext. */ @Override public void setCommandLine(Map<String, String> args) { this.properties = args; } /** * Destroys this servlet by shutting down the OSGi framework and hence the delegatee servlet if one is set at all. */ public final void destroy() { // set the destroyed flag to signal to the startSling method // that Sling should be terminated immediately servletDestroyed = true; // destroy the delegatee if (delegatee != null) { delegatee.destroy(); delegatee = null; } // shutdown the Felix container if (bridge != null) { bridge.destroy(); bridge = null; } // finally call the base class destroy method super.destroy(); } }