Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/activemq/broker/impl/BrokerContainerImpl.java


1   /**
2    *
3    * Copyright 2004 Protique Ltd
4    *
5    * Licensed under the Apache License, Version 2.0 (the "License");
6    * you may not use this file except in compliance with the License.
7    * You may obtain a copy of the License at
8    *
9    * http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   *
17   **/
18  
19  package org.activemq.broker.impl;
20  
21  import java.util.ArrayList;
22  import java.util.HashMap;
23  import java.util.Iterator;
24  import java.util.List;
25  import java.util.Map;
26  import javax.jms.InvalidClientIDException;
27  import javax.jms.InvalidDestinationException;
28  import javax.jms.JMSException;
29  import javax.jms.JMSSecurityException;
30  import javax.transaction.xa.XAException;
31  import org.apache.commons.logging.Log;
32  import org.apache.commons.logging.LogFactory;
33  import org.activemq.ActiveMQConnectionMetaData;
34  import org.activemq.broker.Broker;
35  import org.activemq.broker.BrokerClient;
36  import org.activemq.broker.BrokerConnector;
37  import org.activemq.broker.BrokerContainer;
38  import org.activemq.broker.BrokerContext;
39  import org.activemq.capacity.CapacityMonitorEvent;
40  import org.activemq.capacity.CapacityMonitorEventListener;
41  import org.activemq.io.WireFormat;
42  import org.activemq.io.impl.DefaultWireFormat;
43  import org.activemq.io.util.MemoryBoundedObjectManager;
44  import org.activemq.message.ActiveMQDestination;
45  import org.activemq.message.ActiveMQMessage;
46  import org.activemq.message.ActiveMQXid;
47  import org.activemq.message.ConnectionInfo;
48  import org.activemq.message.ConsumerInfo;
49  import org.activemq.message.DurableUnsubscribe;
50  import org.activemq.message.MessageAck;
51  import org.activemq.message.ProducerInfo;
52  import org.activemq.message.SessionInfo;
53  import org.activemq.security.SecurityAdapter;
54  import org.activemq.service.RedeliveryPolicy;
55  import org.activemq.service.DeadLetterPolicy;
56  import org.activemq.service.Service;
57  import org.activemq.store.PersistenceAdapter;
58  import org.activemq.transport.DiscoveryAgent;
59  import org.activemq.transport.NetworkConnector;
60  import org.activemq.transport.TransportServerChannel;
61  import org.activemq.util.IdGenerator;
62  import EDU.oswego.cs.dl.util.concurrent.ConcurrentHashMap;
63  import EDU.oswego.cs.dl.util.concurrent.CopyOnWriteArrayList;
64  import EDU.oswego.cs.dl.util.concurrent.CopyOnWriteArraySet;
65  import java.util.Set;
66  
67  /**
68   * Represents the ActiveMQ JMS Broker which typically has one or many connectors
69   *
70   * @version $Revision: 1.1.1.1 $
71   */
72  public class BrokerContainerImpl implements BrokerContainer, CapacityMonitorEventListener {
73      public static final String DISABLE_CLEAN_SHUTDOWN_PROPERTY = "activemq.broker.disable-clean-shutdown";
74      private static final Log log = LogFactory.getLog(BrokerContainerImpl.class);
75      private static final boolean useLoggingForShutdownErrors = false;
76  
77      private BrokerContext context;
78      private Broker broker;
79      private Map clientIds;
80      private Map consumerInfos;
81      private Map producerInfos;
82      private List transportConnectors;
83      private Thread shutdownHook;
84      private boolean stopped;
85      private List networkConnectors;
86      private DiscoveryAgent discoveryAgent;
87      private Map localDiscoveryDetails;
88      private Set remoteClientIds;
89  
90  
91      public BrokerContainerImpl() {
92          this(new IdGenerator().generateId());
93      }
94  
95      public BrokerContainerImpl(String brokerName) {
96          this(brokerName, BrokerContext.getInstance());
97      }
98  
99      public BrokerContainerImpl(String brokerName, MemoryBoundedObjectManager memoryManager) {
100         this(brokerName, BrokerContext.getInstance(), memoryManager);
101     }
102     
103     public BrokerContainerImpl(String brokerName,String clusterName) {
104         this(brokerName, clusterName,BrokerContext.getInstance());
105         
106     }
107 
108     public BrokerContainerImpl(String brokerName, PersistenceAdapter persistenceAdapter) {
109         this(brokerName, persistenceAdapter, BrokerContext.getInstance());
110     }
111 
112     public BrokerContainerImpl(String brokerName, BrokerContext context) {
113         this(new DefaultBroker(brokerName), context);
114     }
115     
116     public BrokerContainerImpl(String brokerName, BrokerContext context, MemoryBoundedObjectManager memoryManager) {
117         this(new DefaultBroker(brokerName,memoryManager), context);
118     }
119     
120     public BrokerContainerImpl(String brokerName, String clusterName, BrokerContext context) {
121         this(new DefaultBroker(brokerName,clusterName), context);
122     }
123     
124     public BrokerContainerImpl(String brokerName, PersistenceAdapter persistenceAdapter, BrokerContext context) {
125         this(new DefaultBroker(brokerName, persistenceAdapter), context);
126     }
127 
128     public BrokerContainerImpl(String brokerName,String clusterName, PersistenceAdapter persistenceAdapter, BrokerContext context) {
129         this(new DefaultBroker(brokerName,clusterName, persistenceAdapter), context);
130     }
131 
132     /**
133      * @param broker
134      */
135     public BrokerContainerImpl(Broker broker, BrokerContext context) {
136         this.broker = broker;
137         this.context = context;
138         this.clientIds = new ConcurrentHashMap();
139         this.consumerInfos = new ConcurrentHashMap();
140         this.producerInfos = new ConcurrentHashMap();
141         this.transportConnectors = new CopyOnWriteArrayList();
142         this.networkConnectors = new CopyOnWriteArrayList();
143         this.remoteClientIds = new CopyOnWriteArraySet();
144         this.broker.addCapacityEventListener(this);
145         if (this.broker instanceof DefaultBroker){
146             ((DefaultBroker)broker).setBrokercontainer(this);
147         }
148         doRegistration(broker.getBrokerName());
149     }
150 
151     /**
152      * start the Container
153      *
154      * @throws JMSException
155      */
156     public void start() throws JMSException {
157         log.info("ActiveMQ "+ActiveMQConnectionMetaData.PROVIDER_VERSION+" JMS Message Broker (" + broker.getBrokerName() + ") is starting");
158         log.info("For help or more information please see: http://www.logicblaze.com");
159         broker.start();
160         addShutdownHook();
161 
162         // TODO we might not need to copy the collections, as maybe the List might not
163         // throw concurrent modification exception? Couldn't tell from the docs
164         // but I don't think it does
165 
166         for (Iterator iter = new ArrayList(networkConnectors).iterator(); iter.hasNext();) {
167             Service connector = (Service) iter.next();
168             connector.start();
169         }
170 
171         for (Iterator iter = new ArrayList(transportConnectors).iterator(); iter.hasNext();) {
172             Service connector = (Service) iter.next();
173             connector.start();
174         }
175 
176         if (discoveryAgent != null) {
177             discoveryAgent.start();
178 
179             localDiscoveryDetails = createLocalDiscoveryDetails();
180             discoveryAgent.registerService(getLocalBrokerName(), localDiscoveryDetails);
181         }
182 
183         log.info("ActiveMQ JMS Message Broker (" + broker.getBrokerName() + ") has started");
184     }
185 
186     /**
187      * Stop the Container
188      *
189      * @throws JMSException
190      */
191     public synchronized void stop() throws JMSException {
192         if (!stopped) {
193             stopped = true;
194 
195             log.info("ActiveMQ Message Broker (" + broker.getBrokerName() + ") is shutting down");
196 
197             context.deregisterContainer(broker.getBrokerName(), this);
198 
199             try {
200                 Runtime.getRuntime().removeShutdownHook(shutdownHook);
201             }
202             catch (Exception e) {
203                 log.debug("Caught exception, must be shutting down: " + e);
204             }
205 
206             JMSException firstException = null;
207             if (discoveryAgent != null) {
208                 try {
209                     discoveryAgent.stop();
210                 } catch (JMSException e) {
211                     firstException = e;
212                     log.warn("Could not close discovery agent: " + discoveryAgent + " due to: " + e, e);
213                 }
214             }
215 
216             for (Iterator iter = new ArrayList(transportConnectors).iterator(); iter.hasNext();) {
217                 Service connector = (Service) iter.next();
218                 try {
219                     connector.stop();
220                 }
221                 catch (JMSException e) {
222                     if (firstException == null) {
223                         firstException = e;
224                     }
225                     log.warn("Could not close transport connector: " + connector + " due to: " + e, e);
226                 }
227             }
228             transportConnectors.clear();
229 
230             for (Iterator iter = new ArrayList(networkConnectors).iterator(); iter.hasNext();) {
231                 Service connector = (Service) iter.next();
232                 try {
233                     connector.stop();
234                 }
235                 catch (JMSException e) {
236                     if (firstException == null) {
237                         firstException = e;
238                     }
239                     log.warn("Could not close network connector: " + connector + " due to: " + e, e);
240                 }
241             }
242             networkConnectors.clear();
243 
244             
245 
246             // lets close all the channels
247             // note that this Map implementation does not throw concurrent modification exception
248             for (Iterator iter = clientIds.values().iterator();iter.hasNext();) {
249                 // should remove clients from parent container?
250                 BrokerClient client = (BrokerClient) iter.next();
251                 if (client != null) {
252                     try {
253                         client.stop();
254                     }
255                     catch (JMSException e) {
256                         if (firstException == null) {
257                             firstException = e;
258                         }
259                         log.warn("Could not close client: " + client + " due to: " + e, e);
260                     }
261                 }
262             }
263             clientIds.clear();
264 
265             broker.removeCapacityEventListener(this);
266             broker.stop();
267 
268             log.info("ActiveMQ JMS Message Broker (" + broker.getBrokerName() + ") stopped");
269 
270             if (firstException != null) {
271                 throw firstException;
272             }
273         }
274     }
275 
276     /**
277      * registers a new Connection
278      *
279      * @param client
280      * @param info   infomation about the client-side Connection
281      * @throws InvalidClientIDException if the ClientID of the Connection is a duplicate
282      */
283   synchronized public void registerConnection(BrokerClient client, ConnectionInfo info) throws JMSException {
284     String clientId = info.getClientId();
285     if (clientIds.containsKey(clientId)) {
286       int timeout = 5000;
287       log.info("Got duplicate client with id: " + clientId + ". Giving the existing client " + timeout + " millis to prove it's alive.");
288 
289       // Assert that the existing client is alive
290       BrokerClient existingClient = (BrokerClient) clientIds.get(clientId);
291       JMSException ex = null;
292       boolean isValid = true;
293       try {
294         existingClient.validateConnection(timeout);
295       } catch (JMSException e) {
296         isValid = false;
297         ex = e;
298       }
299       if (isValid) {
300         // The existing client is valid, so kick the new client
301         log.info("Client: " + clientId + " on transport: " + existingClient.getChannel()
302             + "' is alive, rejecting new client on transport: " + client.getChannel());
303         throw new InvalidClientIDException("Duplicate clientId: " + info);
304       } else {
305         // A transport error occured or the existing client did not
306         // respond in time, so kick it and let the new client connect.
307         log.info("Replacing client: " + clientId + " on transport: " + existingClient.getChannel() + " ("
308             + ex.getMessage() + ") with client on transport: " + client.getChannel());
309         
310         // @TODO: Not sure this is the proper way to close the existing client
311         existingClient.cleanUp(); 
312         existingClient.stop();
313       }
314 
315     }
316     getBroker().addClient(client, info);
317     log.info("Adding new client: " + clientId + " on transport: " + client.getChannel());
318     clientIds.put(clientId, client);
319   }
320 
321     /**
322      * un-registers a Connection
323      *
324      * @param client
325      * @param info   infomation about the client-side Connection
326      * @throws JMSException
327      */
328     public void deregisterConnection(BrokerClient client, ConnectionInfo info) throws JMSException {
329         String clientId = client.getClientID();
330         if (clientId != null) {
331             Object answer = clientIds.remove(clientId);
332             if (answer != null) {
333                 log.info("Removing client: " + clientId + " on transport: " + client.getChannel());
334                 getBroker().removeClient(client, info);
335             }
336             else {
337                 log.warn("Got duplicate deregisterConnection for client: " + clientId);
338             }
339         }
340         else {
341             log.warn("No clientID available for client: " + client);
342         }
343     }
344 
345     /**
346      * Registers a MessageConsumer
347      *
348      * @param client
349      * @param info
350      * @throws JMSException
351      * @throws JMSSecurityException if client authentication fails for the Destination the Consumer applies for
352      */
353     public void registerMessageConsumer(BrokerClient client, ConsumerInfo info) throws JMSException {
354         consumerInfos.put(info, client);
355         getBroker().addMessageConsumer(client, info);
356     }
357 
358     /**
359      * De-register a MessageConsumer from the Broker
360      *
361      * @param client
362      * @param info
363      * @throws JMSException
364      */
365     public void deregisterMessageConsumer(BrokerClient client, ConsumerInfo info) throws JMSException {
366         consumerInfos.remove(info);
367         getBroker().removeMessageConsumer(client, info);
368     }
369 
370     /**
371      * Registers a MessageProducer
372      *
373      * @param client
374      * @param info
375      * @throws JMSException
376      * @throws JMSSecurityException if client authentication fails for the Destination the Consumer applies for
377      */
378     public void registerMessageProducer(BrokerClient client, ProducerInfo info) throws JMSException {
379         ActiveMQDestination dest = info.getDestination();
380         checkTempDestinationExistance(dest);
381         getBroker().addMessageProducer(client, info);
382 
383         producerInfos.put(info, client);
384     }
385 
386     /**
387      * De-register a MessageProducer from the Broker
388      *
389      * @param client
390      * @param info
391      * @throws JMSException
392      */
393     public void deregisterMessageProducer(BrokerClient client, ProducerInfo info) throws JMSException {
394         getBroker().removeMessageProducer(client, info);
395 
396         producerInfos.remove(info);
397     }
398 
399     /**
400      * Register a client-side Session (used for Monitoring)
401      *
402      * @param client
403      * @param info
404      * @throws JMSException
405      */
406     public void registerSession(BrokerClient client, SessionInfo info) throws JMSException {
407     }
408 
409     /**
410      * De-register a client-side Session from the Broker (used for monitoring)
411      *
412      * @param client
413      * @param info
414      * @throws JMSException
415      */
416     public void deregisterSession(BrokerClient client, SessionInfo info) throws JMSException {
417     }
418 
419     /**
420      * Start a transaction from the Client session
421      *
422      * @param client
423      * @param transactionId
424      * @throws JMSException
425      */
426     public void startTransaction(BrokerClient client, String transactionId) throws JMSException {
427         getBroker().startTransaction(client, transactionId);
428     }
429 
430     /**
431      * Rollback a transacton
432      *
433      * @param client
434      * @param transactionId
435      * @throws JMSException
436      */
437     public void rollbackTransaction(BrokerClient client, String transactionId) throws JMSException {
438         getBroker().rollbackTransaction(client, transactionId);
439     }
440 
441     /**
442      * Commit a transaction
443      *
444      * @param client
445      * @param transactionId
446      * @throws JMSException
447      */
448     public void commitTransaction(BrokerClient client, String transactionId) throws JMSException {
449         getBroker().commitTransaction(client, transactionId);
450     }
451 
452     /**
453      * Send a non-transacted message to the Broker
454      *
455      * @param client
456      * @param message
457      * @throws JMSException
458      */
459     public void sendMessage(BrokerClient client, ActiveMQMessage message) throws JMSException {
460         ActiveMQDestination dest = message.getJMSActiveMQDestination();        
461         checkTempDestinationExistance(dest);
462         broker.sendMessage(client, message);
463     }
464     
465     /**
466      * register a remote clientID
467      * @param remoteClientID
468      */
469     
470     public void registerRemoteClientID(String remoteClientID){
471         remoteClientIds.add(remoteClientID);
472     }
473     
474     /**
475      * deregister a remote clientID
476      * @param remoteClientID
477      */
478     public void deregisterRemoteClientID(String remoteClientID){
479         remoteClientIds.remove(remoteClientID);
480     }
481 
482     /**
483      * @param dest
484      * @throws InvalidDestinationException
485      */
486     private void checkTempDestinationExistance(ActiveMQDestination dest) throws InvalidDestinationException {
487         if (dest != null && dest.isTemporary()) {
488             //check to see if the client that is the target for the temporary destination still exists
489             String clientId = ActiveMQDestination.getClientId(dest);
490             if (clientId == null) {
491                 throw new InvalidDestinationException("Destination " + dest.getPhysicalName()
492                         + " is a temporary destination with null clientId");
493             }
494             if (!clientIds.containsKey(clientId) && !remoteClientIds.contains(clientId)) {
495                 throw new InvalidDestinationException("Destination " + dest.getPhysicalName()
496                         + " is no longer valid because the client " + clientId + " no longer exists");
497             }
498         }
499     }
500 
501     /**
502      * Acknowledge reciept of a message
503      *
504      * @param client
505      * @param ack
506      * @throws JMSException
507      */
508     public void acknowledgeMessage(BrokerClient client, MessageAck ack) throws JMSException {
509         getBroker().acknowledgeMessage(client, ack);
510     }
511 
512     /**
513      * Command to delete a durable topic subscription
514      *
515      * @param client
516      * @param ds
517      * @throws JMSException
518      */
519     public void durableUnsubscribe(BrokerClient client, DurableUnsubscribe ds) throws JMSException {
520         getBroker().deleteSubscription(ds.getClientId(), ds.getSubscriberName());
521     }
522 
523     /**
524      * Start an XA transaction.
525      *
526      * @param client
527      * @param xid
528      */
529     public void startTransaction(BrokerClient client, ActiveMQXid xid) throws XAException {
530         getBroker().startTransaction(client, xid);
531     }
532 
533     /**
534      * Gets the prepared XA transactions.
535      *
536      * @param client
537      * @return
538      */
539     public ActiveMQXid[] getPreparedTransactions(BrokerClient client) throws XAException {
540         return getBroker().getPreparedTransactions(client);
541     }
542 
543     /**
544      * Prepare an XA transaction.
545      *
546      * @param client
547      * @param xid
548      */
549     public int prepareTransaction(BrokerClient client, ActiveMQXid xid) throws XAException {
550         return getBroker().prepareTransaction(client, xid);
551     }
552 
553     /**
554      * Rollback an XA transaction.
555      *
556      * @param client
557      * @param xid
558      */
559     public void rollbackTransaction(BrokerClient client, ActiveMQXid xid) throws XAException {
560         getBroker().rollbackTransaction(client, xid);
561     }
562 
563     /**
564      * Commit an XA transaction.
565      *
566      * @param client
567      * @param xid
568      * @param onePhase
569      */
570     public void commitTransaction(BrokerClient client, ActiveMQXid xid, boolean onePhase) throws XAException {
571         getBroker().commitTransaction(client, xid, onePhase);
572     }
573 
574 
575     /**
576      * Update any message producers about our capacity to handle messages
577      *
578      * @param event
579      */
580     public void capacityChanged(CapacityMonitorEvent event) {
581         //only send to producers
582         for (Iterator i = producerInfos.values().iterator(); i.hasNext();) {
583             BrokerClient client = (BrokerClient) i.next();
584             client.updateBrokerCapacity(event.getCapacity());
585         }
586     }
587 
588 
589     // Properties
590     //-------------------------------------------------------------------------
591 
592     public List getTransportConnectors() {
593         return transportConnectors;
594     }
595 
596     public void setTransportConnectors(List transportConnectors) {
597         this.transportConnectors = new CopyOnWriteArrayList(transportConnectors);
598     }
599 
600     public void addConnector(BrokerConnector connector) {
601         if( !transportConnectors.contains(connector) ) {
602             transportConnectors.add(connector);
603             if (connector.getServerChannel() != null){
604                 context.registerConnector(connector.getServerChannel().getUrl(), connector);
605             }
606         }
607     }
608 
609     public void removeConnector(BrokerConnector connector) {
610         transportConnectors.remove(connector);
611         if (connector != null && connector.getServerChannel() != null){
612             context.deregisterConnector(connector.getServerChannel().getUrl());
613         }
614     }
615 
616 
617     public void addConnector(String bindAddress) throws JMSException {
618         addConnector(bindAddress, new DefaultWireFormat());
619     }
620 
621     public void addConnector(String bindAddress, WireFormat wireFormat) throws JMSException {
622         addConnector(new BrokerConnectorImpl(this, bindAddress, wireFormat));
623     }
624 
625     public void addConnector(TransportServerChannel transportConnector) {
626         addConnector(new BrokerConnectorImpl(this, transportConnector));
627     }
628 
629     public List getNetworkConnectors() {
630         return networkConnectors;
631     }
632 
633     public void setNetworkConnectors(List networkConnectors) {
634         this.networkConnectors = new CopyOnWriteArrayList(networkConnectors);
635     }
636 
637     public NetworkConnector addNetworkConnector(String uri) throws JMSException {
638         NetworkConnector connector = addNetworkConnector();
639         connector.addNetworkChannel(uri);
640         return connector;
641     }
642 
643     public NetworkConnector addNetworkConnector() {
644         NetworkConnector connector = new NetworkConnector(this);
645         addNetworkConnector(connector);
646         return connector;
647     }
648 
649     public void addNetworkConnector(NetworkConnector connector) {
650         networkConnectors.add(connector);
651     }
652 
653     public void removeNetworkConnector(NetworkConnector connector) {
654         networkConnectors.remove(connector);
655     }
656 
657 
658     public Broker getBroker() {
659         return broker;
660     }
661 
662     public PersistenceAdapter getPersistenceAdapter() {
663         return broker != null ? broker.getPersistenceAdapter() : null;
664     }
665 
666     public void setPersistenceAdapter(PersistenceAdapter persistenceAdapter) {
667         checkBrokerSet();
668         broker.setPersistenceAdapter(persistenceAdapter);
669     }
670 
671     public DiscoveryAgent getDiscoveryAgent() {
672         return discoveryAgent;
673     }
674 
675     public void setDiscoveryAgent(DiscoveryAgent discoveryAgent) {
676         this.discoveryAgent = discoveryAgent;
677     }
678 
679     public SecurityAdapter getSecurityAdapter() {
680         return broker != null ? broker.getSecurityAdapter() : null;
681     }
682 
683     public void setSecurityAdapter(SecurityAdapter securityAdapter) {
684         checkBrokerSet();
685         broker.setSecurityAdapter(securityAdapter);
686     }
687 
688     public RedeliveryPolicy getRedeliveryPolicy() {
689         return broker != null ? broker.getRedeliveryPolicy() : null;
690     }
691 
692     public void setRedeliveryPolicy(RedeliveryPolicy redeliveryPolicy) {
693         checkBrokerSet();
694         broker.setRedeliveryPolicy(redeliveryPolicy);
695     }
696 
697     public DeadLetterPolicy getDeadLetterPolicy() {
698         return broker != null ? broker.getDeadLetterPolicy() : null;
699     }
700 
701     public void setDeadLetterPolicy(DeadLetterPolicy deadLetterPolicy) {
702         checkBrokerSet();
703         broker.setDeadLetterPolicy(deadLetterPolicy);
704     }
705 
706     // Implementation methods
707     //-------------------------------------------------------------------------
708 
709     protected void checkBrokerSet() {
710         if (broker == null) {
711             throw new IllegalStateException("Cannot set this property as we don't have a broker yet");
712         }
713     }
714 
715     protected Map createLocalDiscoveryDetails() {
716         Map map = new HashMap();
717         map.put("brokerName", getLocalBrokerName());
718         map.put("connectURL", getLocalConnectionURL());
719         return map;
720     }
721 
722     protected String getLocalBrokerName() {
723         return getBroker().getBrokerName();
724     }
725 
726     protected String getLocalConnectionURL() {
727         StringBuffer buffer = new StringBuffer("reliable:");
728         List list = getTransportConnectors();
729         boolean first = true;
730         for(Iterator iter = list.iterator();iter.hasNext();){
731             BrokerConnector brokerConnector = (BrokerConnector)iter.next();
732             TransportServerChannel connector = brokerConnector.getServerChannel();
733             if(connector!=null){
734                 String url = connector.getUrl();
735                 if(first){
736                     first = false;
737                 }else{
738                     buffer.append(",");
739                 }
740                 buffer.append(url);
741             }
742         }
743         return buffer.toString();
744     }
745 
746     protected void addShutdownHook() {
747         if(System.getProperty(DISABLE_CLEAN_SHUTDOWN_PROPERTY,"false").equals("true"))
748             return;
749         
750         shutdownHook = new Thread("ActiveMQ ShutdownHook") {
751             public void run() {
752                 containerShutdown();
753             }
754         };
755         Runtime.getRuntime().addShutdownHook(shutdownHook);
756     }
757 
758     /**
759      * Causes a clean shutdown of the container when the VM is being shut down
760      */
761     protected void containerShutdown() {
762         try {
763             stop();
764         }
765         catch (JMSException e) {
766             Exception linkedException = e.getLinkedException();
767             if (linkedException != null) {
768                 if (useLoggingForShutdownErrors) {
769                     log.error("Failed to shut down: " + e + ". Reason: " + linkedException, linkedException);
770                 }
771                 else {
772                     System.err.println("Failed to shut down: " + e + ". Reason: " + linkedException);
773                 }
774             }
775             else {
776                 if (useLoggingForShutdownErrors) {
777                     log.error("Failed to shut down: " + e);
778                 }
779                 else {
780                     System.err.println("Failed to shut down: " + e);
781                 }
782             }
783             if (!useLoggingForShutdownErrors) {
784                 e.printStackTrace(System.err);
785             }
786         }
787         catch (Exception e) {
788             if (useLoggingForShutdownErrors) {
789                 log.error("Failed to shut down: " + e, e);
790             }
791             else {
792                 System.err.println("Failed to shut down: " + e);
793                 e.printStackTrace(System.err);
794             }
795         }
796     }
797     
798     protected void doDeRegistration(String oldName){
799         context.deregisterContainer(oldName,this);
800         context.deregisterContainer("vm://"+oldName,this);
801     }
802     protected void doRegistration(String brokerName){
803        
804         //lets register ourselves with the context
805         context.registerContainer(brokerName, this);
806         //register ourselves for vm:// transports
807         context.registerContainer("vm://" + brokerName, this);
808     }
809 }