001 /** 002 * 003 * Copyright 2004 Protique Ltd 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 * 017 **/ 018 019 package org.activemq.broker.impl; 020 021 import java.util.ArrayList; 022 import java.util.HashMap; 023 import java.util.Iterator; 024 import java.util.List; 025 import java.util.Map; 026 import javax.jms.InvalidClientIDException; 027 import javax.jms.InvalidDestinationException; 028 import javax.jms.JMSException; 029 import javax.jms.JMSSecurityException; 030 import javax.transaction.xa.XAException; 031 import org.apache.commons.logging.Log; 032 import org.apache.commons.logging.LogFactory; 033 import org.activemq.ActiveMQConnectionMetaData; 034 import org.activemq.broker.Broker; 035 import org.activemq.broker.BrokerClient; 036 import org.activemq.broker.BrokerConnector; 037 import org.activemq.broker.BrokerContainer; 038 import org.activemq.broker.BrokerContext; 039 import org.activemq.capacity.CapacityMonitorEvent; 040 import org.activemq.capacity.CapacityMonitorEventListener; 041 import org.activemq.io.WireFormat; 042 import org.activemq.io.impl.DefaultWireFormat; 043 import org.activemq.io.util.MemoryBoundedObjectManager; 044 import org.activemq.message.ActiveMQDestination; 045 import org.activemq.message.ActiveMQMessage; 046 import org.activemq.message.ActiveMQXid; 047 import org.activemq.message.ConnectionInfo; 048 import org.activemq.message.ConsumerInfo; 049 import org.activemq.message.DurableUnsubscribe; 050 import org.activemq.message.MessageAck; 051 import org.activemq.message.ProducerInfo; 052 import org.activemq.message.SessionInfo; 053 import org.activemq.security.SecurityAdapter; 054 import org.activemq.service.RedeliveryPolicy; 055 import org.activemq.service.DeadLetterPolicy; 056 import org.activemq.service.Service; 057 import org.activemq.store.PersistenceAdapter; 058 import org.activemq.transport.DiscoveryAgent; 059 import org.activemq.transport.NetworkConnector; 060 import org.activemq.transport.TransportServerChannel; 061 import org.activemq.util.IdGenerator; 062 import EDU.oswego.cs.dl.util.concurrent.ConcurrentHashMap; 063 import EDU.oswego.cs.dl.util.concurrent.CopyOnWriteArrayList; 064 import EDU.oswego.cs.dl.util.concurrent.CopyOnWriteArraySet; 065 import java.util.Set; 066 067 /** 068 * Represents the ActiveMQ JMS Broker which typically has one or many connectors 069 * 070 * @version $Revision: 1.1.1.1 $ 071 */ 072 public class BrokerContainerImpl implements BrokerContainer, CapacityMonitorEventListener { 073 public static final String DISABLE_CLEAN_SHUTDOWN_PROPERTY = "activemq.broker.disable-clean-shutdown"; 074 private static final Log log = LogFactory.getLog(BrokerContainerImpl.class); 075 private static final boolean useLoggingForShutdownErrors = false; 076 077 private BrokerContext context; 078 private Broker broker; 079 private Map clientIds; 080 private Map consumerInfos; 081 private Map producerInfos; 082 private List transportConnectors; 083 private Thread shutdownHook; 084 private boolean stopped; 085 private List networkConnectors; 086 private DiscoveryAgent discoveryAgent; 087 private Map localDiscoveryDetails; 088 private Set remoteClientIds; 089 090 091 public BrokerContainerImpl() { 092 this(new IdGenerator().generateId()); 093 } 094 095 public BrokerContainerImpl(String brokerName) { 096 this(brokerName, BrokerContext.getInstance()); 097 } 098 099 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 }