001/** 002 * GRANITE DATA SERVICES 003 * Copyright (C) 2006-2013 GRANITE DATA SERVICES S.A.S. 004 * 005 * This file is part of the Granite Data Services Platform. 006 * 007 * Granite Data Services is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * Granite Data Services is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 015 * General Public License for more details. 016 * 017 * You should have received a copy of the GNU Lesser General Public 018 * License along with this library; if not, write to the Free Software 019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 020 * USA, or see <http://www.gnu.org/licenses/>. 021 */ 022package org.granite.gravity; 023 024import javax.servlet.ServletConfig; 025import javax.servlet.ServletContext; 026import javax.servlet.ServletException; 027import javax.servlet.http.HttpServlet; 028 029import org.granite.config.ConfigProvider; 030import org.granite.config.GraniteConfig; 031import org.granite.config.GraniteConfigListener; 032import org.granite.config.ServletGraniteConfig; 033import org.granite.config.flex.ServicesConfig; 034import org.granite.config.flex.ServletServicesConfig; 035import org.granite.util.TypeUtil; 036 037/** 038 * @author Franck WOLFF 039 */ 040public class GravityManager { 041 042 private static final String GRAVITY_KEY = Gravity.class.getName(); 043 044 /** 045 * Parse gravity configuration (granite-config.xml), start gravity by using the specified factory and put it 046 * in ServletContext. If Gravity is already started, returns the previous instance from the servlet context. 047 * <br><br> 048 * This method is intended to be used in {@link HttpServlet#init(ServletConfig)} methods only and 049 * synchronizes on the current ServletContext instance. 050 * 051 * @param servletConfig the servlet config passed in HttpServlet.init(ServletConfig config) method. 052 * @return a newly created and started Gravity instance or previously started one. 053 * @throws ServletException if something goes wrong (GravityFactory not found, Gravity.start() error, etc.) 054 */ 055 public static Gravity start(ServletConfig servletConfig) throws ServletException { 056 return start(servletConfig.getServletContext()); 057 } 058 059 public static Gravity start(ServletContext context) throws ServletException { 060 Gravity gravity = null; 061 062 synchronized (context) { 063 064 gravity = (Gravity)context.getAttribute(GRAVITY_KEY); 065 066 if (gravity == null) { 067 GraniteConfig graniteConfig = ServletGraniteConfig.loadConfig(context); 068 ServicesConfig servicesConfig = ServletServicesConfig.loadConfig(context); 069 070 GravityServiceConfigurator serviceConfigurator = (GravityServiceConfigurator)context.getAttribute(GraniteConfigListener.GRANITE_CONFIG_ATTRIBUTE); 071 if (serviceConfigurator != null) 072 serviceConfigurator.configureGravityServices(context); 073 074 GravityConfig gravityConfig = new GravityConfig(graniteConfig); 075 076 String gravityFactory = gravityConfig.getGravityFactory(); 077 try { 078 GravityFactory factory = TypeUtil.newInstance(gravityFactory, GravityFactory.class); 079 gravity = factory.newGravity(gravityConfig, servicesConfig, graniteConfig, GraniteConfigListener.getSharedContext(context)); 080 } 081 catch (Exception e) { 082 throw new ServletException("Could not create Gravity instance with factory: " + gravityFactory, e); 083 } 084 085 try { 086 gravity.start(); 087 context.setAttribute(GRAVITY_KEY, gravity); 088 089 if (context.getAttribute(GraniteConfigListener.GRANITE_CONFIG_PROVIDER_ATTRIBUTE) != null) 090 ((ConfigProvider)context.getAttribute(GraniteConfigListener.GRANITE_CONFIG_PROVIDER_ATTRIBUTE)).initGravity(gravity); 091 092 GraniteConfigListener.registerShutdownListener(context, gravity); 093 } 094 catch (Exception e) { 095 throw new ServletException("Gravity initialization error", e); 096 } 097 } 098 } 099 100 return gravity; 101 } 102 103 104 public static interface GravityServiceConfigurator { 105 106 public void configureGravityServices(ServletContext context) throws ServletException; 107 } 108 109 110 /** 111 * Reconfigure gravity with the new supplied configuration (after reloading granite-config.xml). 112 * <br><br> 113 * Only these configuration options are taken into account when reconfiguring Gravity: 114 * <ul> 115 * <li>channelIdleTimeoutMillis</li> 116 * <li>longPollingTimeout</li> 117 * <li>retryOnError</li> 118 * <li>maxMessagesQueuedPerChannel</li> 119 * <li>corePoolSize</li> 120 * <li>maximumPoolSize</li> 121 * <li>keepAliveTimeMillis</li> 122 * </ul> 123 * 124 * @param context the ServletContext where the gravity instance is registered. 125 * @param gravityConfig the new (reloaded) GravityConfig. 126 */ 127 public static void reconfigure(ServletContext context, GravityConfig gravityConfig) { 128 synchronized (context) { 129 Gravity gravity = getGravity(context); 130 gravity.reconfigure(gravityConfig, ServletGraniteConfig.getConfig(context)); 131 } 132 } 133 134 /** 135 * Returns a previously started Gravity instance. This method isn't synchronized and should be used in 136 * HttpServlet.doPost(...) methods only. 137 * 138 * @param context the ServletContext from which to retrieve the Gravity instance. 139 * @return the unique and started Gravity instance (or null if {@link #start(ServletConfig)} 140 * has never been called). 141 */ 142 public static Gravity getGravity(ServletContext context) { 143 return (Gravity)context.getAttribute(GRAVITY_KEY); 144 } 145 146}