Source code: org/mule/MuleManager.java
1 /*
2 * $Header: /cvsroot/mule/mule/src/java/org/mule/MuleManager.java,v 1.11 2003/10/20 21:19:17 rossmason Exp $
3 * $Revision: 1.11 $
4 * $Date: 2003/10/20 21:19:17 $
5 * ------------------------------------------------------------------------------------------------------
6 *
7 * Copyright (c) Cubis Limited. All rights reserved.
8 * http://www.cubis.co.uk
9 *
10 * The software in this package is published under the terms of the BSD
11 * style license a copy of which has been included with this distribution in
12 * the LICENSE.txt file.
13 *
14 */
15 package org.mule;
16
17 import java.io.IOException;
18 import java.net.URL;
19 import java.util.Date;
20 import java.util.HashMap;
21 import java.util.Iterator;
22 import java.util.Map;
23
24 import org.apache.commons.logging.Log;
25 import org.apache.commons.logging.LogFactory;
26 import org.mule.digester.MuleDigester;
27 import org.mule.umo.UMODescriptor;
28 import org.mule.umo.UMOEvent;
29 import org.mule.umo.UMOException;
30 import org.mule.umo.UMOProviderDescriptor;
31 import org.mule.umo.UMOSession;
32 import org.mule.umo.impl.MuleProviderDescriptor;
33 import org.mule.umo.impl.MuleSessionManager;
34 import org.mule.umo.impl.ProviderList;
35 import org.mule.umo.provider.UMOConnector;
36 import org.mule.umo.transformer.UMOTransformer;
37 import org.xml.sax.SAXException;
38
39 /**
40 * <p><code>MuleManager</code> maintains and provides services for a Mule instance.
41 * All mules and tranformations are registered in the MuleManager. The Transaction
42 * Manager and performance metric helpers is also accessible from here.
43 * The developer can use the Mulemanager to stop start or pause all or any specific mules
44 * in the system.
45 *
46 * @author <a href="mailto:ross.mason@cubis.co.uk">Ross Mason</a>
47 * @version $Revision: 1.2 $
48 */
49
50 public class MuleManager implements MuleConstants
51 {
52
53 /** singleton instance */
54 private static MuleManager instance = null;
55
56 /** holds a reference to the session manager instance */
57 private MuleSessionManager sessionManager = null;
58
59 /** Default configuration */
60 private MuleConfiguration config = new MuleConfiguration();
61
62 /** Connectors registry */
63 private Map connectors = new HashMap();
64
65 /** Endpoints registry */
66 private Map endpoints = new HashMap();
67
68 /** Holds any environment properties set in the config */
69 private Map props = new HashMap();
70
71 /** Holds a list of global providers accessible to any client code */
72 private ProviderList providers = new ProviderList();
73
74 // /** The transaction Manager to use for global transactions */
75 // private TransactionManager transactionManager = null;
76
77 /** Collection for transformers registered in this session */
78 private HashMap transformers = new HashMap();
79
80 /** True once the Mule Manager is initialised */
81 private static boolean initialised = false;
82
83 /** Holds a reference to the deamon running the Manager if any */
84 private static MuleServer server = null;
85
86 /** logger used by this class */
87 private static transient Log log = LogFactory.getLog(MuleManager.class);
88
89 /** Default Constructor */
90 private MuleManager()
91 {
92 sessionManager = MuleSessionManager.getInstance();
93 }
94
95 /** A helper method to explicitly configure the CacheManager singleton
96 * from a given XML deployment configuration document
97 */
98 public static void configure(String xmlURL) throws IOException, SAXException
99 {
100 load(xmlURL);
101 }
102
103 /** A helper method to explicitly configure the CacheManager singleton
104 * from a given XML deployment configuration document
105 */
106 public static void configure(String xmlURL, MuleServer muleServer) throws IOException, SAXException
107 {
108 server = muleServer;
109 configure(xmlURL);
110 }
111
112 /** Factory method to create the singleton MuleManager instance */
113 protected static MuleManager createInstance()
114 {
115 String config = null;
116 try
117 {
118 config = System.getProperty("org.mule.config");
119 }
120 catch (Exception e)
121 {
122 }
123 try
124 {
125 if (config == null)
126 {
127 URL url = MuleManager.class.getClassLoader().getResource("mule-config.xml");
128 if (url != null)
129 {
130 config = url.toString();
131 }
132 else
133 {
134 log.warn("No mule-config.xml configuration document found on the CLASSPATH.");
135 }
136 }
137 if (config != null)
138 {
139 return load(config);
140
141 }
142 }
143 catch (Exception e)
144 {
145 log.error("Could not load Mule configuration from mule-config.xml", e);
146 }
147 return new MuleManager();
148 }
149
150 /**
151 * Getter method for the current singleton MuleManager
152 *
153 * @return the current singleton MuleManager
154 */
155 public synchronized static MuleManager getInstance()
156 {
157 if (instance == null)
158 {
159 //instance = createInstance();
160 instance = new MuleManager();
161 }
162 return instance;
163 }
164
165 /**
166 * A helper method to load the MuleManager
167 * from a given XML deployment configuration document
168 *
169 * @param url the url String location of the mule-config.xml
170 * @return the MuleManager instance
171 * @throws IOException is thrown if there is a problem loading the url
172 * @throws SAXException is thrown if there is a problem with the syntax of the
173 * config file
174 */
175 public static MuleManager load(String url) throws IOException, SAXException
176 {
177 MuleDigester digester = new MuleDigester();
178 initialised = false;
179 instance = null;
180 instance = (MuleManager) digester.parse(url);
181 initialised = true;
182 return instance;
183 }
184
185 // Implementation methods
186 //-------------------------------------------------------------------------
187
188 /**
189 * Destroys the MuleManager and all resources it maintains
190 */
191 public void destroy() throws UMOException
192 {
193 destroyConnectors();
194 sessionManager.destroy();
195 transformers = null;
196 providers = null;
197 endpoints = null;
198 props = null;
199 initialised = false;
200 instance = null;
201 }
202
203 /**
204 * Destroys all connectors
205 *
206 */
207 private void destroyConnectors()
208 {
209 UMOConnector temp;
210 for (Iterator i = connectors.values().iterator(); i.hasNext();)
211 {
212 temp = (UMOConnector) i.next();
213 try
214 {
215 temp.shutdown();
216 }
217 catch (Exception e)
218 {
219 log.error("Exception while shutting down connector: " + temp.getName() + ". Exception was " + e);
220 }
221 log.info("UMOConnector " + temp.toString() + " has been destroyed successfully");
222 }
223 connectors = null;
224 }
225
226 /**
227 *
228 * @return the MuleConfiguration for this MuleManager. This object is immutable
229 * once the manager has initialised.
230 */
231 public MuleConfiguration getConfiguration()
232 {
233 return config;
234 }
235
236 /**
237 * Getter for the envionment parameters declared in the nule-config.xml
238 * @param key the propery name
239 * @return the property value
240 */
241 public Object getProperty(Object key)
242 {
243 return props.get(key);
244 }
245
246 /**
247 *
248 * @return an Iterator of all environment property names
249 */
250 public Iterator getPropertyNames()
251 {
252 return props.keySet().iterator();
253 }
254
255 // /**
256 // *
257 // * @return the transaction Manager configured on the Mule Manager
258 // */
259 // public TransactionManager getTransactionManager()
260 // {
261 // return transactionManager;
262 // }
263
264 /**
265 *
266 * @param name the name of the Mule UMO to check for
267 * @return true if a Mule of the given name has been registered
268 */
269 public boolean isMuleRegistered(String name)
270 {
271 try
272 {
273 return getSession(name) != null;
274 }
275 catch (UMOException e)
276 {
277 log.warn("Failed to check Mule was registered: " + e);
278 return false;
279 }
280 }
281
282 /**
283 *
284 * @param logicalName the name of the connector to retrieve
285 * @return the connector instnace if it exists
286 * @throws MuleException if the UMOConnector is not found
287 */
288 public UMOConnector lookupConnector(String logicalName) throws MuleException
289 {
290 UMOConnector c = (UMOConnector) connectors.get(logicalName);
291 if (c == null)
292 {
293 throw new MuleException("No connector could be found named: " + logicalName);
294 }
295 return c;
296 }
297
298 /**
299 *
300 * @param logicalName the logical mapping name for an endpoint i.e.
301 * rather than specifing an endpoint to be someone@my.com you can supply
302 * a more descriptive name such as <i>The System Administrator</i>
303 * @return the actual endpoint value or null if it is not found
304 */
305 public String lookupEndpoint(String logicalName)
306 {
307 return (String) endpoints.get(logicalName);
308 }
309
310 /**
311 * Getter for a global provider. Any providers returned from this method
312 * will be read-only as they may be shared by other components. To change
313 * any details on the provider you must clone it first calling it's clone() method
314 * @param logicalName the name of the provider
315 * @return the <code>UMOProviderDescriptor</code> or null if it doesn't exist
316 */
317 public MuleProviderDescriptor lookupProvider(String logicalName)
318 {
319 return (MuleProviderDescriptor) providers.get(logicalName);
320 }
321
322 //TODO doc
323 public void dispatch(String muleName, UMOEvent event) throws UMOException
324 {
325 UMOSession session = sessionManager.getSession(muleName);
326 if (session == null)
327 {
328 throw new MuleException("Failed to find mule with name: " + muleName);
329 }
330 session.dispatchEvent(event);
331 }
332
333 /**
334 * Getter method for a Transformer.
335 * @param name the name of the transformer
336 * @return the Transformer instance if found, otherwise null
337 */
338 public UMOTransformer lookupTransformer(String name)
339 {
340 return (UMOTransformer) transformers.get(name);
341 }
342
343 /**
344 * Registers a <code>UMOConnector</code> with the <code>MuleManager</code>.
345 * @param connector the <code>UMOConnector</code> to register
346 */
347 public void registerConnector(UMOConnector connector)
348 {
349 connectors.put(connector.getName(), connector);
350 }
351
352 /**
353 * Registers an endpoint with a logical name
354 * @param logicalName the name of the endpoint
355 * @param endpoint the physical endpoint value
356 */
357 public void registerEndpoint(String logicalName, String endpoint)
358 {
359 endpoints.put(logicalName, endpoint);
360 }
361
362 /**
363 * Registers a <code>UMODescriptor</code> with the <code>MuleManager</code>.
364 * The manager will take care of creating the Mule UMO and, it's session and proxies.
365 * @param muleDescriptor the <code>UMODescriptor</code> to register
366 */
367 public void registerMule(UMODescriptor muleDescriptor) throws UMOException
368 {
369 if (muleDescriptor == null)
370 {
371 throw new MuleException("Mule UMO to register was null");
372 }
373 //TODO Validate provider setting behaviour against documented behaviour
374
375 //UniversalMessageObject muleUMO = descriptor.getFactory().create(descriptor);
376
377 // if (config != null && config.isSynchronous() &&
378 // !(muleUMO instanceof UMOSyncChainSupport)) {
379 // throw new MuleException("All Mules must have synchronous support when running synchronous");
380 // }
381 UMOSession session = sessionManager.registerSession(muleDescriptor);
382 UMOProviderDescriptor provider = null;
383 String name = null;
384 for (Iterator i = muleDescriptor.getProviders().getReceiverNames(); i.hasNext();)
385 {
386 name = (String) i.next();
387 provider = muleDescriptor.getProviders().getReceiveProvider(name);
388 try
389 {
390 provider.getConnector().registerListener(session, provider);
391 }
392 catch (Exception e)
393 {
394 throw new UMOException(
395 "Failed to register Mule UMO: " + muleDescriptor.getName() + " as a listener: " + e,
396 e);
397 }
398 }
399
400 log.debug("Added Mule UMO: " + muleDescriptor.getName());
401
402 }
403
404 /**
405 * Registers a shared/global provider with the <code>MuleManager</code>.
406 * @param provider the <code>UMOProviderDescriptor</code> to register.
407 */
408 public void registerProvider(MuleProviderDescriptor provider)
409 {
410 providers.add(provider, true);
411 }
412
413 /**
414 * Registers a transformer with the <code>MuleManager</code>.
415 * @param transformer the <code>UMOTransformer</code> to register.
416 */
417 public void registerTransformer(UMOTransformer transformer)
418 {
419 transformers.put(transformer.getName(), transformer);
420 }
421
422 /**
423 * Sets the configuration for the <code>MuleManager</code>.
424 * @param config the configuration object
425 * @throws IllegalAccessError if the <code>MuleManager</code> has already been
426 * initialised.
427 */
428 public void setConfiguration(MuleConfiguration config)
429 {
430 if (initialised)
431 {
432 throw new IllegalAccessError("Once initialised this property is read-only");
433 }
434 else
435 {
436 this.config = config;
437 }
438 }
439
440 /**
441 * Sets an Mule environment parameter in the <code>MuleManager</code>.
442 * @param key the parameter name
443 * @param value the parameter value
444 */
445 public void setProperty(Object key, Object value)
446 {
447 props.put(key, value);
448 }
449
450 // /**
451 // * Sests the XA transaction manager on the <code>MuleManager</code>.
452 // * @param newManager the <code>TransactionManager</code> to use.
453 // * @throws MuleException if the current transaction manager is not null and it's
454 // * state is currently volatile
455 // * NOTE: XA transactions are currently not supported
456 // */
457 // protected void setTransactionManager(TransactionManager newManager) throws MuleException
458 // {
459 // try
460 // {
461 // if (transactionManager != null
462 // && (transactionManager.getStatus() != Status.STATUS_NO_TRANSACTION
463 // || transactionManager.getStatus() != Status.STATUS_COMMITTED
464 // || transactionManager.getStatus() != Status.STATUS_ROLLEDBACK))
465 // {
466 // throw new MuleException("Cannot set Transaction manager the current is in a transaction");
467 // } else
468 // if (transactionManager != null)
469 // {
470 // log.warn("Replacing current transaction manager " + transactionManager.getClass().getName());
471 // }
472 // transactionManager = newManager;
473 //
474 // log.debug("Transaction manager is set to " + transactionManager.getClass().getName());
475 // } catch (SystemException e)
476 // {
477 // log.error("Failed to get status of current transaction Manager: " + e);
478 // throw new MuleException("Failed to get status of current transaction Manager", e);
479 // }
480 // }
481
482 /**
483 * Start the <code>MuleManager</code>. This will start the connectors and sessions.
484 * @throws UMOException if the the connectors or sessions fail to start
485 */
486 public void start() throws UMOException
487 {
488 sessionManager.start();
489 startConnectors();
490 }
491
492 /**
493 * Starts the connectors
494 * @throws MuleException if the connectors fail to start
495 */
496 private void startConnectors() throws MuleException
497 {
498 UMOConnector temp;
499 for (Iterator i = connectors.values().iterator(); i.hasNext();)
500 {
501 temp = (UMOConnector) i.next();
502 try
503 {
504 temp.start();
505 }
506 catch (Exception e)
507 {
508 throw new MuleException(
509 "Exception occurred while shutting down connector: " + temp.getName() + ". Exception was " + e,
510 e);
511 }
512 log.info("UMOConnector " + temp.toString() + " has been started successfully");
513 }
514 }
515
516 /**
517 * Starts a single Mule. This can be useful when stopping and starting some
518 * Mule UMOs while letting others continue
519 * @param name the name of the Mule UMO to start
520 * @throws UMOException if the MuleUMO is not registered
521 */
522 public void startMule(String name) throws UMOException
523 {
524 Object obj = sessionManager.getSession(name);
525 if (obj == null)
526 {
527 throw new MuleException("Cannot find mule " + name);
528 }
529 else
530 {
531 ((UMOSession) obj).start();
532 log.info("Mule " + obj.toString() + " has been started successfully");
533 }
534 }
535
536 /**
537 * Stops the <code>MuleManager</code> which stops all sessions and connectors
538 * @throws UMOException if either any of the sessions or connectors fail to stop
539 */
540 public void stop() throws UMOException
541 {
542 log.debug("Stopping connectors...");
543 stopConnectors();
544 log.debug("Stopping sessions...");
545 sessionManager.stop();
546 }
547
548 /**
549 * Stops the connectors
550 * @throws MuleException if any of the connectors fail to stop
551 */
552 private void stopConnectors() throws MuleException
553 {
554 UMOConnector temp;
555 for (Iterator i = connectors.values().iterator(); i.hasNext();)
556 {
557 temp = (UMOConnector) i.next();
558 try
559 {
560 temp.stop();
561 }
562 catch (Exception e)
563 {
564 throw new MuleException(
565 "Exception occurred while stopping connector: " + temp.getName() + ". Exception was " + e,
566 e);
567 }
568 log.info("UMOConnector " + temp.toString() + " has been stopped successfully");
569 }
570 }
571
572 /**
573 * Stops a single Mule. This can be useful when stopping and starting some
574 * Mule UMOs while letting others continue.
575 * @param name the name of the Mule UMO to stop
576 * @throws UMOException if the MuleUMO is not registered
577 */
578 public void stopMule(String name) throws UMOException
579 {
580 Object obj = sessionManager.getSession(name);
581 if (obj == null)
582 {
583 throw new MuleException("Cannot find mule " + name);
584 }
585 else
586 {
587 ((UMOSession) obj).stop();
588 log.info("mule " + name + " has been stopped successfully");
589 }
590 }
591
592 /**
593 * If the <code>MuleManager</code> was started from the <code>MuleServer</code>
594 * daemon then this will be called by the Server
595 * @param server a reference to the <code>MuleServer</code>.
596 */
597 void setServer(MuleServer server)
598 {
599 MuleManager.server = server;
600 }
601
602 /**
603 * Shuts down the whole server tring to shut down all resources cleanly on the way
604 * @param e an exception that caused the <code>shutdown()</code> method
605 * to be called. If e is null the shutdown message will just display a time when
606 * the server was shutdown. Otherwise the exception information will also be displayed.
607 */
608 public void shutdown(Throwable e)
609 {
610
611 try
612 {
613 destroy();
614 }
615 catch (UMOException e1)
616 {
617 log.fatal("Exception caught while destroying the Server: " + e);
618 }
619
620 if (server != null)
621 {
622 if (e != null)
623 {
624 server.shutdown(e);
625 }
626 else
627 {
628 server.shutdown();
629 }
630 }
631 else
632 {
633 if (e != null)
634 {
635 System.out.println("*************************************************************************");
636 System.out.println("Mule is shutting down due to exception: " + e.getMessage());
637 System.out.println("Shutdown time is: " + new Date().toString());
638 System.out.println("*************************************************************************");
639 }
640 else
641 {
642 System.out.println("*************************************************************************");
643 System.out.println("Mule is shutting down due to normal shutdown request.");
644 System.out.println("Shutdown time is: " + new Date().toString());
645 System.out.println("*************************************************************************");
646 }
647 }
648 System.exit(0);
649 }
650
651 /**
652 * A convenience method to obtain a reference to the Session Manager
653 * @return the <code>MuleSessionManager</code> instance
654 */
655 public MuleSessionManager getSessionManager()
656 {
657 return sessionManager;
658 }
659
660 /**
661 * A convenience method to get a session from the session manager
662 * @param the Mule name for which the session is required
663 * @return a valid session
664 * @throws UMOException if the session fails to initialise or a descriptor
665 * for the specified name does not exist
666 */
667 public UMOSession getSession(String muleName) throws UMOException
668 {
669 return sessionManager.getSession(muleName);
670 }
671
672 /**
673 * A convenience method to get a session from the session manager
674 * @param descriptor the descriptor for which the session is required
675 * @return a valid session
676 * @throws UMOException if the session fails to initialise
677 */
678 public UMOSession getSession(UMODescriptor descriptor) throws UMOException
679 {
680 return sessionManager.getSession(descriptor);
681 }
682 }