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 */
022 package org.granite.gravity;
023
024 import javax.servlet.ServletConfig;
025 import javax.servlet.ServletContext;
026 import javax.servlet.ServletException;
027 import javax.servlet.http.HttpServlet;
028
029 import org.granite.config.ConfigProvider;
030 import org.granite.config.GraniteConfig;
031 import org.granite.config.GraniteConfigListener;
032 import org.granite.config.ServletGraniteConfig;
033 import org.granite.config.flex.ServicesConfig;
034 import org.granite.config.flex.ServletServicesConfig;
035 import org.granite.util.TypeUtil;
036
037 /**
038 * @author Franck WOLFF
039 */
040 public 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 }