1 | // jademx - JADE management using JMX |
2 | // Copyright 2005 Caboodle Networks, Inc. |
3 | // |
4 | // This library is free software; you can redistribute it and/or |
5 | // modify it under the terms of the GNU Lesser General Public |
6 | // License as published by the Free Software Foundation; either |
7 | // version 2.1 of the License, or (at your option) any later version. |
8 | // |
9 | // This library is distributed in the hope that it will be useful, |
10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | // Lesser General Public License for more details. |
13 | // |
14 | // You should have received a copy of the GNU Lesser General Public |
15 | // License along with this library; if not, write to the Free Software |
16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
17 | package jade.jademx.server; |
18 | |
19 | import java.util.Enumeration; |
20 | import java.util.Hashtable; |
21 | import java.util.logging.Level; |
22 | import java.util.logging.Logger; |
23 | |
24 | //import jade.util.Logger; |
25 | |
26 | import javax.servlet.ServletContext; |
27 | import javax.servlet.ServletContextEvent; |
28 | import javax.servlet.ServletContextListener; |
29 | |
30 | /** |
31 | * Let JADE be installed using JMX in servlet context, e.g. under J2EE as a WAR. |
32 | * The class is then described as a <code>listener</code> in the |
33 | * <code>web.xml</code> file. |
34 | * <p>The following context parameters are understood: |
35 | * <table> |
36 | * <tr><th>name</th><th>needed</th></tr> |
37 | * <tr><td><a href="#PARAMETER_JADEMX_SERVER_CLASS_NAME"> |
38 | * <code>{@value #PARAMETER_JADEMX_SERVER_CLASS_NAME}</code></a></td> |
39 | * <td>required</td></tr> |
40 | * <tr><td><a href="#PARAMETER_JADE_SERVICE_JNDI_NAME"> |
41 | * <code>{@value #PARAMETER_JADE_SERVICE_JNDI_NAME}</code></a></td> |
42 | * <td>optional</td></tr> |
43 | * <tr><td><a href="#PARAMETER_JADE_SERVICE_CONFIG_DOC_URL"> |
44 | * <code>{@value #PARAMETER_JADE_SERVICE_CONFIG_DOC_URL}</code></a></td> |
45 | * <td>optional</td></tr> |
46 | * <tr><td><a href="#PARAMETER_JADE_SERVICE_CONFIG_DOC_RESOURCE"> |
47 | * <code>{@value #PARAMETER_JADE_SERVICE_CONFIG_DOC_RESOURCE}</code></a></td> |
48 | * <td>optional</td></tr> |
49 | * <tr><td><a href="#PARAMETER_JADE_SERVICE_OBJECT_NAME_DOMAIN"> |
50 | * <code>{@value #PARAMETER_JADE_SERVICE_OBJECT_NAME_DOMAIN}</code></a></td> |
51 | * <td>optional</td></tr> |
52 | * </table> |
53 | * </p> |
54 | * @author David Bernstein, <a href="http://www.caboodlenetworks.com" |
55 | * >Caboodle Networks, Inc.</a> |
56 | */ |
57 | public class JadeServletContextListener implements ServletContextListener { |
58 | |
59 | // CONTEXT PARAMETER NAMES |
60 | |
61 | /** prefix for <code>PARAMETER_JADE_SERVICE_</code> parameters */ |
62 | private final static String JADE_SERVICE_PARM_PREFIX = "jade.service."; |
63 | |
64 | /** prefix for JNDI environment parameters */ |
65 | private final static String JNDI_ENV_PARM_PREFIX = |
66 | JADE_SERVICE_PARM_PREFIX + "jndi.env."; |
67 | |
68 | /** fragment for configuration document name parameters */ |
69 | private final static String CONFIG_DOC_PARM_FRAGMENT = "config.doc."; |
70 | |
71 | /** |
72 | * Name of <b>required</b> context paramter with name of class implementing |
73 | * <code>JadeMXServer</code> to instantiate |
74 | * with no-argument constructor retrieving MBeanServer. |
75 | * Value: <code>{@value #PARAMETER_JADEMX_SERVER_CLASS_NAME}</code>. |
76 | */ |
77 | public final static String PARAMETER_JADEMX_SERVER_CLASS_NAME = |
78 | "jademx.server.class.name"; |
79 | |
80 | /** |
81 | * Name of <b>optional</b> context parameter with JNDI name to register |
82 | * JadeService as. |
83 | * Value: <code>{@value #PARAMETER_JADE_SERVICE_JNDI_NAME}</code>. |
84 | * Setting this to <code>null</code> will turn off JNDI registration. |
85 | */ |
86 | public final static String PARAMETER_JADE_SERVICE_JNDI_NAME = |
87 | JADE_SERVICE_PARM_PREFIX + "jndi.name"; |
88 | |
89 | /** |
90 | * Name of <b>optional</b> context parameter with URL to find |
91 | * JadeService configuration doc. |
92 | * Value: <code>{@value #PARAMETER_JADE_SERVICE_CONFIG_DOC_URL}</code>. |
93 | * Mutually exclusive with |
94 | * {@link #PARAMETER_JADE_SERVICE_CONFIG_DOC_RESOURCE}. |
95 | */ |
96 | public final static String PARAMETER_JADE_SERVICE_CONFIG_DOC_URL = |
97 | JADE_SERVICE_PARM_PREFIX + CONFIG_DOC_PARM_FRAGMENT + "url"; |
98 | |
99 | /** |
100 | * Name of <b>optional</b> context parameter with resource to find |
101 | * JadeService configuration doc. |
102 | * Value: <code>{@value #PARAMETER_JADE_SERVICE_CONFIG_DOC_RESOURCE}</code>. |
103 | * Mutually exclusive with |
104 | * {@link #PARAMETER_JADE_SERVICE_CONFIG_DOC_URL}. |
105 | */ |
106 | public final static String PARAMETER_JADE_SERVICE_CONFIG_DOC_RESOURCE = |
107 | JADE_SERVICE_PARM_PREFIX + CONFIG_DOC_PARM_FRAGMENT + "resource"; |
108 | |
109 | /** |
110 | * Name of <b>optional</b> context parameter with JMX ObjectName |
111 | * domain to use. |
112 | * Value: <code>{@value #PARAMETER_JADE_SERVICE_OBJECT_NAME_DOMAIN}</code>. |
113 | */ |
114 | public final static String PARAMETER_JADE_SERVICE_OBJECT_NAME_DOMAIN = |
115 | JADE_SERVICE_PARM_PREFIX + "object.name.domain"; |
116 | |
117 | /** local copy of service implementation */ |
118 | private JadeService service; |
119 | |
120 | /** my logger */ |
121 | private final Logger logger = |
122 | Logger.getLogger(JadeServletContextListener.class.getName()); |
123 | // Logger.getMyLogger(JadeServletContextListener.class.getName()); |
124 | |
125 | |
126 | // use the default constructor |
127 | |
128 | /* (non-Javadoc) |
129 | * @see javax.servlet.ServletContextListener#contextInitialized( |
130 | * javax.servlet.ServletContextEvent) |
131 | */ |
132 | public void contextInitialized( ServletContextEvent servletContextEvent ) { |
133 | |
134 | if ( logger.isLoggable( Level.FINE ) ) { |
135 | //System.getProperties().list( System.out );//this version truncates |
136 | logger.log( Level.FINE, "system properties:"); |
137 | java.util.Properties sysProps = System.getProperties(); |
138 | java.util.Enumeration sysPropNames = sysProps.propertyNames(); |
139 | while ( sysPropNames.hasMoreElements() ) { |
140 | String sysPropName = (String)sysPropNames.nextElement(); |
141 | logger.log( Level.FINE, sysPropName + "=" + |
142 | sysProps.getProperty( sysPropName ) ); |
143 | } |
144 | } |
145 | |
146 | try { |
147 | |
148 | try { |
149 | // construct the service instance, which will perform the work |
150 | // and register self as an MBean and register self with JNDI |
151 | service = new JadeService(); |
152 | } |
153 | catch ( Exception e ) { |
154 | e.printStackTrace(); |
155 | throw new RuntimeException( |
156 | "exception constructing JadeService", e ); |
157 | } |
158 | |
159 | |
160 | try { |
161 | |
162 | // servlet context lets us look at our environment |
163 | ServletContext servletContext = |
164 | servletContextEvent.getServletContext(); |
165 | |
166 | // JadeMXServer class name is required context parameter |
167 | String parmJadeMXServerClassName = |
168 | servletContext.getInitParameter( |
169 | PARAMETER_JADEMX_SERVER_CLASS_NAME ); |
170 | if ( null == parmJadeMXServerClassName ) { |
171 | throw new RuntimeException("required context parameter \""+ |
172 | PARAMETER_JADEMX_SERVER_CLASS_NAME+ |
173 | "\" not specified"); |
174 | } |
175 | service.setJadeMXServerClassName( parmJadeMXServerClassName ); |
176 | |
177 | // check for specification of JNDI name for JADE service |
178 | String parmJadeServiceJndiName = |
179 | servletContext.getInitParameter( |
180 | PARAMETER_JADE_SERVICE_JNDI_NAME ); |
181 | if ( null != parmJadeServiceJndiName ) { |
182 | service.setJndiName( parmJadeServiceJndiName ); |
183 | } |
184 | |
185 | // check for specification of config doc as url |
186 | String parmJadeServiceConfigDocUrl = |
187 | servletContext.getInitParameter( |
188 | PARAMETER_JADE_SERVICE_CONFIG_DOC_URL ); |
189 | if ( null != parmJadeServiceConfigDocUrl ) { |
190 | service.setConfigDocUrl( parmJadeServiceConfigDocUrl ); |
191 | } |
192 | |
193 | // check for specification of config doc as resource |
194 | String parmJadeServiceConfigDocResource = |
195 | servletContext.getInitParameter( |
196 | PARAMETER_JADE_SERVICE_CONFIG_DOC_RESOURCE ); |
197 | if ( null != parmJadeServiceConfigDocResource ) { |
198 | service.setConfigDocResource( |
199 | parmJadeServiceConfigDocResource); |
200 | } |
201 | |
202 | // check for specification of ObjectName domain |
203 | String parmJadeServiceObjectNameDomain = |
204 | servletContext.getInitParameter( |
205 | PARAMETER_JADE_SERVICE_OBJECT_NAME_DOMAIN ); |
206 | if ( null != parmJadeServiceObjectNameDomain ) { |
207 | if ( "null".equals( parmJadeServiceObjectNameDomain ) ) { |
208 | // this can be used to turn off registration with JNDI |
209 | parmJadeServiceObjectNameDomain = null; |
210 | } |
211 | service.setObjectNameDomain( |
212 | parmJadeServiceObjectNameDomain ); |
213 | } |
214 | |
215 | // check for JNDI environment InitialContext properties |
216 | Hashtable contextProps = new Hashtable(); |
217 | Enumeration initParmNamesE = |
218 | servletContext.getInitParameterNames(); |
219 | while ( initParmNamesE.hasMoreElements() ) { |
220 | String parmName = (String)initParmNamesE.nextElement(); |
221 | if ( parmName.startsWith( JNDI_ENV_PARM_PREFIX ) ) { |
222 | String envPropName = |
223 | parmName.substring( JNDI_ENV_PARM_PREFIX.length() ); |
224 | String envPropVal = |
225 | servletContext.getInitParameter( parmName ); |
226 | if ( logger.isLoggable( Level.FINE ) ) { |
227 | logger.log( Level.FINE, |
228 | "JNDI env prop:"+envPropName+"="+envPropVal); |
229 | } |
230 | contextProps.put( envPropName, envPropVal ); |
231 | } |
232 | } |
233 | service.setJndiInitialContextProperties( contextProps ); |
234 | |
235 | //logger.log(Logger.INFO, "configured "+service ); |
236 | |
237 | } |
238 | catch ( Exception e ) { |
239 | e.printStackTrace(); |
240 | throw new RuntimeException( |
241 | "exception configuring JadeService "+service, e ); |
242 | } |
243 | |
244 | // register the JadeServiceMBean with the MBeanServer |
245 | JadeMXServer jadeMXServer = null; |
246 | try { |
247 | jadeMXServer = (JadeMXServer) |
248 | Class.forName(service.getJadeMXServerClassName()).newInstance(); |
249 | } |
250 | catch ( Exception e ) { |
251 | e.printStackTrace(); |
252 | throw new RuntimeException( |
253 | "exception instantiating JadeMXServer class"+ |
254 | service.getJadeMXServerClassName(), e ); |
255 | } |
256 | try { |
257 | jadeMXServer.getMBeanServer().registerMBean( service, null ); |
258 | } |
259 | catch ( Exception e ) { |
260 | e.printStackTrace(); |
261 | throw new RuntimeException( |
262 | "exception registering JadeMXServer "+jadeMXServer+ |
263 | " with MBeanServer", e ); |
264 | } |
265 | |
266 | // create the service |
267 | try { |
268 | service.create(); |
269 | } |
270 | catch ( Exception e ) { |
271 | e.printStackTrace(); |
272 | throw new RuntimeException("exception creating "+service, e ); |
273 | } |
274 | |
275 | // start the service |
276 | try { |
277 | service.start(); |
278 | } |
279 | catch ( Exception e ) { |
280 | e.printStackTrace(); |
281 | throw new RuntimeException("exception starting "+service, e ); |
282 | } |
283 | |
284 | } |
285 | catch ( Throwable t ) { |
286 | logger.log( Level.SEVERE, "caught throwable", t); |
287 | System.err.println( |
288 | "JadeServletContextListener.contextInitialized():"+ |
289 | "caught throwable: "); |
290 | t.printStackTrace(); |
291 | throw new RuntimeException( |
292 | "JadeServletContextListener.contextInitialized():"+ |
293 | "caught throwable: ", t ); |
294 | } |
295 | |
296 | } |
297 | |
298 | |
299 | /* (non-Javadoc) |
300 | * @see javax.servlet.ServletContextListener#contextDestroyed( |
301 | * javax.servlet.ServletContextEvent) |
302 | */ |
303 | public void contextDestroyed( ServletContextEvent servletContextEvent ) { |
304 | logger.log( Level.INFO, "destroying servlet context..."); |
305 | // stop the service |
306 | service.stop(); |
307 | // unregister from MBeanServer |
308 | service.unregister(); |
309 | // destroy the service |
310 | service.destroy(); |
311 | } |
312 | |
313 | } |