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.naming.InitialContext; 025import javax.servlet.ServletConfig; 026import javax.servlet.ServletContext; 027import javax.servlet.ServletException; 028import javax.servlet.http.HttpServlet; 029 030import org.granite.config.ConfigProvider; 031import org.granite.config.GraniteConfig; 032import org.granite.config.GraniteConfigListener; 033import org.granite.config.ServletGraniteConfig; 034import org.granite.config.flex.ServicesConfig; 035import org.granite.config.flex.ServletServicesConfig; 036import org.granite.logging.Logger; 037import org.granite.util.TypeUtil; 038 039import java.lang.reflect.Method; 040 041/** 042 * @author Franck WOLFF 043 */ 044public class GravityManager { 045 046 private static final Logger log = Logger.getLogger(GravityManager.class); 047 048 private static final String GRAVITY_KEY = Gravity.class.getName(); 049 050 /** 051 * Parse gravity configuration (granite-config.xml), start gravity by using the specified factory and put it 052 * in ServletContext. If Gravity is already started, returns the previous instance from the servlet context. 053 * <br><br> 054 * This method is intended to be used in {@link HttpServlet#init(ServletConfig)} methods only and 055 * synchronizes on the current ServletContext instance. 056 * 057 * @param servletConfig the servlet config passed in HttpServlet.init(ServletConfig config) method. 058 * @return a newly created and started Gravity instance or previously started one. 059 * @throws ServletException if something goes wrong (GravityFactory not found, Gravity.start() error, etc.) 060 */ 061 public static Gravity start(ServletConfig servletConfig) throws ServletException { 062 return start(servletConfig.getServletContext()); 063 } 064 065 public static Gravity start(ServletContext context) throws ServletException { 066 Gravity gravity = null; 067 068 synchronized (context) { 069 070 gravity = (Gravity)context.getAttribute(GRAVITY_KEY); 071 072 if (gravity == null) { 073 GraniteConfig graniteConfig = ServletGraniteConfig.loadConfig(context); 074 ServicesConfig servicesConfig = ServletServicesConfig.loadConfig(context); 075 076 GravityServiceConfigurator serviceConfigurator = (GravityServiceConfigurator)context.getAttribute(GraniteConfigListener.GRANITE_CONFIG_ATTRIBUTE); 077 if (serviceConfigurator != null) 078 serviceConfigurator.configureGravityServices(context); 079 080 GravityConfig gravityConfig = new GravityConfig(graniteConfig); 081 082 String gravityFactory = gravityConfig.getGravityFactory(); 083 try { 084 GravityFactory factory = TypeUtil.newInstance(gravityFactory, GravityFactory.class); 085 gravity = factory.newGravity(gravityConfig, servicesConfig, graniteConfig, GraniteConfigListener.getSharedContext(context)); 086 } 087 catch (Exception e) { 088 throw new ServletException("Could not create Gravity instance with factory: " + gravityFactory, e); 089 } 090 091 try { 092 gravity.start(); 093 context.setAttribute(GRAVITY_KEY, gravity); 094 095 if (context.getAttribute(GraniteConfigListener.GRANITE_CONFIG_PROVIDER_ATTRIBUTE) != null) 096 ((ConfigProvider)context.getAttribute(GraniteConfigListener.GRANITE_CONFIG_PROVIDER_ATTRIBUTE)).initGravity(gravity); 097 098 GraniteConfigListener.registerShutdownListener(context, gravity); 099 } 100 catch (Exception e) { 101 throw new ServletException("Gravity initialization error", e); 102 } 103 } 104 } 105 106 return gravity; 107 } 108 109 110 public static interface GravityServiceConfigurator { 111 112 public void configureGravityServices(ServletContext context) throws ServletException; 113 } 114 115 116 /** 117 * Reconfigure gravity with the new supplied configuration (after reloading granite-config.xml). 118 * <br><br> 119 * Only these configuration options are taken into account when reconfiguring Gravity: 120 * <ul> 121 * <li>channelIdleTimeoutMillis</li> 122 * <li>longPollingTimeout</li> 123 * <li>retryOnError</li> 124 * <li>maxMessagesQueuedPerChannel</li> 125 * <li>corePoolSize</li> 126 * <li>maximumPoolSize</li> 127 * <li>keepAliveTimeMillis</li> 128 * </ul> 129 * 130 * @param context the ServletContext where the gravity instance is registered. 131 * @param gravityConfig the new (reloaded) GravityConfig. 132 */ 133 public static void reconfigure(ServletContext context, GravityConfig gravityConfig) { 134 synchronized (context) { 135 Gravity gravity = getGravity(context); 136 gravity.reconfigure(gravityConfig, ServletGraniteConfig.getConfig(context)); 137 } 138 } 139 140 /** 141 * Returns a previously started Gravity instance. This method isn't synchronized and should be used in 142 * HttpServlet.doPost(...) methods only. 143 * 144 * @param context the ServletContext from which to retrieve the Gravity instance. 145 * @return the unique and started Gravity instance (or null if {@link #start(ServletConfig)} 146 * has never been called). 147 */ 148 public static Gravity getGravity(ServletContext context) { 149 return (Gravity)context.getAttribute(GRAVITY_KEY); 150 } 151 152}