1 /***
2 * Redistribution and use of this software and associated documentation
3 * ("Software"), with or without modification, are permitted provided
4 * that the following conditions are met:
5 *
6 * 1. Redistributions of source code must retain copyright
7 * statements and notices. Redistributions must also contain a
8 * copy of this document.
9 *
10 * 2. Redistributions in binary form must reproduce the
11 * above copyright notice, this list of conditions and the
12 * following disclaimer in the documentation and/or other
13 * materials provided with the distribution.
14 *
15 * 3. The name "Exolab" must not be used to endorse or promote
16 * products derived from this Software without prior written
17 * permission of Exoffice Technologies. For written permission,
18 * please contact info@exolab.org.
19 *
20 * 4. Products derived from this Software may not be called "Exolab"
21 * nor may "Exolab" appear in their names without prior written
22 * permission of Exoffice Technologies. Exolab is a registered
23 * trademark of Exoffice Technologies.
24 *
25 * 5. Due credit should be given to the Exolab Project
26 * (http://www.exolab.org/).
27 *
28 * THIS SOFTWARE IS PROVIDED BY EXOFFICE TECHNOLOGIES AND CONTRIBUTORS
29 * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
30 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
31 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
32 * EXOFFICE TECHNOLOGIES OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
33 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
35 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
37 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
39 * OF THE POSSIBILITY OF SUCH DAMAGE.
40 *
41 * Copyright 2000-2004 (C) Exoffice Technologies Inc. All Rights Reserved.
42 *
43 * $Id: JmsServer.java,v 1.48 2004/01/03 04:00:56 tanderson Exp $
44 *
45 * Date Author Changes
46 * 2/28/2000 jima Created
47 */
48 package org.exolab.jms.server;
49
50 import java.io.PrintStream;
51 import java.lang.reflect.Constructor;
52 import java.util.ArrayList;
53
54 import javax.naming.Context;
55 import javax.naming.NamingException;
56
57 import org.apache.commons.logging.Log;
58 import org.apache.commons.logging.LogFactory;
59 import org.apache.log4j.xml.DOMConfigurator;
60
61 import org.exolab.core.service.ServiceException;
62 import org.exolab.core.service.ServiceManager;
63 import org.exolab.core.util.RmiRegistryService;
64 import org.exolab.jms.authentication.AuthenticationMgr;
65 import org.exolab.jms.config.Configuration;
66 import org.exolab.jms.config.ConfigurationManager;
67 import org.exolab.jms.config.Connector;
68 import org.exolab.jms.config.ConnectorHelper;
69 import org.exolab.jms.config.ConnectorResource;
70 import org.exolab.jms.config.LoggerConfiguration;
71 import org.exolab.jms.config.types.SchemeType;
72 import org.exolab.jms.events.BasicEventManager;
73 import org.exolab.jms.gc.GarbageCollectionService;
74 import org.exolab.jms.jndi.JndiServerIfc;
75 import org.exolab.jms.lease.LeaseManager;
76 import org.exolab.jms.messagemgr.DestinationManager;
77 import org.exolab.jms.messagemgr.MessageMgr;
78 import org.exolab.jms.persistence.DatabaseService;
79 import org.exolab.jms.scheduler.Scheduler;
80 import org.exolab.jms.threads.ThreadPoolManager;
81 import org.exolab.jms.util.CommandLine;
82 import org.exolab.jms.util.Version;
83
84
85 /***
86 * This class contains the main line for instantiating the JMS Server. It
87 * dynamically detemrines, from the configuration information which of the
88 * servers to implement and then calls the init method on them.
89 *
90 * @version $Revision: 1.48 $ $Date: 2004/01/03 04:00:56 $
91 * @author <a href="mailto:jima@exoffice.com">Jim Alateras</a>
92 * @author <a href="mailto:tima@intalio.com">Tim Anderson</a>
93 * @see ConfigurationManager
94 */
95 public class JmsServer {
96
97 /***
98 * The service manager
99 */
100 protected ServiceManager _services = null;
101
102 /***
103 * The interfaces to this server. One interface is constructed for
104 * each configured connector.
105 */
106 private JmsServerIfc[] _interfaces = null;
107
108 /***
109 * The JNDI providers, when using embedded JNDI. One server is
110 * constructed for each configured connector.
111 */
112 private JndiServerIfc[] _jndiInterfaces = null;
113
114 /***
115 * The configuration of this server
116 */
117 private Configuration _config;
118
119 /***
120 * The logger
121 */
122 private static final Log _log = LogFactory.getLog(JmsServer.class);
123
124 /***
125 * Construct a new <code>JmsServer</code>
126 *
127 * @param config the server configuration
128 * @throws ServerException if the server cannot be created
129 */
130 public JmsServer(Configuration config) throws ServerException {
131 version();
132 ConfigurationManager.setConfig(config);
133 }
134
135
136 /***
137 * Construct a new <code>JmsServer</code>, configured from the specified
138 * configuration file.
139 *
140 * @param file configuration file name
141 * @throws ServerException if the server cannot be created
142 */
143 public JmsServer(String file) throws ServerException {
144 version();
145
146 try {
147 // initialise the configuration manager
148 ConfigurationManager.setConfig(file);
149 _config = ConfigurationManager.getConfig();
150 } catch (Exception exception) {
151 throw new FailedToCreateServerException(
152 "Failed to read configuration: " + file, exception);
153 }
154 }
155
156 /***
157 * Initialise the server
158 *
159 * @throws NamingException if administered objects cannot be bound in JNDI
160 * @throws ServerException if the server cannot be initialised
161 */
162 public void init() throws NamingException, ServerException {
163 // initialise the logger
164 LoggerConfiguration log = _config.getLoggerConfiguration();
165
166 // @todo - need to do this in main(), to allow pluggable log factories
167 // when embedding OpenJMS
168 DOMConfigurator.configure(log.getFile());
169
170 // initialise the service manager
171 _services = ServiceManager.instance();
172
173 // initialise the embedded JNDI server if required
174 if (_config.getServerConfiguration().getEmbeddedJNDI()) {
175 EmbeddedNameService.getInstance();
176 }
177
178 // create the embedded RMI registry, if it is configured
179 if (hasConnector(SchemeType.RMI) &&
180 _config.getRmiConfiguration().getEmbeddedRegistry()) {
181 createRegistry();
182 }
183
184 // initialise the services, and start them
185
186 try {
187 registerServices();
188 _services.startAll();
189 } catch (ServiceException exception) {
190 throw new ServerException("Failed to start services", exception);
191 }
192
193 // create and bind administered destinations
194 DestinationManager.instance().registerConfiguredAdministeredDestinations();
195
196 Context context = NamingHelper.getInitialContext(_config);
197
198 // create the server interfaces
199 initConnectors(context);
200
201 // create the JNDI provider interfaces if required
202 if (_config.getServerConfiguration().getEmbeddedJNDI()) {
203 initJNDIConnectors(context);
204 }
205 }
206
207 /***
208 * This is the main line for the JMS Server. It processes the command line
209 * argument, instantiates an instance of the server class and calls the
210 * init routine on it.
211 */
212 public static void main(String[] args) {
213 try {
214 CommandLine cmdline = new CommandLine(args);
215
216 boolean helpSet = cmdline.exists("help");
217 boolean versionSet = cmdline.exists("version");
218 boolean configSet = cmdline.exists("config");
219
220 if (helpSet) {
221 usage();
222 } else if (versionSet) {
223 version();
224 } else if (!configSet && args.length != 0) {
225 // invalid argument specified
226 usage();
227 } else {
228 String config = cmdline.value(
229 "config", getOpenJMSHome() + "/config/openjms.xml");
230 JmsServer server = new JmsServer(config);
231 server.init();
232 }
233 } catch (Exception exception) {
234 exception.printStackTrace();
235 // force termination of any threads
236 System.exit(-1);
237 }
238 }
239
240 public static void version() {
241 System.err.println(Version.TITLE + " " + Version.VERSION);
242 System.err.println(Version.COPYRIGHT);
243 System.err.println(Version.VENDOR_URL);
244 }
245
246 /***
247 * Print out information on running this sevice
248 */
249 protected static void usage() {
250 PrintStream out = System.out;
251
252 out.println("\n\n");
253 out.println("=====================================================");
254 out.println("Usage information for org.exolab.jms.server.JmsServer");
255 out.println("=====================================================");
256 out.println("\norg.exolab.jms.server.JmsServer");
257 out.println(" [-config <xml config file> | -version | -help]\n");
258 out.println("\t-config file name of xml-based config file\n");
259 out.println("\t-version displays OpenJMS version information\n");
260 out.println("\t-help displays this screen\n");
261 }
262
263 /***
264 * Initialise the services
265 */
266 protected void registerServices() throws ServiceException {
267 // add the thread pool manager
268 _services.add(ThreadPoolManager.instance().getName(),
269 ThreadPoolManager.instance());
270
271 // add the event manager
272 _services.add(BasicEventManager.instance().getName(),
273 BasicEventManager.instance());
274
275 // add the database service
276 _services.add(DatabaseService.instance().getName(),
277 DatabaseService.instance());
278
279 // add the scheduler
280 _services.add(Scheduler.createInstance().getName(),
281 Scheduler.instance());
282
283 // add the lease manager
284 _services.add(LeaseManager.instance().getName(),
285 LeaseManager.instance());
286
287 // add the transaction manager
288 //_services.add (TransactionService.instance().getName(),
289 // TransactionService.instance());
290
291 // add the garbage collection service
292 _services.add(GarbageCollectionService.instance().getName(),
293 GarbageCollectionService.instance());
294
295 // add the authentication manager
296 _services.add(AuthenticationMgr.createInstance().getName(),
297 AuthenticationMgr.instance());
298
299 // add the resource manager service
300 //_services.add(ResourceManager.instance().getName(),
301 // ResourceManager.instance());
302
303 // add the message manager
304 _services.add(MessageMgr.createInstance().getName(),
305 MessageMgr.instance());
306 }
307
308 /***
309 * Creates an interface to the server for each configured connector
310 *
311 * @param context the initial context
312 * @throws NamingException if administered objects cannot be bound in JNDI
313 * @throws ServerException if an interface can't be created
314 */
315 protected void initConnectors(Context context)
316 throws NamingException, ServerException {
317
318 Connector[] connectors = _config.getConnectors().getConnector();
319 _interfaces = new JmsServerIfc[connectors.length];
320
321 for (int i = 0; i < connectors.length; ++i) {
322 Connector connector = connectors[i];
323 _interfaces[i] = initConnector(connector, context);
324 }
325 }
326
327 /***
328 * Create an interface to the server for the specified connector
329 *
330 * @param connector the connector
331 * @param context the initial context
332 * @return the interface corresponding to <code>connector</code>
333 * @throws NamingException if administered objects cannot be bound in JNDI
334 * @throws ServerException if the interface can't be created
335 */
336 protected JmsServerIfc initConnector(Connector connector, Context context)
337 throws NamingException, ServerException {
338
339 _log.info("Creating server interface for the " + connector.getScheme()
340 + " connector");
341
342 JmsServerIfc server;
343 ConnectorResource resource = ConnectorHelper.getConnectorResource(
344 connector.getScheme());
345
346 String className = resource.getServer().getImplementationClass();
347 Class clazz;
348 try {
349 clazz = Class.forName(className);
350 } catch (ClassNotFoundException exception) {
351 throw new FailedToCreateServerException(
352 "Failed to load class " + className);
353 }
354
355 if (!JmsServerIfc.class.isAssignableFrom(clazz)) {
356 throw new FailedToCreateServerException(
357 "Class " + className + " does not implement JmsServerIfc");
358 }
359 try {
360 server = (JmsServerIfc) clazz.newInstance();
361 _log.debug("Created an instance of " + className
362 + " as a server interface");
363 } catch (Exception exception) {
364 throw new FailedToCreateServerException(
365 exception.getMessage(), exception);
366 }
367
368 // initialise the interface
369 server.init();
370
371 // bind any configured connection factories
372 server.bindConnectionFactories(context);
373
374 return server;
375 }
376
377 protected void createRegistry() throws ServerException {
378
379 int port = _config.getRmiConfiguration().getRegistryPort();
380 try {
381 RmiRegistryService service = new RmiRegistryService(port);
382 _services.add(service.getName(), service);
383 } catch (Exception exception) {
384 throw new FailedToCreateServerException(
385 "Failed to start the RMI registry", exception);
386 }
387 _log.info("Embedded RMI registry running on port " + port);
388 }
389
390 /***
391 * Creates a JNDI provider interface for each connector that supports it
392 *
393 * @param context the initial context
394 * @throws NamingException if a provider can't be initialised
395 * @throws ServerException if a provider can't be created
396 */
397 protected void initJNDIConnectors(Context context)
398 throws NamingException, ServerException {
399
400 Connector[] connectors = _config.getConnectors().getConnector();
401 ArrayList interfaces = new ArrayList();
402
403 for (int i = 0; i < connectors.length; ++i) {
404 Connector connector = connectors[i];
405 ConnectorResource resource = ConnectorHelper.getConnectorResource(
406 connector.getScheme());
407 if (resource.getJndi().getImplementationClass() != null) {
408 JndiServerIfc provider = initJNDIConnector(resource, context);
409 interfaces.add(provider);
410 }
411 }
412 _jndiInterfaces = (JndiServerIfc[]) interfaces.toArray(
413 new JndiServerIfc[0]);
414 }
415
416 /***
417 * Creates a JNDI provider interface for the specified connector
418 *
419 * @param connector the connector
420 * @param context the initial context
421 * @return the JNDI provider interface
422 * @throws NamingException if the provider can't be initialised
423 * @throws ServerException if the provider can't be created
424 */
425 protected JndiServerIfc initJNDIConnector(
426 ConnectorResource connector, Context context)
427 throws NamingException, ServerException {
428
429 _log.info("Creating JNDI interface for the " + connector.getScheme()
430 + " connector");
431
432 JndiServerIfc result;
433 String className = connector.getJndi().getImplementationClass();
434 Class clazz;
435 try {
436 clazz = Class.forName(className);
437 } catch (ClassNotFoundException exception) {
438 throw new FailedToCreateServerException(
439 "Failed to load class " + className);
440 }
441 if (!JndiServerIfc.class.isAssignableFrom(clazz)) {
442 throw new FailedToCreateServerException(
443 "Class " + className + " does not implement JndiServerIfc");
444 }
445 try {
446 Constructor constructor = clazz.getDeclaredConstructor(
447 new Class[]{Context.class});
448 result = (JndiServerIfc) constructor.newInstance(
449 new Object[]{context});
450 result.init();
451 _log.debug("Created an instance of " + className
452 + " as a JNDI provider interface");
453 } catch (Exception exception) {
454 throw new FailedToCreateServerException(
455 exception.getMessage(), exception);
456 }
457 return result;
458 }
459
460 /***
461 * Determines if the configuration has the specified connector
462 *
463 * @param scheme the connector scheme
464 * @return <code>true<code> if the configuration has a connector
465 * corresponding to <code>scheme</code>
466 */
467 private boolean hasConnector(SchemeType scheme) {
468 boolean result = false;
469 Connector[] connectors = _config.getConnectors().getConnector();
470 for (int i = 0; i < connectors.length; ++i) {
471 if (connectors[i].getScheme().equals(scheme)) {
472 result = true;
473 break;
474 }
475 }
476 return result;
477 }
478
479 /***
480 * Returns the value of the openjms.home environment variable
481 */
482 private static String getOpenJMSHome() {
483 return System.getProperty("openjms.home",
484 System.getProperty("user.dir"));
485 }
486
487 } //-- JmsServer
This page was automatically generated by Maven