/**
* GRANITE DATA SERVICES
* Copyright (C) 2006-2015 GRANITE DATA SERVICES S.A.S.
*
* This file is part of the Granite Data Services Platform.
*
* Granite Data Services 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.
*
* Granite Data Services 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 should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA, or see <http://www.gnu.org/licenses/>.
*/
package org.granite.gravity;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import org.granite.config.ConfigProvider;
import org.granite.config.GraniteConfig;
import org.granite.config.GraniteConfigListener;
import org.granite.config.ServletGraniteConfig;
import org.granite.config.flex.ServicesConfig;
import org.granite.config.flex.ServletServicesConfig;
import org.granite.util.TypeUtil;
/**
* @author Franck WOLFF
*/
public class GravityManager {
static final String GRAVITY_KEY = Gravity.class.getName();
/**
* Parse gravity configuration (granite-config.xml), start gravity by using the specified factory and put it
* in ServletContext. If Gravity is already started, returns the previous instance from the servlet context.
* <br><br>
* This method is intended to be used in {@link HttpServlet#init(ServletConfig)} methods only and
* synchronizes on the current ServletContext instance.
*
* @param servletConfig the servlet config passed in HttpServlet.init(ServletConfig config) method.
* @return a newly created and started Gravity instance or previously started one.
* @throws ServletException if something goes wrong (GravityFactory not found, Gravity.start() error, etc.)
*/
public static Gravity start(ServletConfig servletConfig) throws ServletException {
return start(servletConfig.getServletContext());
}
public static Gravity start(ServletContext context) throws ServletException {
Gravity gravity = null;
synchronized (context) {
gravity = (Gravity)context.getAttribute(GRAVITY_KEY);
if (gravity == null) {
GraniteConfig graniteConfig = ServletGraniteConfig.loadConfig(context);
graniteConfig.setSharedContext(GraniteConfigListener.getSharedContext(context));
ServicesConfig servicesConfig = ServletServicesConfig.loadConfig(context);
GravityServiceConfigurator serviceConfigurator = (GravityServiceConfigurator)context.getAttribute(GraniteConfigListener.GRANITE_CONFIG_ATTRIBUTE);
if (serviceConfigurator != null)
serviceConfigurator.configureGravityServices(context);
GravityConfig gravityConfig = new GravityConfig(graniteConfig);
String gravityFactory = gravityConfig.getGravityFactory();
try {
GravityFactory factory = TypeUtil.newInstance(gravityFactory, GravityFactory.class);
gravity = factory.newGravity(gravityConfig, servicesConfig, graniteConfig);
}
catch (Exception e) {
throw new ServletException("Could not create Gravity instance with factory: " + gravityFactory, e);
}
try {
gravity.start();
context.setAttribute(GRAVITY_KEY, gravity);
if (context.getAttribute(GraniteConfigListener.GRANITE_CONFIG_PROVIDER_ATTRIBUTE) != null)
((ConfigProvider)context.getAttribute(GraniteConfigListener.GRANITE_CONFIG_PROVIDER_ATTRIBUTE)).initGravity(gravity);
GraniteConfigListener.registerShutdownListener(context, ((GravityInternal)gravity));
}
catch (Exception e) {
throw new ServletException("Gravity initialization error", e);
}
}
}
return gravity;
}
public static interface GravityServiceConfigurator {
public void configureGravityServices(ServletContext context) throws ServletException;
}
/**
* Reconfigure gravity with the new supplied configuration (after reloading granite-config.xml).
* <br><br>
* Only these configuration options are taken into account when reconfiguring Gravity:
* <ul>
* <li>channelIdleTimeoutMillis</li>
* <li>longPollingTimeout</li>
* <li>retryOnError</li>
* <li>maxMessagesQueuedPerChannel</li>
* <li>corePoolSize</li>
* <li>maximumPoolSize</li>
* <li>keepAliveTimeMillis</li>
* </ul>
*
* @param context the ServletContext where the gravity instance is registered.
* @param gravityConfig the new (reloaded) GravityConfig.
*/
public static void reconfigure(ServletContext context, GravityConfig gravityConfig) {
synchronized (context) {
Gravity gravity = getGravity(context);
gravity.reconfigure(gravityConfig, ServletGraniteConfig.getConfig(context));
}
}
/**
* Returns a previously started Gravity instance. This method isn't synchronized and should be used in
* HttpServlet.doPost(...) methods only.
*
* @param context the ServletContext from which to retrieve the Gravity instance.
* @return the unique and started Gravity instance (or null if {@link #start(ServletConfig)}
* has never been called).
*/
public static Gravity getGravity(ServletContext context) {
return (Gravity)context.getAttribute(GRAVITY_KEY);
}
}