001/** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. 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 */ 017package org.apache.activemq.broker; 018 019import java.io.BufferedReader; 020import java.io.File; 021import java.io.IOException; 022import java.io.InputStream; 023import java.io.InputStreamReader; 024import java.net.URI; 025import java.net.URISyntaxException; 026import java.net.UnknownHostException; 027import java.security.Provider; 028import java.security.Security; 029import java.util.ArrayList; 030import java.util.Date; 031import java.util.HashMap; 032import java.util.HashSet; 033import java.util.Iterator; 034import java.util.List; 035import java.util.Locale; 036import java.util.Map; 037import java.util.Set; 038import java.util.concurrent.CopyOnWriteArrayList; 039import java.util.concurrent.CountDownLatch; 040import java.util.concurrent.LinkedBlockingQueue; 041import java.util.concurrent.RejectedExecutionException; 042import java.util.concurrent.RejectedExecutionHandler; 043import java.util.concurrent.SynchronousQueue; 044import java.util.concurrent.ThreadFactory; 045import java.util.concurrent.ThreadPoolExecutor; 046import java.util.concurrent.TimeUnit; 047import java.util.concurrent.atomic.AtomicBoolean; 048import java.util.concurrent.atomic.AtomicInteger; 049import java.util.concurrent.atomic.AtomicLong; 050 051import javax.annotation.PostConstruct; 052import javax.annotation.PreDestroy; 053import javax.management.MalformedObjectNameException; 054import javax.management.ObjectName; 055 056import org.apache.activemq.ActiveMQConnectionMetaData; 057import org.apache.activemq.ConfigurationException; 058import org.apache.activemq.Service; 059import org.apache.activemq.advisory.AdvisoryBroker; 060import org.apache.activemq.broker.cluster.ConnectionSplitBroker; 061import org.apache.activemq.broker.jmx.AnnotatedMBean; 062import org.apache.activemq.broker.jmx.BrokerMBeanSupport; 063import org.apache.activemq.broker.jmx.BrokerView; 064import org.apache.activemq.broker.jmx.ConnectorView; 065import org.apache.activemq.broker.jmx.ConnectorViewMBean; 066import org.apache.activemq.broker.jmx.HealthView; 067import org.apache.activemq.broker.jmx.HealthViewMBean; 068import org.apache.activemq.broker.jmx.JmsConnectorView; 069import org.apache.activemq.broker.jmx.JobSchedulerView; 070import org.apache.activemq.broker.jmx.JobSchedulerViewMBean; 071import org.apache.activemq.broker.jmx.Log4JConfigView; 072import org.apache.activemq.broker.jmx.ManagedRegionBroker; 073import org.apache.activemq.broker.jmx.ManagementContext; 074import org.apache.activemq.broker.jmx.NetworkConnectorView; 075import org.apache.activemq.broker.jmx.NetworkConnectorViewMBean; 076import org.apache.activemq.broker.jmx.ProxyConnectorView; 077import org.apache.activemq.broker.region.CompositeDestinationInterceptor; 078import org.apache.activemq.broker.region.Destination; 079import org.apache.activemq.broker.region.DestinationFactory; 080import org.apache.activemq.broker.region.DestinationFactoryImpl; 081import org.apache.activemq.broker.region.DestinationInterceptor; 082import org.apache.activemq.broker.region.RegionBroker; 083import org.apache.activemq.broker.region.policy.PolicyMap; 084import org.apache.activemq.broker.region.virtual.MirroredQueue; 085import org.apache.activemq.broker.region.virtual.VirtualDestination; 086import org.apache.activemq.broker.region.virtual.VirtualDestinationInterceptor; 087import org.apache.activemq.broker.region.virtual.VirtualTopic; 088import org.apache.activemq.broker.scheduler.JobSchedulerStore; 089import org.apache.activemq.broker.scheduler.SchedulerBroker; 090import org.apache.activemq.broker.scheduler.memory.InMemoryJobSchedulerStore; 091import org.apache.activemq.command.ActiveMQDestination; 092import org.apache.activemq.command.ActiveMQQueue; 093import org.apache.activemq.command.BrokerId; 094import org.apache.activemq.command.ProducerInfo; 095import org.apache.activemq.filter.DestinationFilter; 096import org.apache.activemq.network.ConnectionFilter; 097import org.apache.activemq.network.DiscoveryNetworkConnector; 098import org.apache.activemq.network.NetworkConnector; 099import org.apache.activemq.network.jms.JmsConnector; 100import org.apache.activemq.openwire.OpenWireFormat; 101import org.apache.activemq.proxy.ProxyConnector; 102import org.apache.activemq.security.MessageAuthorizationPolicy; 103import org.apache.activemq.selector.SelectorParser; 104import org.apache.activemq.store.JournaledStore; 105import org.apache.activemq.store.PListStore; 106import org.apache.activemq.store.PersistenceAdapter; 107import org.apache.activemq.store.PersistenceAdapterFactory; 108import org.apache.activemq.store.memory.MemoryPersistenceAdapter; 109import org.apache.activemq.thread.Scheduler; 110import org.apache.activemq.thread.TaskRunnerFactory; 111import org.apache.activemq.transport.TransportFactorySupport; 112import org.apache.activemq.transport.TransportServer; 113import org.apache.activemq.transport.vm.VMTransportFactory; 114import org.apache.activemq.usage.SystemUsage; 115import org.apache.activemq.util.BrokerSupport; 116import org.apache.activemq.util.DefaultIOExceptionHandler; 117import org.apache.activemq.util.IOExceptionHandler; 118import org.apache.activemq.util.IOExceptionSupport; 119import org.apache.activemq.util.IOHelper; 120import org.apache.activemq.util.InetAddressUtil; 121import org.apache.activemq.util.ServiceStopper; 122import org.apache.activemq.util.ThreadPoolUtils; 123import org.apache.activemq.util.TimeUtils; 124import org.apache.activemq.util.URISupport; 125import org.slf4j.Logger; 126import org.slf4j.LoggerFactory; 127import org.slf4j.MDC; 128 129/** 130 * Manages the life-cycle of an ActiveMQ Broker. A BrokerService consists of a 131 * number of transport connectors, network connectors and a bunch of properties 132 * which can be used to configure the broker as its lazily created. 133 * 134 * @org.apache.xbean.XBean 135 */ 136public class BrokerService implements Service { 137 public static final String DEFAULT_PORT = "61616"; 138 public static final String LOCAL_HOST_NAME; 139 public static final String BROKER_VERSION; 140 public static final String DEFAULT_BROKER_NAME = "localhost"; 141 public static final int DEFAULT_MAX_FILE_LENGTH = 1024 * 1024 * 32; 142 public static final long DEFAULT_START_TIMEOUT = 600000L; 143 144 private static final Logger LOG = LoggerFactory.getLogger(BrokerService.class); 145 146 @SuppressWarnings("unused") 147 private static final long serialVersionUID = 7353129142305630237L; 148 149 private boolean useJmx = true; 150 private boolean enableStatistics = true; 151 private boolean persistent = true; 152 private boolean populateJMSXUserID; 153 private boolean useAuthenticatedPrincipalForJMSXUserID; 154 private boolean populateUserNameInMBeans; 155 private long mbeanInvocationTimeout = 0; 156 157 private boolean useShutdownHook = true; 158 private boolean useLoggingForShutdownErrors; 159 private boolean shutdownOnMasterFailure; 160 private boolean shutdownOnSlaveFailure; 161 private boolean waitForSlave; 162 private long waitForSlaveTimeout = DEFAULT_START_TIMEOUT; 163 private boolean passiveSlave; 164 private String brokerName = DEFAULT_BROKER_NAME; 165 private File dataDirectoryFile; 166 private File tmpDataDirectory; 167 private Broker broker; 168 private BrokerView adminView; 169 private ManagementContext managementContext; 170 private ObjectName brokerObjectName; 171 private TaskRunnerFactory taskRunnerFactory; 172 private TaskRunnerFactory persistenceTaskRunnerFactory; 173 private SystemUsage systemUsage; 174 private SystemUsage producerSystemUsage; 175 private SystemUsage consumerSystemUsaage; 176 private PersistenceAdapter persistenceAdapter; 177 private PersistenceAdapterFactory persistenceFactory; 178 protected DestinationFactory destinationFactory; 179 private MessageAuthorizationPolicy messageAuthorizationPolicy; 180 private final List<TransportConnector> transportConnectors = new CopyOnWriteArrayList<TransportConnector>(); 181 private final List<NetworkConnector> networkConnectors = new CopyOnWriteArrayList<NetworkConnector>(); 182 private final List<ProxyConnector> proxyConnectors = new CopyOnWriteArrayList<ProxyConnector>(); 183 private final List<JmsConnector> jmsConnectors = new CopyOnWriteArrayList<JmsConnector>(); 184 private final List<Service> services = new ArrayList<Service>(); 185 private transient Thread shutdownHook; 186 private String[] transportConnectorURIs; 187 private String[] networkConnectorURIs; 188 private JmsConnector[] jmsBridgeConnectors; // these are Jms to Jms bridges 189 // to other jms messaging systems 190 private boolean deleteAllMessagesOnStartup; 191 private boolean advisorySupport = true; 192 private URI vmConnectorURI; 193 private String defaultSocketURIString; 194 private PolicyMap destinationPolicy; 195 private final AtomicBoolean started = new AtomicBoolean(false); 196 private final AtomicBoolean stopped = new AtomicBoolean(false); 197 private final AtomicBoolean stopping = new AtomicBoolean(false); 198 private BrokerPlugin[] plugins; 199 private boolean keepDurableSubsActive = true; 200 private boolean useVirtualTopics = true; 201 private boolean useMirroredQueues = false; 202 private boolean useTempMirroredQueues = true; 203 private BrokerId brokerId; 204 private volatile DestinationInterceptor[] destinationInterceptors; 205 private ActiveMQDestination[] destinations; 206 private PListStore tempDataStore; 207 private int persistenceThreadPriority = Thread.MAX_PRIORITY; 208 private boolean useLocalHostBrokerName; 209 private final CountDownLatch stoppedLatch = new CountDownLatch(1); 210 private final CountDownLatch startedLatch = new CountDownLatch(1); 211 private Broker regionBroker; 212 private int producerSystemUsagePortion = 60; 213 private int consumerSystemUsagePortion = 40; 214 private boolean splitSystemUsageForProducersConsumers; 215 private boolean monitorConnectionSplits = false; 216 private int taskRunnerPriority = Thread.NORM_PRIORITY; 217 private boolean dedicatedTaskRunner; 218 private boolean cacheTempDestinations = false;// useful for failover 219 private int timeBeforePurgeTempDestinations = 5000; 220 private final List<Runnable> shutdownHooks = new ArrayList<Runnable>(); 221 private boolean systemExitOnShutdown; 222 private int systemExitOnShutdownExitCode; 223 private SslContext sslContext; 224 private boolean forceStart = false; 225 private IOExceptionHandler ioExceptionHandler; 226 private boolean schedulerSupport = false; 227 private File schedulerDirectoryFile; 228 private Scheduler scheduler; 229 private ThreadPoolExecutor executor; 230 private int schedulePeriodForDestinationPurge= 0; 231 private int maxPurgedDestinationsPerSweep = 0; 232 private int schedulePeriodForDiskUsageCheck = 0; 233 private BrokerContext brokerContext; 234 private boolean networkConnectorStartAsync = false; 235 private boolean allowTempAutoCreationOnSend; 236 private JobSchedulerStore jobSchedulerStore; 237 private final AtomicLong totalConnections = new AtomicLong(); 238 private final AtomicInteger currentConnections = new AtomicInteger(); 239 240 private long offlineDurableSubscriberTimeout = -1; 241 private long offlineDurableSubscriberTaskSchedule = 300000; 242 private DestinationFilter virtualConsumerDestinationFilter; 243 244 private final AtomicBoolean persistenceAdapterStarted = new AtomicBoolean(false); 245 private Throwable startException = null; 246 private boolean startAsync = false; 247 private Date startDate; 248 private boolean slave = true; 249 250 private boolean restartAllowed = true; 251 private boolean restartRequested = false; 252 private boolean rejectDurableConsumers = false; 253 254 private int storeOpenWireVersion = OpenWireFormat.DEFAULT_STORE_VERSION; 255 256 static { 257 258 try { 259 ClassLoader loader = BrokerService.class.getClassLoader(); 260 Class<?> clazz = loader.loadClass("org.bouncycastle.jce.provider.BouncyCastleProvider"); 261 Provider bouncycastle = (Provider) clazz.newInstance(); 262 Security.insertProviderAt(bouncycastle, 2); 263 LOG.info("Loaded the Bouncy Castle security provider."); 264 } catch(Throwable e) { 265 // No BouncyCastle found so we use the default Java Security Provider 266 } 267 268 String localHostName = "localhost"; 269 try { 270 localHostName = InetAddressUtil.getLocalHostName(); 271 } catch (UnknownHostException e) { 272 LOG.error("Failed to resolve localhost"); 273 } 274 LOCAL_HOST_NAME = localHostName; 275 276 String version = null; 277 try(InputStream in = BrokerService.class.getResourceAsStream("/org/apache/activemq/version.txt")) { 278 if (in != null) { 279 try(InputStreamReader isr = new InputStreamReader(in); 280 BufferedReader reader = new BufferedReader(isr)) { 281 version = reader.readLine(); 282 } 283 } 284 } catch (IOException ie) { 285 LOG.warn("Error reading broker version ", ie); 286 } 287 BROKER_VERSION = version; 288 } 289 290 @Override 291 public String toString() { 292 return "BrokerService[" + getBrokerName() + "]"; 293 } 294 295 private String getBrokerVersion() { 296 String version = ActiveMQConnectionMetaData.PROVIDER_VERSION; 297 if (version == null) { 298 version = BROKER_VERSION; 299 } 300 301 return version; 302 } 303 304 /** 305 * Adds a new transport connector for the given bind address 306 * 307 * @return the newly created and added transport connector 308 * @throws Exception 309 */ 310 public TransportConnector addConnector(String bindAddress) throws Exception { 311 return addConnector(new URI(bindAddress)); 312 } 313 314 /** 315 * Adds a new transport connector for the given bind address 316 * 317 * @return the newly created and added transport connector 318 * @throws Exception 319 */ 320 public TransportConnector addConnector(URI bindAddress) throws Exception { 321 return addConnector(createTransportConnector(bindAddress)); 322 } 323 324 /** 325 * Adds a new transport connector for the given TransportServer transport 326 * 327 * @return the newly created and added transport connector 328 * @throws Exception 329 */ 330 public TransportConnector addConnector(TransportServer transport) throws Exception { 331 return addConnector(new TransportConnector(transport)); 332 } 333 334 /** 335 * Adds a new transport connector 336 * 337 * @return the transport connector 338 * @throws Exception 339 */ 340 public TransportConnector addConnector(TransportConnector connector) throws Exception { 341 transportConnectors.add(connector); 342 return connector; 343 } 344 345 /** 346 * Stops and removes a transport connector from the broker. 347 * 348 * @param connector 349 * @return true if the connector has been previously added to the broker 350 * @throws Exception 351 */ 352 public boolean removeConnector(TransportConnector connector) throws Exception { 353 boolean rc = transportConnectors.remove(connector); 354 if (rc) { 355 unregisterConnectorMBean(connector); 356 } 357 return rc; 358 } 359 360 /** 361 * Adds a new network connector using the given discovery address 362 * 363 * @return the newly created and added network connector 364 * @throws Exception 365 */ 366 public NetworkConnector addNetworkConnector(String discoveryAddress) throws Exception { 367 return addNetworkConnector(new URI(discoveryAddress)); 368 } 369 370 /** 371 * Adds a new proxy connector using the given bind address 372 * 373 * @return the newly created and added network connector 374 * @throws Exception 375 */ 376 public ProxyConnector addProxyConnector(String bindAddress) throws Exception { 377 return addProxyConnector(new URI(bindAddress)); 378 } 379 380 /** 381 * Adds a new network connector using the given discovery address 382 * 383 * @return the newly created and added network connector 384 * @throws Exception 385 */ 386 public NetworkConnector addNetworkConnector(URI discoveryAddress) throws Exception { 387 NetworkConnector connector = new DiscoveryNetworkConnector(discoveryAddress); 388 return addNetworkConnector(connector); 389 } 390 391 /** 392 * Adds a new proxy connector using the given bind address 393 * 394 * @return the newly created and added network connector 395 * @throws Exception 396 */ 397 public ProxyConnector addProxyConnector(URI bindAddress) throws Exception { 398 ProxyConnector connector = new ProxyConnector(); 399 connector.setBind(bindAddress); 400 connector.setRemote(new URI("fanout:multicast://default")); 401 return addProxyConnector(connector); 402 } 403 404 /** 405 * Adds a new network connector to connect this broker to a federated 406 * network 407 */ 408 public NetworkConnector addNetworkConnector(NetworkConnector connector) throws Exception { 409 connector.setBrokerService(this); 410 connector.setLocalUri(getVmConnectorURI()); 411 // Set a connection filter so that the connector does not establish loop 412 // back connections. 413 connector.setConnectionFilter(new ConnectionFilter() { 414 @Override 415 public boolean connectTo(URI location) { 416 List<TransportConnector> transportConnectors = getTransportConnectors(); 417 for (Iterator<TransportConnector> iter = transportConnectors.iterator(); iter.hasNext();) { 418 try { 419 TransportConnector tc = iter.next(); 420 if (location.equals(tc.getConnectUri())) { 421 return false; 422 } 423 } catch (Throwable e) { 424 } 425 } 426 return true; 427 } 428 }); 429 networkConnectors.add(connector); 430 return connector; 431 } 432 433 /** 434 * Removes the given network connector without stopping it. The caller 435 * should call {@link NetworkConnector#stop()} to close the connector 436 */ 437 public boolean removeNetworkConnector(NetworkConnector connector) { 438 boolean answer = networkConnectors.remove(connector); 439 if (answer) { 440 unregisterNetworkConnectorMBean(connector); 441 } 442 return answer; 443 } 444 445 public ProxyConnector addProxyConnector(ProxyConnector connector) throws Exception { 446 URI uri = getVmConnectorURI(); 447 connector.setLocalUri(uri); 448 proxyConnectors.add(connector); 449 if (isUseJmx()) { 450 registerProxyConnectorMBean(connector); 451 } 452 return connector; 453 } 454 455 public JmsConnector addJmsConnector(JmsConnector connector) throws Exception { 456 connector.setBrokerService(this); 457 jmsConnectors.add(connector); 458 if (isUseJmx()) { 459 registerJmsConnectorMBean(connector); 460 } 461 return connector; 462 } 463 464 public JmsConnector removeJmsConnector(JmsConnector connector) { 465 if (jmsConnectors.remove(connector)) { 466 return connector; 467 } 468 return null; 469 } 470 471 public void masterFailed() { 472 if (shutdownOnMasterFailure) { 473 LOG.error("The Master has failed ... shutting down"); 474 try { 475 stop(); 476 } catch (Exception e) { 477 LOG.error("Failed to stop for master failure", e); 478 } 479 } else { 480 LOG.warn("Master Failed - starting all connectors"); 481 try { 482 startAllConnectors(); 483 broker.nowMasterBroker(); 484 } catch (Exception e) { 485 LOG.error("Failed to startAllConnectors", e); 486 } 487 } 488 } 489 490 public String getUptime() { 491 long delta = getUptimeMillis(); 492 493 if (delta == 0) { 494 return "not started"; 495 } 496 497 return TimeUtils.printDuration(delta); 498 } 499 500 public long getUptimeMillis() { 501 if (startDate == null) { 502 return 0; 503 } 504 505 return new Date().getTime() - startDate.getTime(); 506 } 507 508 public boolean isStarted() { 509 return started.get() && startedLatch.getCount() == 0; 510 } 511 512 /** 513 * Forces a start of the broker. 514 * By default a BrokerService instance that was 515 * previously stopped using BrokerService.stop() cannot be restarted 516 * using BrokerService.start(). 517 * This method enforces a restart. 518 * It is not recommended to force a restart of the broker and will not work 519 * for most but some very trivial broker configurations. 520 * For restarting a broker instance we recommend to first call stop() on 521 * the old instance and then recreate a new BrokerService instance. 522 * 523 * @param force - if true enforces a restart. 524 * @throws Exception 525 */ 526 public void start(boolean force) throws Exception { 527 forceStart = force; 528 stopped.set(false); 529 started.set(false); 530 start(); 531 } 532 533 // Service interface 534 // ------------------------------------------------------------------------- 535 536 protected boolean shouldAutostart() { 537 return true; 538 } 539 540 /** 541 * JSR-250 callback wrapper; converts checked exceptions to runtime exceptions 542 * 543 * delegates to autoStart, done to prevent backwards incompatible signature change 544 */ 545 @PostConstruct 546 private void postConstruct() { 547 try { 548 autoStart(); 549 } catch (Exception ex) { 550 throw new RuntimeException(ex); 551 } 552 } 553 554 /** 555 * 556 * @throws Exception 557 * @org. apache.xbean.InitMethod 558 */ 559 public void autoStart() throws Exception { 560 if(shouldAutostart()) { 561 start(); 562 } 563 } 564 565 @Override 566 public void start() throws Exception { 567 if (stopped.get() || !started.compareAndSet(false, true)) { 568 // lets just ignore redundant start() calls 569 // as its way too easy to not be completely sure if start() has been 570 // called or not with the gazillion of different configuration 571 // mechanisms 572 // throw new IllegalStateException("Already started."); 573 return; 574 } 575 576 stopping.set(false); 577 startDate = new Date(); 578 MDC.put("activemq.broker", brokerName); 579 580 try { 581 if (systemExitOnShutdown && useShutdownHook) { 582 throw new ConfigurationException("'useShutdownHook' property cannot be be used with 'systemExitOnShutdown', please turn it off (useShutdownHook=false)"); 583 } 584 processHelperProperties(); 585 if (isUseJmx()) { 586 // need to remove MDC during starting JMX, as that would otherwise causes leaks, as spawned threads inheirt the MDC and 587 // we cannot cleanup clear that during shutdown of the broker. 588 MDC.remove("activemq.broker"); 589 try { 590 startManagementContext(); 591 for (NetworkConnector connector : getNetworkConnectors()) { 592 registerNetworkConnectorMBean(connector); 593 } 594 } finally { 595 MDC.put("activemq.broker", brokerName); 596 } 597 } 598 599 // in jvm master slave, lets not publish over existing broker till we get the lock 600 final BrokerRegistry brokerRegistry = BrokerRegistry.getInstance(); 601 if (brokerRegistry.lookup(getBrokerName()) == null) { 602 brokerRegistry.bind(getBrokerName(), BrokerService.this); 603 } 604 startPersistenceAdapter(startAsync); 605 startBroker(startAsync); 606 brokerRegistry.bind(getBrokerName(), BrokerService.this); 607 } catch (Exception e) { 608 LOG.error("Failed to start Apache ActiveMQ ({}, {})", new Object[]{ getBrokerName(), brokerId }, e); 609 try { 610 if (!stopped.get()) { 611 stop(); 612 } 613 } catch (Exception ex) { 614 LOG.warn("Failed to stop broker after failure in start. This exception will be ignored.", ex); 615 } 616 throw e; 617 } finally { 618 MDC.remove("activemq.broker"); 619 } 620 } 621 622 private void startPersistenceAdapter(boolean async) throws Exception { 623 if (async) { 624 new Thread("Persistence Adapter Starting Thread") { 625 @Override 626 public void run() { 627 try { 628 doStartPersistenceAdapter(); 629 } catch (Throwable e) { 630 startException = e; 631 } finally { 632 synchronized (persistenceAdapterStarted) { 633 persistenceAdapterStarted.set(true); 634 persistenceAdapterStarted.notifyAll(); 635 } 636 } 637 } 638 }.start(); 639 } else { 640 doStartPersistenceAdapter(); 641 } 642 } 643 644 private void doStartPersistenceAdapter() throws Exception { 645 getPersistenceAdapter().setUsageManager(getProducerSystemUsage()); 646 getPersistenceAdapter().setBrokerName(getBrokerName()); 647 LOG.info("Using Persistence Adapter: {}", getPersistenceAdapter()); 648 if (deleteAllMessagesOnStartup) { 649 deleteAllMessages(); 650 } 651 getPersistenceAdapter().start(); 652 653 getJobSchedulerStore(); 654 if (jobSchedulerStore != null) { 655 try { 656 jobSchedulerStore.start(); 657 } catch (Exception e) { 658 RuntimeException exception = new RuntimeException( 659 "Failed to start job scheduler store: " + jobSchedulerStore, e); 660 LOG.error(exception.getLocalizedMessage(), e); 661 throw exception; 662 } 663 } 664 } 665 666 private void startBroker(boolean async) throws Exception { 667 if (async) { 668 new Thread("Broker Starting Thread") { 669 @Override 670 public void run() { 671 try { 672 synchronized (persistenceAdapterStarted) { 673 if (!persistenceAdapterStarted.get()) { 674 persistenceAdapterStarted.wait(); 675 } 676 } 677 doStartBroker(); 678 } catch (Throwable t) { 679 startException = t; 680 } 681 } 682 }.start(); 683 } else { 684 doStartBroker(); 685 } 686 } 687 688 private void doStartBroker() throws Exception { 689 if (startException != null) { 690 return; 691 } 692 startDestinations(); 693 addShutdownHook(); 694 695 broker = getBroker(); 696 brokerId = broker.getBrokerId(); 697 698 // need to log this after creating the broker so we have its id and name 699 LOG.info("Apache ActiveMQ {} ({}, {}) is starting", new Object[]{ getBrokerVersion(), getBrokerName(), brokerId }); 700 broker.start(); 701 702 if (isUseJmx()) { 703 if (getManagementContext().isCreateConnector() && !getManagementContext().isConnectorStarted()) { 704 // try to restart management context 705 // typical for slaves that use the same ports as master 706 managementContext.stop(); 707 startManagementContext(); 708 } 709 ManagedRegionBroker managedBroker = (ManagedRegionBroker) regionBroker; 710 managedBroker.setContextBroker(broker); 711 adminView.setBroker(managedBroker); 712 } 713 714 if (ioExceptionHandler == null) { 715 setIoExceptionHandler(new DefaultIOExceptionHandler()); 716 } 717 718 if (isUseJmx() && Log4JConfigView.isLog4JAvailable()) { 719 ObjectName objectName = BrokerMBeanSupport.createLog4JConfigViewName(getBrokerObjectName().toString()); 720 Log4JConfigView log4jConfigView = new Log4JConfigView(); 721 AnnotatedMBean.registerMBean(getManagementContext(), log4jConfigView, objectName); 722 } 723 724 startAllConnectors(); 725 726 LOG.info("Apache ActiveMQ {} ({}, {}) started", new Object[]{ getBrokerVersion(), getBrokerName(), brokerId}); 727 LOG.info("For help or more information please see: http://activemq.apache.org"); 728 729 getBroker().brokerServiceStarted(); 730 checkSystemUsageLimits(); 731 startedLatch.countDown(); 732 getBroker().nowMasterBroker(); 733 } 734 735 /** 736 * JSR-250 callback wrapper; converts checked exceptions to runtime exceptions 737 * 738 * delegates to stop, done to prevent backwards incompatible signature change 739 */ 740 @PreDestroy 741 private void preDestroy () { 742 try { 743 stop(); 744 } catch (Exception ex) { 745 throw new RuntimeException(); 746 } 747 } 748 749 /** 750 * 751 * @throws Exception 752 * @org.apache .xbean.DestroyMethod 753 */ 754 @Override 755 public void stop() throws Exception { 756 if (!stopping.compareAndSet(false, true)) { 757 LOG.trace("Broker already stopping/stopped"); 758 return; 759 } 760 761 MDC.put("activemq.broker", brokerName); 762 763 if (systemExitOnShutdown) { 764 new Thread() { 765 @Override 766 public void run() { 767 System.exit(systemExitOnShutdownExitCode); 768 } 769 }.start(); 770 } 771 772 LOG.info("Apache ActiveMQ {} ({}, {}) is shutting down", new Object[]{ getBrokerVersion(), getBrokerName(), brokerId} ); 773 774 removeShutdownHook(); 775 if (this.scheduler != null) { 776 this.scheduler.stop(); 777 this.scheduler = null; 778 } 779 ServiceStopper stopper = new ServiceStopper(); 780 if (services != null) { 781 for (Service service : services) { 782 stopper.stop(service); 783 } 784 } 785 stopAllConnectors(stopper); 786 this.slave = true; 787 // remove any VMTransports connected 788 // this has to be done after services are stopped, 789 // to avoid timing issue with discovery (spinning up a new instance) 790 BrokerRegistry.getInstance().unbind(getBrokerName()); 791 VMTransportFactory.stopped(getBrokerName()); 792 if (broker != null) { 793 stopper.stop(broker); 794 broker = null; 795 } 796 797 if (jobSchedulerStore != null) { 798 jobSchedulerStore.stop(); 799 jobSchedulerStore = null; 800 } 801 if (tempDataStore != null) { 802 tempDataStore.stop(); 803 tempDataStore = null; 804 } 805 try { 806 stopper.stop(persistenceAdapter); 807 persistenceAdapter = null; 808 if (isUseJmx()) { 809 stopper.stop(getManagementContext()); 810 managementContext = null; 811 } 812 // Clear SelectorParser cache to free memory 813 SelectorParser.clearCache(); 814 } finally { 815 started.set(false); 816 stopped.set(true); 817 stoppedLatch.countDown(); 818 } 819 820 if (this.taskRunnerFactory != null) { 821 this.taskRunnerFactory.shutdown(); 822 this.taskRunnerFactory = null; 823 } 824 if (this.executor != null) { 825 ThreadPoolUtils.shutdownNow(executor); 826 this.executor = null; 827 } 828 829 this.destinationInterceptors = null; 830 this.destinationFactory = null; 831 832 if (startDate != null) { 833 LOG.info("Apache ActiveMQ {} ({}, {}) uptime {}", new Object[]{ getBrokerVersion(), getBrokerName(), brokerId, getUptime()}); 834 } 835 LOG.info("Apache ActiveMQ {} ({}, {}) is shutdown", new Object[]{ getBrokerVersion(), getBrokerName(), brokerId}); 836 837 synchronized (shutdownHooks) { 838 for (Runnable hook : shutdownHooks) { 839 try { 840 hook.run(); 841 } catch (Throwable e) { 842 stopper.onException(hook, e); 843 } 844 } 845 } 846 847 MDC.remove("activemq.broker"); 848 849 // and clear start date 850 startDate = null; 851 852 stopper.throwFirstException(); 853 } 854 855 public boolean checkQueueSize(String queueName) { 856 long count = 0; 857 long queueSize = 0; 858 Map<ActiveMQDestination, Destination> destinationMap = regionBroker.getDestinationMap(); 859 for (Map.Entry<ActiveMQDestination, Destination> entry : destinationMap.entrySet()) { 860 if (entry.getKey().isQueue()) { 861 if (entry.getValue().getName().matches(queueName)) { 862 queueSize = entry.getValue().getDestinationStatistics().getMessages().getCount(); 863 count += queueSize; 864 if (queueSize > 0) { 865 LOG.info("Queue has pending message: {} queueSize is: {}", entry.getValue().getName(), queueSize); 866 } 867 } 868 } 869 } 870 return count == 0; 871 } 872 873 /** 874 * This method (both connectorName and queueName are using regex to match) 875 * 1. stop the connector (supposed the user input the connector which the 876 * clients connect to) 2. to check whether there is any pending message on 877 * the queues defined by queueName 3. supposedly, after stop the connector, 878 * client should failover to other broker and pending messages should be 879 * forwarded. if no pending messages, the method finally call stop to stop 880 * the broker. 881 * 882 * @param connectorName 883 * @param queueName 884 * @param timeout 885 * @param pollInterval 886 * @throws Exception 887 */ 888 public void stopGracefully(String connectorName, String queueName, long timeout, long pollInterval) throws Exception { 889 if (isUseJmx()) { 890 if (connectorName == null || queueName == null || timeout <= 0) { 891 throw new Exception( 892 "connectorName and queueName cannot be null and timeout should be >0 for stopGracefully."); 893 } 894 if (pollInterval <= 0) { 895 pollInterval = 30; 896 } 897 LOG.info("Stop gracefully with connectorName: {} queueName: {} timeout: {} pollInterval: {}", new Object[]{ 898 connectorName, queueName, timeout, pollInterval 899 }); 900 TransportConnector connector; 901 for (int i = 0; i < transportConnectors.size(); i++) { 902 connector = transportConnectors.get(i); 903 if (connector != null && connector.getName() != null && connector.getName().matches(connectorName)) { 904 connector.stop(); 905 } 906 } 907 long start = System.currentTimeMillis(); 908 while (System.currentTimeMillis() - start < timeout * 1000) { 909 // check quesize until it gets zero 910 if (checkQueueSize(queueName)) { 911 stop(); 912 break; 913 } else { 914 Thread.sleep(pollInterval * 1000); 915 } 916 } 917 if (stopped.get()) { 918 LOG.info("Successfully stop the broker."); 919 } else { 920 LOG.info("There is still pending message on the queue. Please check and stop the broker manually."); 921 } 922 } 923 } 924 925 /** 926 * A helper method to block the caller thread until the broker has been 927 * stopped 928 */ 929 public void waitUntilStopped() { 930 while (isStarted() && !stopped.get()) { 931 try { 932 stoppedLatch.await(); 933 } catch (InterruptedException e) { 934 // ignore 935 } 936 } 937 } 938 939 public boolean isStopped() { 940 return stopped.get(); 941 } 942 943 /** 944 * A helper method to block the caller thread until the broker has fully started 945 * @return boolean true if wait succeeded false if broker was not started or was stopped 946 */ 947 public boolean waitUntilStarted() { 948 return waitUntilStarted(DEFAULT_START_TIMEOUT); 949 } 950 951 /** 952 * A helper method to block the caller thread until the broker has fully started 953 * 954 * @param timeout 955 * the amount of time to wait before giving up and returning false. 956 * 957 * @return boolean true if wait succeeded false if broker was not started or was stopped 958 */ 959 public boolean waitUntilStarted(long timeout) { 960 boolean waitSucceeded = isStarted(); 961 long expiration = Math.max(0, timeout + System.currentTimeMillis()); 962 while (!isStarted() && !stopped.get() && !waitSucceeded && expiration > System.currentTimeMillis()) { 963 try { 964 if (startException != null) { 965 return waitSucceeded; 966 } 967 waitSucceeded = startedLatch.await(100L, TimeUnit.MILLISECONDS); 968 } catch (InterruptedException ignore) { 969 } 970 } 971 return waitSucceeded; 972 } 973 974 // Properties 975 // ------------------------------------------------------------------------- 976 /** 977 * Returns the message broker 978 */ 979 public Broker getBroker() throws Exception { 980 if (broker == null) { 981 broker = createBroker(); 982 } 983 return broker; 984 } 985 986 /** 987 * Returns the administration view of the broker; used to create and destroy 988 * resources such as queues and topics. Note this method returns null if JMX 989 * is disabled. 990 */ 991 public BrokerView getAdminView() throws Exception { 992 if (adminView == null) { 993 // force lazy creation 994 getBroker(); 995 } 996 return adminView; 997 } 998 999 public void setAdminView(BrokerView adminView) { 1000 this.adminView = adminView; 1001 } 1002 1003 public String getBrokerName() { 1004 return brokerName; 1005 } 1006 1007 /** 1008 * Sets the name of this broker; which must be unique in the network 1009 * 1010 * @param brokerName 1011 */ 1012 public void setBrokerName(String brokerName) { 1013 if (brokerName == null) { 1014 throw new NullPointerException("The broker name cannot be null"); 1015 } 1016 String str = brokerName.replaceAll("[^a-zA-Z0-9\\.\\_\\-\\:]", "_"); 1017 if (!str.equals(brokerName)) { 1018 LOG.error("Broker Name: {} contained illegal characters - replaced with {}", brokerName, str); 1019 } 1020 this.brokerName = str.trim(); 1021 } 1022 1023 public PersistenceAdapterFactory getPersistenceFactory() { 1024 return persistenceFactory; 1025 } 1026 1027 public File getDataDirectoryFile() { 1028 if (dataDirectoryFile == null) { 1029 dataDirectoryFile = new File(IOHelper.getDefaultDataDirectory()); 1030 } 1031 return dataDirectoryFile; 1032 } 1033 1034 public File getBrokerDataDirectory() { 1035 String brokerDir = getBrokerName(); 1036 return new File(getDataDirectoryFile(), brokerDir); 1037 } 1038 1039 /** 1040 * Sets the directory in which the data files will be stored by default for 1041 * the JDBC and Journal persistence adaptors. 1042 * 1043 * @param dataDirectory 1044 * the directory to store data files 1045 */ 1046 public void setDataDirectory(String dataDirectory) { 1047 setDataDirectoryFile(new File(dataDirectory)); 1048 } 1049 1050 /** 1051 * Sets the directory in which the data files will be stored by default for 1052 * the JDBC and Journal persistence adaptors. 1053 * 1054 * @param dataDirectoryFile 1055 * the directory to store data files 1056 */ 1057 public void setDataDirectoryFile(File dataDirectoryFile) { 1058 this.dataDirectoryFile = dataDirectoryFile; 1059 } 1060 1061 /** 1062 * @return the tmpDataDirectory 1063 */ 1064 public File getTmpDataDirectory() { 1065 if (tmpDataDirectory == null) { 1066 tmpDataDirectory = new File(getBrokerDataDirectory(), "tmp_storage"); 1067 } 1068 return tmpDataDirectory; 1069 } 1070 1071 /** 1072 * @param tmpDataDirectory 1073 * the tmpDataDirectory to set 1074 */ 1075 public void setTmpDataDirectory(File tmpDataDirectory) { 1076 this.tmpDataDirectory = tmpDataDirectory; 1077 } 1078 1079 public void setPersistenceFactory(PersistenceAdapterFactory persistenceFactory) { 1080 this.persistenceFactory = persistenceFactory; 1081 } 1082 1083 public void setDestinationFactory(DestinationFactory destinationFactory) { 1084 this.destinationFactory = destinationFactory; 1085 } 1086 1087 public boolean isPersistent() { 1088 return persistent; 1089 } 1090 1091 /** 1092 * Sets whether or not persistence is enabled or disabled. 1093 * @org.apache.xbean.Property propertyEditor="org.apache.activemq.util.BooleanEditor" 1094 */ 1095 public void setPersistent(boolean persistent) { 1096 this.persistent = persistent; 1097 } 1098 1099 public boolean isPopulateJMSXUserID() { 1100 return populateJMSXUserID; 1101 } 1102 1103 /** 1104 * Sets whether or not the broker should populate the JMSXUserID header. 1105 */ 1106 public void setPopulateJMSXUserID(boolean populateJMSXUserID) { 1107 this.populateJMSXUserID = populateJMSXUserID; 1108 } 1109 1110 public SystemUsage getSystemUsage() { 1111 try { 1112 if (systemUsage == null) { 1113 1114 systemUsage = new SystemUsage("Main", getPersistenceAdapter(), getTempDataStore(), getJobSchedulerStore()); 1115 systemUsage.setExecutor(getExecutor()); 1116 systemUsage.getMemoryUsage().setLimit(1024L * 1024 * 1024 * 1); // 1 GB 1117 systemUsage.getTempUsage().setLimit(1024L * 1024 * 1024 * 50); // 50 GB 1118 systemUsage.getStoreUsage().setLimit(1024L * 1024 * 1024 * 100); // 100 GB 1119 systemUsage.getJobSchedulerUsage().setLimit(1024L * 1024 * 1024 * 50); // 50 GB 1120 addService(this.systemUsage); 1121 } 1122 return systemUsage; 1123 } catch (IOException e) { 1124 LOG.error("Cannot create SystemUsage", e); 1125 throw new RuntimeException("Fatally failed to create SystemUsage" + e.getMessage(), e); 1126 } 1127 } 1128 1129 public void setSystemUsage(SystemUsage memoryManager) { 1130 if (this.systemUsage != null) { 1131 removeService(this.systemUsage); 1132 } 1133 this.systemUsage = memoryManager; 1134 if (this.systemUsage.getExecutor()==null) { 1135 this.systemUsage.setExecutor(getExecutor()); 1136 } 1137 addService(this.systemUsage); 1138 } 1139 1140 /** 1141 * @return the consumerUsageManager 1142 * @throws IOException 1143 */ 1144 public SystemUsage getConsumerSystemUsage() throws IOException { 1145 if (this.consumerSystemUsaage == null) { 1146 if (splitSystemUsageForProducersConsumers) { 1147 this.consumerSystemUsaage = new SystemUsage(getSystemUsage(), "Consumer"); 1148 float portion = consumerSystemUsagePortion / 100f; 1149 this.consumerSystemUsaage.getMemoryUsage().setUsagePortion(portion); 1150 addService(this.consumerSystemUsaage); 1151 } else { 1152 consumerSystemUsaage = getSystemUsage(); 1153 } 1154 } 1155 return this.consumerSystemUsaage; 1156 } 1157 1158 /** 1159 * @param consumerSystemUsaage 1160 * the storeSystemUsage to set 1161 */ 1162 public void setConsumerSystemUsage(SystemUsage consumerSystemUsaage) { 1163 if (this.consumerSystemUsaage != null) { 1164 removeService(this.consumerSystemUsaage); 1165 } 1166 this.consumerSystemUsaage = consumerSystemUsaage; 1167 addService(this.consumerSystemUsaage); 1168 } 1169 1170 /** 1171 * @return the producerUsageManager 1172 * @throws IOException 1173 */ 1174 public SystemUsage getProducerSystemUsage() throws IOException { 1175 if (producerSystemUsage == null) { 1176 if (splitSystemUsageForProducersConsumers) { 1177 producerSystemUsage = new SystemUsage(getSystemUsage(), "Producer"); 1178 float portion = producerSystemUsagePortion / 100f; 1179 producerSystemUsage.getMemoryUsage().setUsagePortion(portion); 1180 addService(producerSystemUsage); 1181 } else { 1182 producerSystemUsage = getSystemUsage(); 1183 } 1184 } 1185 return producerSystemUsage; 1186 } 1187 1188 /** 1189 * @param producerUsageManager 1190 * the producerUsageManager to set 1191 */ 1192 public void setProducerSystemUsage(SystemUsage producerUsageManager) { 1193 if (this.producerSystemUsage != null) { 1194 removeService(this.producerSystemUsage); 1195 } 1196 this.producerSystemUsage = producerUsageManager; 1197 addService(this.producerSystemUsage); 1198 } 1199 1200 public PersistenceAdapter getPersistenceAdapter() throws IOException { 1201 if (persistenceAdapter == null) { 1202 persistenceAdapter = createPersistenceAdapter(); 1203 configureService(persistenceAdapter); 1204 this.persistenceAdapter = registerPersistenceAdapterMBean(persistenceAdapter); 1205 } 1206 return persistenceAdapter; 1207 } 1208 1209 /** 1210 * Sets the persistence adaptor implementation to use for this broker 1211 * 1212 * @throws IOException 1213 */ 1214 public void setPersistenceAdapter(PersistenceAdapter persistenceAdapter) throws IOException { 1215 if (!isPersistent() && ! (persistenceAdapter instanceof MemoryPersistenceAdapter)) { 1216 LOG.warn("persistent=\"false\", ignoring configured persistenceAdapter: {}", persistenceAdapter); 1217 return; 1218 } 1219 this.persistenceAdapter = persistenceAdapter; 1220 configureService(this.persistenceAdapter); 1221 this.persistenceAdapter = registerPersistenceAdapterMBean(persistenceAdapter); 1222 } 1223 1224 public TaskRunnerFactory getTaskRunnerFactory() { 1225 if (this.taskRunnerFactory == null) { 1226 this.taskRunnerFactory = new TaskRunnerFactory("ActiveMQ BrokerService["+getBrokerName()+"] Task", getTaskRunnerPriority(), true, 1000, 1227 isDedicatedTaskRunner()); 1228 this.taskRunnerFactory.setThreadClassLoader(this.getClass().getClassLoader()); 1229 } 1230 return this.taskRunnerFactory; 1231 } 1232 1233 public void setTaskRunnerFactory(TaskRunnerFactory taskRunnerFactory) { 1234 this.taskRunnerFactory = taskRunnerFactory; 1235 } 1236 1237 public TaskRunnerFactory getPersistenceTaskRunnerFactory() { 1238 if (taskRunnerFactory == null) { 1239 persistenceTaskRunnerFactory = new TaskRunnerFactory("Persistence Adaptor Task", persistenceThreadPriority, 1240 true, 1000, isDedicatedTaskRunner()); 1241 } 1242 return persistenceTaskRunnerFactory; 1243 } 1244 1245 public void setPersistenceTaskRunnerFactory(TaskRunnerFactory persistenceTaskRunnerFactory) { 1246 this.persistenceTaskRunnerFactory = persistenceTaskRunnerFactory; 1247 } 1248 1249 public boolean isUseJmx() { 1250 return useJmx; 1251 } 1252 1253 public boolean isEnableStatistics() { 1254 return enableStatistics; 1255 } 1256 1257 /** 1258 * Sets whether or not the Broker's services enable statistics or not. 1259 */ 1260 public void setEnableStatistics(boolean enableStatistics) { 1261 this.enableStatistics = enableStatistics; 1262 } 1263 1264 /** 1265 * Sets whether or not the Broker's services should be exposed into JMX or 1266 * not. 1267 * @org.apache.xbean.Property propertyEditor="org.apache.activemq.util.BooleanEditor" 1268 */ 1269 public void setUseJmx(boolean useJmx) { 1270 this.useJmx = useJmx; 1271 } 1272 1273 public ObjectName getBrokerObjectName() throws MalformedObjectNameException { 1274 if (brokerObjectName == null) { 1275 brokerObjectName = createBrokerObjectName(); 1276 } 1277 return brokerObjectName; 1278 } 1279 1280 /** 1281 * Sets the JMX ObjectName for this broker 1282 */ 1283 public void setBrokerObjectName(ObjectName brokerObjectName) { 1284 this.brokerObjectName = brokerObjectName; 1285 } 1286 1287 public ManagementContext getManagementContext() { 1288 if (managementContext == null) { 1289 managementContext = new ManagementContext(); 1290 } 1291 return managementContext; 1292 } 1293 1294 public void setManagementContext(ManagementContext managementContext) { 1295 this.managementContext = managementContext; 1296 } 1297 1298 public NetworkConnector getNetworkConnectorByName(String connectorName) { 1299 for (NetworkConnector connector : networkConnectors) { 1300 if (connector.getName().equals(connectorName)) { 1301 return connector; 1302 } 1303 } 1304 return null; 1305 } 1306 1307 public String[] getNetworkConnectorURIs() { 1308 return networkConnectorURIs; 1309 } 1310 1311 public void setNetworkConnectorURIs(String[] networkConnectorURIs) { 1312 this.networkConnectorURIs = networkConnectorURIs; 1313 } 1314 1315 public TransportConnector getConnectorByName(String connectorName) { 1316 for (TransportConnector connector : transportConnectors) { 1317 if (connector.getName().equals(connectorName)) { 1318 return connector; 1319 } 1320 } 1321 return null; 1322 } 1323 1324 public Map<String, String> getTransportConnectorURIsAsMap() { 1325 Map<String, String> answer = new HashMap<String, String>(); 1326 for (TransportConnector connector : transportConnectors) { 1327 try { 1328 URI uri = connector.getConnectUri(); 1329 if (uri != null) { 1330 String scheme = uri.getScheme(); 1331 if (scheme != null) { 1332 answer.put(scheme.toLowerCase(Locale.ENGLISH), uri.toString()); 1333 } 1334 } 1335 } catch (Exception e) { 1336 LOG.debug("Failed to read URI to build transportURIsAsMap", e); 1337 } 1338 } 1339 return answer; 1340 } 1341 1342 public ProducerBrokerExchange getProducerBrokerExchange(ProducerInfo producerInfo){ 1343 ProducerBrokerExchange result = null; 1344 1345 for (TransportConnector connector : transportConnectors) { 1346 for (TransportConnection tc: connector.getConnections()){ 1347 result = tc.getProducerBrokerExchangeIfExists(producerInfo); 1348 if (result !=null){ 1349 return result; 1350 } 1351 } 1352 } 1353 return result; 1354 } 1355 1356 public String[] getTransportConnectorURIs() { 1357 return transportConnectorURIs; 1358 } 1359 1360 public void setTransportConnectorURIs(String[] transportConnectorURIs) { 1361 this.transportConnectorURIs = transportConnectorURIs; 1362 } 1363 1364 /** 1365 * @return Returns the jmsBridgeConnectors. 1366 */ 1367 public JmsConnector[] getJmsBridgeConnectors() { 1368 return jmsBridgeConnectors; 1369 } 1370 1371 /** 1372 * @param jmsConnectors 1373 * The jmsBridgeConnectors to set. 1374 */ 1375 public void setJmsBridgeConnectors(JmsConnector[] jmsConnectors) { 1376 this.jmsBridgeConnectors = jmsConnectors; 1377 } 1378 1379 public Service[] getServices() { 1380 return services.toArray(new Service[0]); 1381 } 1382 1383 /** 1384 * Sets the services associated with this broker. 1385 */ 1386 public void setServices(Service[] services) { 1387 this.services.clear(); 1388 if (services != null) { 1389 for (int i = 0; i < services.length; i++) { 1390 this.services.add(services[i]); 1391 } 1392 } 1393 } 1394 1395 /** 1396 * Adds a new service so that it will be started as part of the broker 1397 * lifecycle 1398 */ 1399 public void addService(Service service) { 1400 services.add(service); 1401 } 1402 1403 public void removeService(Service service) { 1404 services.remove(service); 1405 } 1406 1407 public boolean isUseLoggingForShutdownErrors() { 1408 return useLoggingForShutdownErrors; 1409 } 1410 1411 /** 1412 * Sets whether or not we should use commons-logging when reporting errors 1413 * when shutting down the broker 1414 */ 1415 public void setUseLoggingForShutdownErrors(boolean useLoggingForShutdownErrors) { 1416 this.useLoggingForShutdownErrors = useLoggingForShutdownErrors; 1417 } 1418 1419 public boolean isUseShutdownHook() { 1420 return useShutdownHook; 1421 } 1422 1423 /** 1424 * Sets whether or not we should use a shutdown handler to close down the 1425 * broker cleanly if the JVM is terminated. It is recommended you leave this 1426 * enabled. 1427 */ 1428 public void setUseShutdownHook(boolean useShutdownHook) { 1429 this.useShutdownHook = useShutdownHook; 1430 } 1431 1432 public boolean isAdvisorySupport() { 1433 return advisorySupport; 1434 } 1435 1436 /** 1437 * Allows the support of advisory messages to be disabled for performance 1438 * reasons. 1439 * @org.apache.xbean.Property propertyEditor="org.apache.activemq.util.BooleanEditor" 1440 */ 1441 public void setAdvisorySupport(boolean advisorySupport) { 1442 this.advisorySupport = advisorySupport; 1443 } 1444 1445 public List<TransportConnector> getTransportConnectors() { 1446 return new ArrayList<TransportConnector>(transportConnectors); 1447 } 1448 1449 /** 1450 * Sets the transport connectors which this broker will listen on for new 1451 * clients 1452 * 1453 * @org.apache.xbean.Property 1454 * nestedType="org.apache.activemq.broker.TransportConnector" 1455 */ 1456 public void setTransportConnectors(List<TransportConnector> transportConnectors) throws Exception { 1457 for (TransportConnector connector : transportConnectors) { 1458 addConnector(connector); 1459 } 1460 } 1461 1462 public TransportConnector getTransportConnectorByName(String name){ 1463 for (TransportConnector transportConnector : transportConnectors){ 1464 if (name.equals(transportConnector.getName())){ 1465 return transportConnector; 1466 } 1467 } 1468 return null; 1469 } 1470 1471 public TransportConnector getTransportConnectorByScheme(String scheme){ 1472 for (TransportConnector transportConnector : transportConnectors){ 1473 if (scheme.equals(transportConnector.getUri().getScheme())){ 1474 return transportConnector; 1475 } 1476 } 1477 return null; 1478 } 1479 1480 public List<NetworkConnector> getNetworkConnectors() { 1481 return new ArrayList<NetworkConnector>(networkConnectors); 1482 } 1483 1484 public List<ProxyConnector> getProxyConnectors() { 1485 return new ArrayList<ProxyConnector>(proxyConnectors); 1486 } 1487 1488 /** 1489 * Sets the network connectors which this broker will use to connect to 1490 * other brokers in a federated network 1491 * 1492 * @org.apache.xbean.Property 1493 * nestedType="org.apache.activemq.network.NetworkConnector" 1494 */ 1495 public void setNetworkConnectors(List<?> networkConnectors) throws Exception { 1496 for (Object connector : networkConnectors) { 1497 addNetworkConnector((NetworkConnector) connector); 1498 } 1499 } 1500 1501 /** 1502 * Sets the network connectors which this broker will use to connect to 1503 * other brokers in a federated network 1504 */ 1505 public void setProxyConnectors(List<?> proxyConnectors) throws Exception { 1506 for (Object connector : proxyConnectors) { 1507 addProxyConnector((ProxyConnector) connector); 1508 } 1509 } 1510 1511 public PolicyMap getDestinationPolicy() { 1512 return destinationPolicy; 1513 } 1514 1515 /** 1516 * Sets the destination specific policies available either for exact 1517 * destinations or for wildcard areas of destinations. 1518 */ 1519 public void setDestinationPolicy(PolicyMap policyMap) { 1520 this.destinationPolicy = policyMap; 1521 } 1522 1523 public BrokerPlugin[] getPlugins() { 1524 return plugins; 1525 } 1526 1527 /** 1528 * Sets a number of broker plugins to install such as for security 1529 * authentication or authorization 1530 */ 1531 public void setPlugins(BrokerPlugin[] plugins) { 1532 this.plugins = plugins; 1533 } 1534 1535 public MessageAuthorizationPolicy getMessageAuthorizationPolicy() { 1536 return messageAuthorizationPolicy; 1537 } 1538 1539 /** 1540 * Sets the policy used to decide if the current connection is authorized to 1541 * consume a given message 1542 */ 1543 public void setMessageAuthorizationPolicy(MessageAuthorizationPolicy messageAuthorizationPolicy) { 1544 this.messageAuthorizationPolicy = messageAuthorizationPolicy; 1545 } 1546 1547 /** 1548 * Delete all messages from the persistent store 1549 * 1550 * @throws IOException 1551 */ 1552 public void deleteAllMessages() throws IOException { 1553 getPersistenceAdapter().deleteAllMessages(); 1554 } 1555 1556 public boolean isDeleteAllMessagesOnStartup() { 1557 return deleteAllMessagesOnStartup; 1558 } 1559 1560 /** 1561 * Sets whether or not all messages are deleted on startup - mostly only 1562 * useful for testing. 1563 * @org.apache.xbean.Property propertyEditor="org.apache.activemq.util.BooleanEditor" 1564 */ 1565 public void setDeleteAllMessagesOnStartup(boolean deletePersistentMessagesOnStartup) { 1566 this.deleteAllMessagesOnStartup = deletePersistentMessagesOnStartup; 1567 } 1568 1569 public URI getVmConnectorURI() { 1570 if (vmConnectorURI == null) { 1571 try { 1572 vmConnectorURI = new URI("vm://" + getBrokerName().replaceAll("[^a-zA-Z0-9\\.\\_\\-]", "_")); 1573 } catch (URISyntaxException e) { 1574 LOG.error("Badly formed URI from {}", getBrokerName(), e); 1575 } 1576 } 1577 return vmConnectorURI; 1578 } 1579 1580 public void setVmConnectorURI(URI vmConnectorURI) { 1581 this.vmConnectorURI = vmConnectorURI; 1582 } 1583 1584 public String getDefaultSocketURIString() { 1585 if (started.get()) { 1586 if (this.defaultSocketURIString == null) { 1587 for (TransportConnector tc:this.transportConnectors) { 1588 String result = null; 1589 try { 1590 result = tc.getPublishableConnectString(); 1591 } catch (Exception e) { 1592 LOG.warn("Failed to get the ConnectURI for {}", tc, e); 1593 } 1594 if (result != null) { 1595 // find first publishable uri 1596 if (tc.isUpdateClusterClients() || tc.isRebalanceClusterClients()) { 1597 this.defaultSocketURIString = result; 1598 break; 1599 } else { 1600 // or use the first defined 1601 if (this.defaultSocketURIString == null) { 1602 this.defaultSocketURIString = result; 1603 } 1604 } 1605 } 1606 } 1607 1608 } 1609 return this.defaultSocketURIString; 1610 } 1611 return null; 1612 } 1613 1614 /** 1615 * @return Returns the shutdownOnMasterFailure. 1616 */ 1617 public boolean isShutdownOnMasterFailure() { 1618 return shutdownOnMasterFailure; 1619 } 1620 1621 /** 1622 * @param shutdownOnMasterFailure 1623 * The shutdownOnMasterFailure to set. 1624 */ 1625 public void setShutdownOnMasterFailure(boolean shutdownOnMasterFailure) { 1626 this.shutdownOnMasterFailure = shutdownOnMasterFailure; 1627 } 1628 1629 public boolean isKeepDurableSubsActive() { 1630 return keepDurableSubsActive; 1631 } 1632 1633 public void setKeepDurableSubsActive(boolean keepDurableSubsActive) { 1634 this.keepDurableSubsActive = keepDurableSubsActive; 1635 } 1636 1637 public boolean isUseVirtualTopics() { 1638 return useVirtualTopics; 1639 } 1640 1641 /** 1642 * Sets whether or not <a 1643 * href="http://activemq.apache.org/virtual-destinations.html">Virtual 1644 * Topics</a> should be supported by default if they have not been 1645 * explicitly configured. 1646 */ 1647 public void setUseVirtualTopics(boolean useVirtualTopics) { 1648 this.useVirtualTopics = useVirtualTopics; 1649 } 1650 1651 public DestinationInterceptor[] getDestinationInterceptors() { 1652 return destinationInterceptors; 1653 } 1654 1655 public boolean isUseMirroredQueues() { 1656 return useMirroredQueues; 1657 } 1658 1659 /** 1660 * Sets whether or not <a 1661 * href="http://activemq.apache.org/mirrored-queues.html">Mirrored 1662 * Queues</a> should be supported by default if they have not been 1663 * explicitly configured. 1664 */ 1665 public void setUseMirroredQueues(boolean useMirroredQueues) { 1666 this.useMirroredQueues = useMirroredQueues; 1667 } 1668 1669 /** 1670 * Sets the destination interceptors to use 1671 */ 1672 public void setDestinationInterceptors(DestinationInterceptor[] destinationInterceptors) { 1673 this.destinationInterceptors = destinationInterceptors; 1674 } 1675 1676 public ActiveMQDestination[] getDestinations() { 1677 return destinations; 1678 } 1679 1680 /** 1681 * Sets the destinations which should be loaded/created on startup 1682 */ 1683 public void setDestinations(ActiveMQDestination[] destinations) { 1684 this.destinations = destinations; 1685 } 1686 1687 /** 1688 * @return the tempDataStore 1689 */ 1690 public synchronized PListStore getTempDataStore() { 1691 if (tempDataStore == null) { 1692 if (!isPersistent()) { 1693 return null; 1694 } 1695 1696 try { 1697 PersistenceAdapter pa = getPersistenceAdapter(); 1698 if( pa!=null && pa instanceof PListStore) { 1699 return (PListStore) pa; 1700 } 1701 } catch (IOException e) { 1702 throw new RuntimeException(e); 1703 } 1704 1705 boolean result = true; 1706 boolean empty = true; 1707 try { 1708 File directory = getTmpDataDirectory(); 1709 if (directory.exists() && directory.isDirectory()) { 1710 File[] files = directory.listFiles(); 1711 if (files != null && files.length > 0) { 1712 empty = false; 1713 for (int i = 0; i < files.length; i++) { 1714 File file = files[i]; 1715 if (!file.isDirectory()) { 1716 result &= file.delete(); 1717 } 1718 } 1719 } 1720 } 1721 if (!empty) { 1722 String str = result ? "Successfully deleted" : "Failed to delete"; 1723 LOG.info("{} temporary storage", str); 1724 } 1725 1726 String clazz = "org.apache.activemq.store.kahadb.plist.PListStoreImpl"; 1727 this.tempDataStore = (PListStore) getClass().getClassLoader().loadClass(clazz).newInstance(); 1728 this.tempDataStore.setDirectory(getTmpDataDirectory()); 1729 configureService(tempDataStore); 1730 this.tempDataStore.start(); 1731 } catch (Exception e) { 1732 throw new RuntimeException(e); 1733 } 1734 } 1735 return tempDataStore; 1736 } 1737 1738 /** 1739 * @param tempDataStore 1740 * the tempDataStore to set 1741 */ 1742 public void setTempDataStore(PListStore tempDataStore) { 1743 this.tempDataStore = tempDataStore; 1744 configureService(tempDataStore); 1745 try { 1746 tempDataStore.start(); 1747 } catch (Exception e) { 1748 RuntimeException exception = new RuntimeException("Failed to start provided temp data store: " + tempDataStore, e); 1749 LOG.error(exception.getLocalizedMessage(), e); 1750 throw exception; 1751 } 1752 } 1753 1754 public int getPersistenceThreadPriority() { 1755 return persistenceThreadPriority; 1756 } 1757 1758 public void setPersistenceThreadPriority(int persistenceThreadPriority) { 1759 this.persistenceThreadPriority = persistenceThreadPriority; 1760 } 1761 1762 /** 1763 * @return the useLocalHostBrokerName 1764 */ 1765 public boolean isUseLocalHostBrokerName() { 1766 return this.useLocalHostBrokerName; 1767 } 1768 1769 /** 1770 * @param useLocalHostBrokerName 1771 * the useLocalHostBrokerName to set 1772 */ 1773 public void setUseLocalHostBrokerName(boolean useLocalHostBrokerName) { 1774 this.useLocalHostBrokerName = useLocalHostBrokerName; 1775 if (useLocalHostBrokerName && !started.get() && brokerName == null || brokerName == DEFAULT_BROKER_NAME) { 1776 brokerName = LOCAL_HOST_NAME; 1777 } 1778 } 1779 1780 /** 1781 * Looks up and lazily creates if necessary the destination for the given 1782 * JMS name 1783 */ 1784 public Destination getDestination(ActiveMQDestination destination) throws Exception { 1785 return getBroker().addDestination(getAdminConnectionContext(), destination,false); 1786 } 1787 1788 public void removeDestination(ActiveMQDestination destination) throws Exception { 1789 getBroker().removeDestination(getAdminConnectionContext(), destination, 0); 1790 } 1791 1792 public int getProducerSystemUsagePortion() { 1793 return producerSystemUsagePortion; 1794 } 1795 1796 public void setProducerSystemUsagePortion(int producerSystemUsagePortion) { 1797 this.producerSystemUsagePortion = producerSystemUsagePortion; 1798 } 1799 1800 public int getConsumerSystemUsagePortion() { 1801 return consumerSystemUsagePortion; 1802 } 1803 1804 public void setConsumerSystemUsagePortion(int consumerSystemUsagePortion) { 1805 this.consumerSystemUsagePortion = consumerSystemUsagePortion; 1806 } 1807 1808 public boolean isSplitSystemUsageForProducersConsumers() { 1809 return splitSystemUsageForProducersConsumers; 1810 } 1811 1812 public void setSplitSystemUsageForProducersConsumers(boolean splitSystemUsageForProducersConsumers) { 1813 this.splitSystemUsageForProducersConsumers = splitSystemUsageForProducersConsumers; 1814 } 1815 1816 public boolean isMonitorConnectionSplits() { 1817 return monitorConnectionSplits; 1818 } 1819 1820 public void setMonitorConnectionSplits(boolean monitorConnectionSplits) { 1821 this.monitorConnectionSplits = monitorConnectionSplits; 1822 } 1823 1824 public int getTaskRunnerPriority() { 1825 return taskRunnerPriority; 1826 } 1827 1828 public void setTaskRunnerPriority(int taskRunnerPriority) { 1829 this.taskRunnerPriority = taskRunnerPriority; 1830 } 1831 1832 public boolean isDedicatedTaskRunner() { 1833 return dedicatedTaskRunner; 1834 } 1835 1836 public void setDedicatedTaskRunner(boolean dedicatedTaskRunner) { 1837 this.dedicatedTaskRunner = dedicatedTaskRunner; 1838 } 1839 1840 public boolean isCacheTempDestinations() { 1841 return cacheTempDestinations; 1842 } 1843 1844 public void setCacheTempDestinations(boolean cacheTempDestinations) { 1845 this.cacheTempDestinations = cacheTempDestinations; 1846 } 1847 1848 public int getTimeBeforePurgeTempDestinations() { 1849 return timeBeforePurgeTempDestinations; 1850 } 1851 1852 public void setTimeBeforePurgeTempDestinations(int timeBeforePurgeTempDestinations) { 1853 this.timeBeforePurgeTempDestinations = timeBeforePurgeTempDestinations; 1854 } 1855 1856 public boolean isUseTempMirroredQueues() { 1857 return useTempMirroredQueues; 1858 } 1859 1860 public void setUseTempMirroredQueues(boolean useTempMirroredQueues) { 1861 this.useTempMirroredQueues = useTempMirroredQueues; 1862 } 1863 1864 public synchronized JobSchedulerStore getJobSchedulerStore() { 1865 1866 // If support is off don't allow any scheduler even is user configured their own. 1867 if (!isSchedulerSupport()) { 1868 return null; 1869 } 1870 1871 // If the user configured their own we use it even if persistence is disabled since 1872 // we don't know anything about their implementation. 1873 if (jobSchedulerStore == null) { 1874 1875 if (!isPersistent()) { 1876 this.jobSchedulerStore = new InMemoryJobSchedulerStore(); 1877 configureService(jobSchedulerStore); 1878 return this.jobSchedulerStore; 1879 } 1880 1881 try { 1882 PersistenceAdapter pa = getPersistenceAdapter(); 1883 if (pa != null) { 1884 this.jobSchedulerStore = pa.createJobSchedulerStore(); 1885 jobSchedulerStore.setDirectory(getSchedulerDirectoryFile()); 1886 configureService(jobSchedulerStore); 1887 return this.jobSchedulerStore; 1888 } 1889 } catch (IOException e) { 1890 throw new RuntimeException(e); 1891 } catch (UnsupportedOperationException ex) { 1892 // It's ok if the store doesn't implement a scheduler. 1893 } catch (Exception e) { 1894 throw new RuntimeException(e); 1895 } 1896 1897 try { 1898 PersistenceAdapter pa = getPersistenceAdapter(); 1899 if (pa != null && pa instanceof JobSchedulerStore) { 1900 this.jobSchedulerStore = (JobSchedulerStore) pa; 1901 configureService(jobSchedulerStore); 1902 return this.jobSchedulerStore; 1903 } 1904 } catch (IOException e) { 1905 throw new RuntimeException(e); 1906 } 1907 1908 // Load the KahaDB store as a last resort, this only works if KahaDB is 1909 // included at runtime, otherwise this will fail. User should disable 1910 // scheduler support if this fails. 1911 try { 1912 String clazz = "org.apache.activemq.store.kahadb.KahaDBPersistenceAdapter"; 1913 PersistenceAdapter adaptor = (PersistenceAdapter)getClass().getClassLoader().loadClass(clazz).newInstance(); 1914 jobSchedulerStore = adaptor.createJobSchedulerStore(); 1915 jobSchedulerStore.setDirectory(getSchedulerDirectoryFile()); 1916 configureService(jobSchedulerStore); 1917 LOG.info("JobScheduler using directory: {}", getSchedulerDirectoryFile()); 1918 } catch (Exception e) { 1919 throw new RuntimeException(e); 1920 } 1921 } 1922 return jobSchedulerStore; 1923 } 1924 1925 public void setJobSchedulerStore(JobSchedulerStore jobSchedulerStore) { 1926 this.jobSchedulerStore = jobSchedulerStore; 1927 configureService(jobSchedulerStore); 1928 } 1929 1930 // 1931 // Implementation methods 1932 // ------------------------------------------------------------------------- 1933 /** 1934 * Handles any lazy-creation helper properties which are added to make 1935 * things easier to configure inside environments such as Spring 1936 * 1937 * @throws Exception 1938 */ 1939 protected void processHelperProperties() throws Exception { 1940 if (transportConnectorURIs != null) { 1941 for (int i = 0; i < transportConnectorURIs.length; i++) { 1942 String uri = transportConnectorURIs[i]; 1943 addConnector(uri); 1944 } 1945 } 1946 if (networkConnectorURIs != null) { 1947 for (int i = 0; i < networkConnectorURIs.length; i++) { 1948 String uri = networkConnectorURIs[i]; 1949 addNetworkConnector(uri); 1950 } 1951 } 1952 if (jmsBridgeConnectors != null) { 1953 for (int i = 0; i < jmsBridgeConnectors.length; i++) { 1954 addJmsConnector(jmsBridgeConnectors[i]); 1955 } 1956 } 1957 } 1958 1959 /** 1960 * Check that the store usage limit is not greater than max usable 1961 * space and adjust if it is 1962 */ 1963 protected void checkStoreUsageLimits() throws IOException { 1964 final SystemUsage usage = getSystemUsage(); 1965 1966 if (getPersistenceAdapter() != null) { 1967 PersistenceAdapter adapter = getPersistenceAdapter(); 1968 File dir = adapter.getDirectory(); 1969 1970 if (dir != null) { 1971 String dirPath = dir.getAbsolutePath(); 1972 if (!dir.isAbsolute()) { 1973 dir = new File(dirPath); 1974 } 1975 1976 while (dir != null && !dir.isDirectory()) { 1977 dir = dir.getParentFile(); 1978 } 1979 long storeLimit = usage.getStoreUsage().getLimit(); 1980 long storeCurrent = usage.getStoreUsage().getUsage(); 1981 long dirFreeSpace = dir.getUsableSpace(); 1982 if (storeLimit > (dirFreeSpace + storeCurrent)) { 1983 LOG.warn("Store limit is " + storeLimit / (1024 * 1024) + 1984 " mb (current store usage is " + storeCurrent / (1024 * 1024) + 1985 " mb). The data directory: " + dir.getAbsolutePath() + 1986 " only has " + dirFreeSpace / (1024 * 1024) + 1987 " mb of usable space - resetting to maximum available disk space: " + 1988 (dirFreeSpace + storeCurrent) / (1024 * 1024) + " mb"); 1989 usage.getStoreUsage().setLimit(dirFreeSpace + storeCurrent); 1990 } 1991 } 1992 1993 long maxJournalFileSize = 0; 1994 long storeLimit = usage.getStoreUsage().getLimit(); 1995 1996 if (adapter instanceof JournaledStore) { 1997 maxJournalFileSize = ((JournaledStore) adapter).getJournalMaxFileLength(); 1998 } 1999 2000 if (storeLimit < maxJournalFileSize) { 2001 LOG.error("Store limit is " + storeLimit / (1024 * 1024) + 2002 " mb, whilst the max journal file size for the store is: " + 2003 maxJournalFileSize / (1024 * 1024) + " mb, " + 2004 "the store will not accept any data when used."); 2005 2006 } 2007 } 2008 } 2009 2010 /** 2011 * Check that temporary usage limit is not greater than max usable 2012 * space and adjust if it is 2013 */ 2014 protected void checkTmpStoreUsageLimits() throws IOException { 2015 final SystemUsage usage = getSystemUsage(); 2016 2017 File tmpDir = getTmpDataDirectory(); 2018 if (tmpDir != null) { 2019 2020 String tmpDirPath = tmpDir.getAbsolutePath(); 2021 if (!tmpDir.isAbsolute()) { 2022 tmpDir = new File(tmpDirPath); 2023 } 2024 2025 long storeLimit = usage.getTempUsage().getLimit(); 2026 long storeCurrent = usage.getTempUsage().getUsage(); 2027 while (tmpDir != null && !tmpDir.isDirectory()) { 2028 tmpDir = tmpDir.getParentFile(); 2029 } 2030 long dirFreeSpace = tmpDir.getUsableSpace(); 2031 if (storeLimit > (dirFreeSpace + storeCurrent)) { 2032 LOG.warn("Temporary Store limit is " + storeLimit / (1024 * 1024) + 2033 " mb (current temporary store usage is " + storeCurrent / (1024 * 1024) + 2034 " mb). The temporary data directory: " + tmpDir.getAbsolutePath() + 2035 " only has " + dirFreeSpace / (1024 * 1024) + 2036 " mb of usable space - resetting to maximum available disk space: " + 2037 (dirFreeSpace + storeCurrent) / (1024 * 1024) + " mb"); 2038 usage.getTempUsage().setLimit(dirFreeSpace + storeCurrent); 2039 } 2040 2041 if (isPersistent()) { 2042 long maxJournalFileSize; 2043 2044 PListStore store = usage.getTempUsage().getStore(); 2045 if (store != null && store instanceof JournaledStore) { 2046 maxJournalFileSize = ((JournaledStore) store).getJournalMaxFileLength(); 2047 } else { 2048 maxJournalFileSize = DEFAULT_MAX_FILE_LENGTH; 2049 } 2050 2051 if (storeLimit < maxJournalFileSize) { 2052 LOG.error("Temporary Store limit is " + storeLimit / (1024 * 1024) + 2053 " mb, whilst the max journal file size for the temporary store is: " + 2054 maxJournalFileSize / (1024 * 1024) + " mb, " + 2055 "the temp store will not accept any data when used."); 2056 } 2057 } 2058 } 2059 } 2060 2061 /** 2062 * Schedules a periodic task based on schedulePeriodForDiskLimitCheck to 2063 * update store and temporary store limits if the amount of available space 2064 * plus current store size is less than the existin configured limit 2065 */ 2066 protected void scheduleDiskUsageLimitsCheck() throws IOException { 2067 if (schedulePeriodForDiskUsageCheck > 0 && 2068 (getPersistenceAdapter() != null || getTmpDataDirectory() != null)) { 2069 Runnable diskLimitCheckTask = new Runnable() { 2070 @Override 2071 public void run() { 2072 try { 2073 checkStoreUsageLimits(); 2074 } catch (IOException e) { 2075 LOG.error("Failed to check persistent disk usage limits", e); 2076 } 2077 2078 try { 2079 checkTmpStoreUsageLimits(); 2080 } catch (IOException e) { 2081 LOG.error("Failed to check temporary store usage limits", e); 2082 } 2083 } 2084 }; 2085 scheduler.executePeriodically(diskLimitCheckTask, schedulePeriodForDiskUsageCheck); 2086 } 2087 } 2088 2089 protected void checkSystemUsageLimits() throws IOException { 2090 final SystemUsage usage = getSystemUsage(); 2091 long memLimit = usage.getMemoryUsage().getLimit(); 2092 long jvmLimit = Runtime.getRuntime().maxMemory(); 2093 2094 if (memLimit > jvmLimit) { 2095 usage.getMemoryUsage().setPercentOfJvmHeap(70); 2096 LOG.warn("Memory Usage for the Broker (" + memLimit / (1024 * 1024) + 2097 " mb) is more than the maximum available for the JVM: " + 2098 jvmLimit / (1024 * 1024) + " mb - resetting to 70% of maximum available: " + (usage.getMemoryUsage().getLimit() / (1024 * 1024)) + " mb"); 2099 } 2100 2101 //Check the persistent store and temp store limits if they exist 2102 //and schedule a periodic check to update disk limits if 2103 //schedulePeriodForDiskLimitCheck is set 2104 checkStoreUsageLimits(); 2105 checkTmpStoreUsageLimits(); 2106 scheduleDiskUsageLimitsCheck(); 2107 2108 if (getJobSchedulerStore() != null) { 2109 JobSchedulerStore scheduler = getJobSchedulerStore(); 2110 File schedulerDir = scheduler.getDirectory(); 2111 if (schedulerDir != null) { 2112 2113 String schedulerDirPath = schedulerDir.getAbsolutePath(); 2114 if (!schedulerDir.isAbsolute()) { 2115 schedulerDir = new File(schedulerDirPath); 2116 } 2117 2118 while (schedulerDir != null && !schedulerDir.isDirectory()) { 2119 schedulerDir = schedulerDir.getParentFile(); 2120 } 2121 long schedulerLimit = usage.getJobSchedulerUsage().getLimit(); 2122 long dirFreeSpace = schedulerDir.getUsableSpace(); 2123 if (schedulerLimit > dirFreeSpace) { 2124 LOG.warn("Job Scheduler Store limit is " + schedulerLimit / (1024 * 1024) + 2125 " mb, whilst the data directory: " + schedulerDir.getAbsolutePath() + 2126 " only has " + dirFreeSpace / (1024 * 1024) + " mb of usable space - resetting to " + 2127 dirFreeSpace / (1024 * 1024) + " mb."); 2128 usage.getJobSchedulerUsage().setLimit(dirFreeSpace); 2129 } 2130 } 2131 } 2132 } 2133 2134 public void stopAllConnectors(ServiceStopper stopper) { 2135 for (Iterator<NetworkConnector> iter = getNetworkConnectors().iterator(); iter.hasNext();) { 2136 NetworkConnector connector = iter.next(); 2137 unregisterNetworkConnectorMBean(connector); 2138 stopper.stop(connector); 2139 } 2140 for (Iterator<ProxyConnector> iter = getProxyConnectors().iterator(); iter.hasNext();) { 2141 ProxyConnector connector = iter.next(); 2142 stopper.stop(connector); 2143 } 2144 for (Iterator<JmsConnector> iter = jmsConnectors.iterator(); iter.hasNext();) { 2145 JmsConnector connector = iter.next(); 2146 stopper.stop(connector); 2147 } 2148 for (Iterator<TransportConnector> iter = getTransportConnectors().iterator(); iter.hasNext();) { 2149 TransportConnector connector = iter.next(); 2150 try { 2151 unregisterConnectorMBean(connector); 2152 } catch (IOException e) { 2153 } 2154 stopper.stop(connector); 2155 } 2156 } 2157 2158 protected TransportConnector registerConnectorMBean(TransportConnector connector) throws IOException { 2159 try { 2160 ObjectName objectName = createConnectorObjectName(connector); 2161 connector = connector.asManagedConnector(getManagementContext(), objectName); 2162 ConnectorViewMBean view = new ConnectorView(connector); 2163 AnnotatedMBean.registerMBean(getManagementContext(), view, objectName); 2164 return connector; 2165 } catch (Throwable e) { 2166 throw IOExceptionSupport.create("Transport Connector could not be registered in JMX: " + e, e); 2167 } 2168 } 2169 2170 protected void unregisterConnectorMBean(TransportConnector connector) throws IOException { 2171 if (isUseJmx()) { 2172 try { 2173 ObjectName objectName = createConnectorObjectName(connector); 2174 getManagementContext().unregisterMBean(objectName); 2175 } catch (Throwable e) { 2176 throw IOExceptionSupport.create( 2177 "Transport Connector could not be unregistered in JMX: " + e.getMessage(), e); 2178 } 2179 } 2180 } 2181 2182 protected PersistenceAdapter registerPersistenceAdapterMBean(PersistenceAdapter adaptor) throws IOException { 2183 return adaptor; 2184 } 2185 2186 protected void unregisterPersistenceAdapterMBean(PersistenceAdapter adaptor) throws IOException { 2187 if (isUseJmx()) {} 2188 } 2189 2190 private ObjectName createConnectorObjectName(TransportConnector connector) throws MalformedObjectNameException { 2191 return BrokerMBeanSupport.createConnectorName(getBrokerObjectName(), "clientConnectors", connector.getName()); 2192 } 2193 2194 public void registerNetworkConnectorMBean(NetworkConnector connector) throws IOException { 2195 NetworkConnectorViewMBean view = new NetworkConnectorView(connector); 2196 try { 2197 ObjectName objectName = createNetworkConnectorObjectName(connector); 2198 connector.setObjectName(objectName); 2199 AnnotatedMBean.registerMBean(getManagementContext(), view, objectName); 2200 } catch (Throwable e) { 2201 throw IOExceptionSupport.create("Network Connector could not be registered in JMX: " + e.getMessage(), e); 2202 } 2203 } 2204 2205 protected ObjectName createNetworkConnectorObjectName(NetworkConnector connector) throws MalformedObjectNameException { 2206 return BrokerMBeanSupport.createNetworkConnectorName(getBrokerObjectName(), "networkConnectors", connector.getName()); 2207 } 2208 2209 public ObjectName createDuplexNetworkConnectorObjectName(String transport) throws MalformedObjectNameException { 2210 return BrokerMBeanSupport.createNetworkConnectorName(getBrokerObjectName(), "duplexNetworkConnectors", transport); 2211 } 2212 2213 protected void unregisterNetworkConnectorMBean(NetworkConnector connector) { 2214 if (isUseJmx()) { 2215 try { 2216 ObjectName objectName = createNetworkConnectorObjectName(connector); 2217 getManagementContext().unregisterMBean(objectName); 2218 } catch (Exception e) { 2219 LOG.warn("Network Connector could not be unregistered from JMX due " + e.getMessage() + ". This exception is ignored.", e); 2220 } 2221 } 2222 } 2223 2224 protected void registerProxyConnectorMBean(ProxyConnector connector) throws IOException { 2225 ProxyConnectorView view = new ProxyConnectorView(connector); 2226 try { 2227 ObjectName objectName = BrokerMBeanSupport.createNetworkConnectorName(getBrokerObjectName(), "proxyConnectors", connector.getName()); 2228 AnnotatedMBean.registerMBean(getManagementContext(), view, objectName); 2229 } catch (Throwable e) { 2230 throw IOExceptionSupport.create("Broker could not be registered in JMX: " + e.getMessage(), e); 2231 } 2232 } 2233 2234 protected void registerJmsConnectorMBean(JmsConnector connector) throws IOException { 2235 JmsConnectorView view = new JmsConnectorView(connector); 2236 try { 2237 ObjectName objectName = BrokerMBeanSupport.createNetworkConnectorName(getBrokerObjectName(), "jmsConnectors", connector.getName()); 2238 AnnotatedMBean.registerMBean(getManagementContext(), view, objectName); 2239 } catch (Throwable e) { 2240 throw IOExceptionSupport.create("Broker could not be registered in JMX: " + e.getMessage(), e); 2241 } 2242 } 2243 2244 /** 2245 * Factory method to create a new broker 2246 * 2247 * @throws Exception 2248 */ 2249 protected Broker createBroker() throws Exception { 2250 regionBroker = createRegionBroker(); 2251 Broker broker = addInterceptors(regionBroker); 2252 // Add a filter that will stop access to the broker once stopped 2253 broker = new MutableBrokerFilter(broker) { 2254 Broker old; 2255 2256 @Override 2257 public void stop() throws Exception { 2258 old = this.next.getAndSet(new ErrorBroker("Broker has been stopped: " + this) { 2259 // Just ignore additional stop actions. 2260 @Override 2261 public void stop() throws Exception { 2262 } 2263 }); 2264 old.stop(); 2265 } 2266 2267 @Override 2268 public void start() throws Exception { 2269 if (forceStart && old != null) { 2270 this.next.set(old); 2271 } 2272 getNext().start(); 2273 } 2274 }; 2275 return broker; 2276 } 2277 2278 /** 2279 * Factory method to create the core region broker onto which interceptors 2280 * are added 2281 * 2282 * @throws Exception 2283 */ 2284 protected Broker createRegionBroker() throws Exception { 2285 if (destinationInterceptors == null) { 2286 destinationInterceptors = createDefaultDestinationInterceptor(); 2287 } 2288 configureServices(destinationInterceptors); 2289 DestinationInterceptor destinationInterceptor = new CompositeDestinationInterceptor(destinationInterceptors); 2290 if (destinationFactory == null) { 2291 destinationFactory = new DestinationFactoryImpl(this, getTaskRunnerFactory(), getPersistenceAdapter()); 2292 } 2293 return createRegionBroker(destinationInterceptor); 2294 } 2295 2296 protected Broker createRegionBroker(DestinationInterceptor destinationInterceptor) throws IOException { 2297 RegionBroker regionBroker; 2298 if (isUseJmx()) { 2299 try { 2300 regionBroker = new ManagedRegionBroker(this, getManagementContext(), getBrokerObjectName(), 2301 getTaskRunnerFactory(), getConsumerSystemUsage(), destinationFactory, destinationInterceptor,getScheduler(),getExecutor()); 2302 } catch(MalformedObjectNameException me){ 2303 LOG.warn("Cannot create ManagedRegionBroker due " + me.getMessage(), me); 2304 throw new IOException(me); 2305 } 2306 } else { 2307 regionBroker = new RegionBroker(this, getTaskRunnerFactory(), getConsumerSystemUsage(), destinationFactory, 2308 destinationInterceptor,getScheduler(),getExecutor()); 2309 } 2310 destinationFactory.setRegionBroker(regionBroker); 2311 regionBroker.setKeepDurableSubsActive(keepDurableSubsActive); 2312 regionBroker.setBrokerName(getBrokerName()); 2313 regionBroker.getDestinationStatistics().setEnabled(enableStatistics); 2314 regionBroker.setAllowTempAutoCreationOnSend(isAllowTempAutoCreationOnSend()); 2315 if (brokerId != null) { 2316 regionBroker.setBrokerId(brokerId); 2317 } 2318 return regionBroker; 2319 } 2320 2321 /** 2322 * Create the default destination interceptor 2323 */ 2324 protected DestinationInterceptor[] createDefaultDestinationInterceptor() { 2325 List<DestinationInterceptor> answer = new ArrayList<DestinationInterceptor>(); 2326 if (isUseVirtualTopics()) { 2327 VirtualDestinationInterceptor interceptor = new VirtualDestinationInterceptor(); 2328 VirtualTopic virtualTopic = new VirtualTopic(); 2329 virtualTopic.setName("VirtualTopic.>"); 2330 VirtualDestination[] virtualDestinations = { virtualTopic }; 2331 interceptor.setVirtualDestinations(virtualDestinations); 2332 answer.add(interceptor); 2333 } 2334 if (isUseMirroredQueues()) { 2335 MirroredQueue interceptor = new MirroredQueue(); 2336 answer.add(interceptor); 2337 } 2338 DestinationInterceptor[] array = new DestinationInterceptor[answer.size()]; 2339 answer.toArray(array); 2340 return array; 2341 } 2342 2343 /** 2344 * Strategy method to add interceptors to the broker 2345 * 2346 * @throws IOException 2347 */ 2348 protected Broker addInterceptors(Broker broker) throws Exception { 2349 if (isSchedulerSupport()) { 2350 SchedulerBroker sb = new SchedulerBroker(this, broker, getJobSchedulerStore()); 2351 if (isUseJmx()) { 2352 JobSchedulerViewMBean view = new JobSchedulerView(sb.getJobScheduler()); 2353 try { 2354 ObjectName objectName = BrokerMBeanSupport.createJobSchedulerServiceName(getBrokerObjectName()); 2355 AnnotatedMBean.registerMBean(getManagementContext(), view, objectName); 2356 this.adminView.setJMSJobScheduler(objectName); 2357 } catch (Throwable e) { 2358 throw IOExceptionSupport.create("JobScheduler could not be registered in JMX: " 2359 + e.getMessage(), e); 2360 } 2361 } 2362 broker = sb; 2363 } 2364 if (isUseJmx()) { 2365 HealthViewMBean statusView = new HealthView((ManagedRegionBroker)getRegionBroker()); 2366 try { 2367 ObjectName objectName = BrokerMBeanSupport.createHealthServiceName(getBrokerObjectName()); 2368 AnnotatedMBean.registerMBean(getManagementContext(), statusView, objectName); 2369 } catch (Throwable e) { 2370 throw IOExceptionSupport.create("Status MBean could not be registered in JMX: " 2371 + e.getMessage(), e); 2372 } 2373 } 2374 if (isAdvisorySupport()) { 2375 broker = new AdvisoryBroker(broker); 2376 } 2377 broker = new CompositeDestinationBroker(broker); 2378 broker = new TransactionBroker(broker, getPersistenceAdapter().createTransactionStore()); 2379 if (isPopulateJMSXUserID()) { 2380 UserIDBroker userIDBroker = new UserIDBroker(broker); 2381 userIDBroker.setUseAuthenticatePrincipal(isUseAuthenticatedPrincipalForJMSXUserID()); 2382 broker = userIDBroker; 2383 } 2384 if (isMonitorConnectionSplits()) { 2385 broker = new ConnectionSplitBroker(broker); 2386 } 2387 if (plugins != null) { 2388 for (int i = 0; i < plugins.length; i++) { 2389 BrokerPlugin plugin = plugins[i]; 2390 broker = plugin.installPlugin(broker); 2391 } 2392 } 2393 return broker; 2394 } 2395 2396 protected PersistenceAdapter createPersistenceAdapter() throws IOException { 2397 if (isPersistent()) { 2398 PersistenceAdapterFactory fac = getPersistenceFactory(); 2399 if (fac != null) { 2400 return fac.createPersistenceAdapter(); 2401 } else { 2402 try { 2403 String clazz = "org.apache.activemq.store.kahadb.KahaDBPersistenceAdapter"; 2404 PersistenceAdapter adaptor = (PersistenceAdapter)getClass().getClassLoader().loadClass(clazz).newInstance(); 2405 File dir = new File(getBrokerDataDirectory(),"KahaDB"); 2406 adaptor.setDirectory(dir); 2407 return adaptor; 2408 } catch (Throwable e) { 2409 throw IOExceptionSupport.create(e); 2410 } 2411 } 2412 } else { 2413 return new MemoryPersistenceAdapter(); 2414 } 2415 } 2416 2417 protected ObjectName createBrokerObjectName() throws MalformedObjectNameException { 2418 return BrokerMBeanSupport.createBrokerObjectName(getManagementContext().getJmxDomainName(), getBrokerName()); 2419 } 2420 2421 protected TransportConnector createTransportConnector(URI brokerURI) throws Exception { 2422 TransportServer transport = TransportFactorySupport.bind(this, brokerURI); 2423 return new TransportConnector(transport); 2424 } 2425 2426 /** 2427 * Extracts the port from the options 2428 */ 2429 protected Object getPort(Map<?,?> options) { 2430 Object port = options.get("port"); 2431 if (port == null) { 2432 port = DEFAULT_PORT; 2433 LOG.warn("No port specified so defaulting to: {}", port); 2434 } 2435 return port; 2436 } 2437 2438 protected void addShutdownHook() { 2439 if (useShutdownHook) { 2440 shutdownHook = new Thread("ActiveMQ ShutdownHook") { 2441 @Override 2442 public void run() { 2443 containerShutdown(); 2444 } 2445 }; 2446 Runtime.getRuntime().addShutdownHook(shutdownHook); 2447 } 2448 } 2449 2450 protected void removeShutdownHook() { 2451 if (shutdownHook != null) { 2452 try { 2453 Runtime.getRuntime().removeShutdownHook(shutdownHook); 2454 } catch (Exception e) { 2455 LOG.debug("Caught exception, must be shutting down. This exception is ignored.", e); 2456 } 2457 } 2458 } 2459 2460 /** 2461 * Sets hooks to be executed when broker shut down 2462 * 2463 * @org.apache.xbean.Property 2464 */ 2465 public void setShutdownHooks(List<Runnable> hooks) throws Exception { 2466 for (Runnable hook : hooks) { 2467 addShutdownHook(hook); 2468 } 2469 } 2470 2471 /** 2472 * Causes a clean shutdown of the container when the VM is being shut down 2473 */ 2474 protected void containerShutdown() { 2475 try { 2476 stop(); 2477 } catch (IOException e) { 2478 Throwable linkedException = e.getCause(); 2479 if (linkedException != null) { 2480 logError("Failed to shut down: " + e + ". Reason: " + linkedException, linkedException); 2481 } else { 2482 logError("Failed to shut down: " + e, e); 2483 } 2484 if (!useLoggingForShutdownErrors) { 2485 e.printStackTrace(System.err); 2486 } 2487 } catch (Exception e) { 2488 logError("Failed to shut down: " + e, e); 2489 } 2490 } 2491 2492 protected void logError(String message, Throwable e) { 2493 if (useLoggingForShutdownErrors) { 2494 LOG.error("Failed to shut down: " + e); 2495 } else { 2496 System.err.println("Failed to shut down: " + e); 2497 } 2498 } 2499 2500 /** 2501 * Starts any configured destinations on startup 2502 */ 2503 protected void startDestinations() throws Exception { 2504 if (destinations != null) { 2505 ConnectionContext adminConnectionContext = getAdminConnectionContext(); 2506 for (int i = 0; i < destinations.length; i++) { 2507 ActiveMQDestination destination = destinations[i]; 2508 getBroker().addDestination(adminConnectionContext, destination,true); 2509 } 2510 } 2511 if (isUseVirtualTopics()) { 2512 startVirtualConsumerDestinations(); 2513 } 2514 } 2515 2516 /** 2517 * Returns the broker's administration connection context used for 2518 * configuring the broker at startup 2519 */ 2520 public ConnectionContext getAdminConnectionContext() throws Exception { 2521 return BrokerSupport.getConnectionContext(getBroker()); 2522 } 2523 2524 protected void startManagementContext() throws Exception { 2525 getManagementContext().setBrokerName(brokerName); 2526 getManagementContext().start(); 2527 adminView = new BrokerView(this, null); 2528 ObjectName objectName = getBrokerObjectName(); 2529 AnnotatedMBean.registerMBean(getManagementContext(), adminView, objectName); 2530 } 2531 2532 /** 2533 * Start all transport and network connections, proxies and bridges 2534 * 2535 * @throws Exception 2536 */ 2537 public void startAllConnectors() throws Exception { 2538 Set<ActiveMQDestination> durableDestinations = getBroker().getDurableDestinations(); 2539 List<TransportConnector> al = new ArrayList<TransportConnector>(); 2540 for (Iterator<TransportConnector> iter = getTransportConnectors().iterator(); iter.hasNext();) { 2541 TransportConnector connector = iter.next(); 2542 al.add(startTransportConnector(connector)); 2543 } 2544 if (al.size() > 0) { 2545 // let's clear the transportConnectors list and replace it with 2546 // the started transportConnector instances 2547 this.transportConnectors.clear(); 2548 setTransportConnectors(al); 2549 } 2550 this.slave = false; 2551 URI uri = getVmConnectorURI(); 2552 Map<String, String> map = new HashMap<String, String>(URISupport.parseParameters(uri)); 2553 map.put("async", "false"); 2554 uri = URISupport.createURIWithQuery(uri, URISupport.createQueryString(map)); 2555 2556 if (!stopped.get()) { 2557 ThreadPoolExecutor networkConnectorStartExecutor = null; 2558 if (isNetworkConnectorStartAsync()) { 2559 // spin up as many threads as needed 2560 networkConnectorStartExecutor = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 2561 10, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(), 2562 new ThreadFactory() { 2563 int count=0; 2564 @Override 2565 public Thread newThread(Runnable runnable) { 2566 Thread thread = new Thread(runnable, "NetworkConnector Start Thread-" +(count++)); 2567 thread.setDaemon(true); 2568 return thread; 2569 } 2570 }); 2571 } 2572 2573 for (Iterator<NetworkConnector> iter = getNetworkConnectors().iterator(); iter.hasNext();) { 2574 final NetworkConnector connector = iter.next(); 2575 connector.setLocalUri(uri); 2576 connector.setBrokerName(getBrokerName()); 2577 connector.setDurableDestinations(durableDestinations); 2578 if (getDefaultSocketURIString() != null) { 2579 connector.setBrokerURL(getDefaultSocketURIString()); 2580 } 2581 if (networkConnectorStartExecutor != null) { 2582 networkConnectorStartExecutor.execute(new Runnable() { 2583 @Override 2584 public void run() { 2585 try { 2586 LOG.info("Async start of {}", connector); 2587 connector.start(); 2588 } catch(Exception e) { 2589 LOG.error("Async start of network connector: {} failed", connector, e); 2590 } 2591 } 2592 }); 2593 } else { 2594 connector.start(); 2595 } 2596 } 2597 if (networkConnectorStartExecutor != null) { 2598 // executor done when enqueued tasks are complete 2599 ThreadPoolUtils.shutdown(networkConnectorStartExecutor); 2600 } 2601 2602 for (Iterator<ProxyConnector> iter = getProxyConnectors().iterator(); iter.hasNext();) { 2603 ProxyConnector connector = iter.next(); 2604 connector.start(); 2605 } 2606 for (Iterator<JmsConnector> iter = jmsConnectors.iterator(); iter.hasNext();) { 2607 JmsConnector connector = iter.next(); 2608 connector.start(); 2609 } 2610 for (Service service : services) { 2611 configureService(service); 2612 service.start(); 2613 } 2614 } 2615 } 2616 2617 public TransportConnector startTransportConnector(TransportConnector connector) throws Exception { 2618 connector.setBrokerService(this); 2619 connector.setTaskRunnerFactory(getTaskRunnerFactory()); 2620 MessageAuthorizationPolicy policy = getMessageAuthorizationPolicy(); 2621 if (policy != null) { 2622 connector.setMessageAuthorizationPolicy(policy); 2623 } 2624 if (isUseJmx()) { 2625 connector = registerConnectorMBean(connector); 2626 } 2627 connector.getStatistics().setEnabled(enableStatistics); 2628 connector.start(); 2629 return connector; 2630 } 2631 2632 /** 2633 * Perform any custom dependency injection 2634 */ 2635 protected void configureServices(Object[] services) { 2636 for (Object service : services) { 2637 configureService(service); 2638 } 2639 } 2640 2641 /** 2642 * Perform any custom dependency injection 2643 */ 2644 protected void configureService(Object service) { 2645 if (service instanceof BrokerServiceAware) { 2646 BrokerServiceAware serviceAware = (BrokerServiceAware) service; 2647 serviceAware.setBrokerService(this); 2648 } 2649 } 2650 2651 public void handleIOException(IOException exception) { 2652 if (ioExceptionHandler != null) { 2653 ioExceptionHandler.handle(exception); 2654 } else { 2655 LOG.info("No IOExceptionHandler registered, ignoring IO exception", exception); 2656 } 2657 } 2658 2659 protected void startVirtualConsumerDestinations() throws Exception { 2660 ConnectionContext adminConnectionContext = getAdminConnectionContext(); 2661 Set<ActiveMQDestination> destinations = destinationFactory.getDestinations(); 2662 DestinationFilter filter = getVirtualTopicConsumerDestinationFilter(); 2663 if (!destinations.isEmpty()) { 2664 for (ActiveMQDestination destination : destinations) { 2665 if (filter.matches(destination) == true) { 2666 broker.addDestination(adminConnectionContext, destination, false); 2667 } 2668 } 2669 } 2670 } 2671 2672 private DestinationFilter getVirtualTopicConsumerDestinationFilter() { 2673 // created at startup, so no sync needed 2674 if (virtualConsumerDestinationFilter == null) { 2675 Set <ActiveMQQueue> consumerDestinations = new HashSet<ActiveMQQueue>(); 2676 if (destinationInterceptors != null) { 2677 for (DestinationInterceptor interceptor : destinationInterceptors) { 2678 if (interceptor instanceof VirtualDestinationInterceptor) { 2679 VirtualDestinationInterceptor virtualDestinationInterceptor = (VirtualDestinationInterceptor) interceptor; 2680 for (VirtualDestination virtualDestination: virtualDestinationInterceptor.getVirtualDestinations()) { 2681 if (virtualDestination instanceof VirtualTopic) { 2682 consumerDestinations.add(new ActiveMQQueue(((VirtualTopic) virtualDestination).getPrefix() + DestinationFilter.ANY_DESCENDENT)); 2683 } 2684 } 2685 } 2686 } 2687 } 2688 ActiveMQQueue filter = new ActiveMQQueue(); 2689 filter.setCompositeDestinations(consumerDestinations.toArray(new ActiveMQDestination[]{})); 2690 virtualConsumerDestinationFilter = DestinationFilter.parseFilter(filter); 2691 } 2692 return virtualConsumerDestinationFilter; 2693 } 2694 2695 protected synchronized ThreadPoolExecutor getExecutor() { 2696 if (this.executor == null) { 2697 this.executor = new ThreadPoolExecutor(1, 10, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(), new ThreadFactory() { 2698 2699 private long i = 0; 2700 2701 @Override 2702 public Thread newThread(Runnable runnable) { 2703 this.i++; 2704 Thread thread = new Thread(runnable, "ActiveMQ BrokerService.worker." + this.i); 2705 thread.setDaemon(true); 2706 thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { 2707 @Override 2708 public void uncaughtException(final Thread t, final Throwable e) { 2709 LOG.error("Error in thread '{}'", t.getName(), e); 2710 } 2711 }); 2712 return thread; 2713 } 2714 }, new RejectedExecutionHandler() { 2715 @Override 2716 public void rejectedExecution(final Runnable r, final ThreadPoolExecutor executor) { 2717 try { 2718 executor.getQueue().offer(r, 60, TimeUnit.SECONDS); 2719 } catch (InterruptedException e) { 2720 throw new RejectedExecutionException("Interrupted waiting for BrokerService.worker"); 2721 } 2722 2723 throw new RejectedExecutionException("Timed Out while attempting to enqueue Task."); 2724 } 2725 }); 2726 } 2727 return this.executor; 2728 } 2729 2730 public synchronized Scheduler getScheduler() { 2731 if (this.scheduler==null) { 2732 this.scheduler = new Scheduler("ActiveMQ Broker["+getBrokerName()+"] Scheduler"); 2733 try { 2734 this.scheduler.start(); 2735 } catch (Exception e) { 2736 LOG.error("Failed to start Scheduler", e); 2737 } 2738 } 2739 return this.scheduler; 2740 } 2741 2742 public Broker getRegionBroker() { 2743 return regionBroker; 2744 } 2745 2746 public void setRegionBroker(Broker regionBroker) { 2747 this.regionBroker = regionBroker; 2748 } 2749 2750 public void addShutdownHook(Runnable hook) { 2751 synchronized (shutdownHooks) { 2752 shutdownHooks.add(hook); 2753 } 2754 } 2755 2756 public void removeShutdownHook(Runnable hook) { 2757 synchronized (shutdownHooks) { 2758 shutdownHooks.remove(hook); 2759 } 2760 } 2761 2762 public boolean isSystemExitOnShutdown() { 2763 return systemExitOnShutdown; 2764 } 2765 2766 /** 2767 * @org.apache.xbean.Property propertyEditor="org.apache.activemq.util.BooleanEditor" 2768 */ 2769 public void setSystemExitOnShutdown(boolean systemExitOnShutdown) { 2770 this.systemExitOnShutdown = systemExitOnShutdown; 2771 } 2772 2773 public int getSystemExitOnShutdownExitCode() { 2774 return systemExitOnShutdownExitCode; 2775 } 2776 2777 public void setSystemExitOnShutdownExitCode(int systemExitOnShutdownExitCode) { 2778 this.systemExitOnShutdownExitCode = systemExitOnShutdownExitCode; 2779 } 2780 2781 public SslContext getSslContext() { 2782 return sslContext; 2783 } 2784 2785 public void setSslContext(SslContext sslContext) { 2786 this.sslContext = sslContext; 2787 } 2788 2789 public boolean isShutdownOnSlaveFailure() { 2790 return shutdownOnSlaveFailure; 2791 } 2792 2793 /** 2794 * @org.apache.xbean.Property propertyEditor="org.apache.activemq.util.BooleanEditor" 2795 */ 2796 public void setShutdownOnSlaveFailure(boolean shutdownOnSlaveFailure) { 2797 this.shutdownOnSlaveFailure = shutdownOnSlaveFailure; 2798 } 2799 2800 public boolean isWaitForSlave() { 2801 return waitForSlave; 2802 } 2803 2804 /** 2805 * @org.apache.xbean.Property propertyEditor="org.apache.activemq.util.BooleanEditor" 2806 */ 2807 public void setWaitForSlave(boolean waitForSlave) { 2808 this.waitForSlave = waitForSlave; 2809 } 2810 2811 public long getWaitForSlaveTimeout() { 2812 return this.waitForSlaveTimeout; 2813 } 2814 2815 public void setWaitForSlaveTimeout(long waitForSlaveTimeout) { 2816 this.waitForSlaveTimeout = waitForSlaveTimeout; 2817 } 2818 2819 /** 2820 * Get the passiveSlave 2821 * @return the passiveSlave 2822 */ 2823 public boolean isPassiveSlave() { 2824 return this.passiveSlave; 2825 } 2826 2827 /** 2828 * Set the passiveSlave 2829 * @param passiveSlave the passiveSlave to set 2830 * @org.apache.xbean.Property propertyEditor="org.apache.activemq.util.BooleanEditor" 2831 */ 2832 public void setPassiveSlave(boolean passiveSlave) { 2833 this.passiveSlave = passiveSlave; 2834 } 2835 2836 /** 2837 * override the Default IOException handler, called when persistence adapter 2838 * has experiences File or JDBC I/O Exceptions 2839 * 2840 * @param ioExceptionHandler 2841 */ 2842 public void setIoExceptionHandler(IOExceptionHandler ioExceptionHandler) { 2843 configureService(ioExceptionHandler); 2844 this.ioExceptionHandler = ioExceptionHandler; 2845 } 2846 2847 public IOExceptionHandler getIoExceptionHandler() { 2848 return ioExceptionHandler; 2849 } 2850 2851 /** 2852 * @return the schedulerSupport 2853 */ 2854 public boolean isSchedulerSupport() { 2855 return this.schedulerSupport; 2856 } 2857 2858 /** 2859 * @param schedulerSupport the schedulerSupport to set 2860 * @org.apache.xbean.Property propertyEditor="org.apache.activemq.util.BooleanEditor" 2861 */ 2862 public void setSchedulerSupport(boolean schedulerSupport) { 2863 this.schedulerSupport = schedulerSupport; 2864 } 2865 2866 /** 2867 * @return the schedulerDirectory 2868 */ 2869 public File getSchedulerDirectoryFile() { 2870 if (this.schedulerDirectoryFile == null) { 2871 this.schedulerDirectoryFile = new File(getBrokerDataDirectory(), "scheduler"); 2872 } 2873 return schedulerDirectoryFile; 2874 } 2875 2876 /** 2877 * @param schedulerDirectory the schedulerDirectory to set 2878 */ 2879 public void setSchedulerDirectoryFile(File schedulerDirectory) { 2880 this.schedulerDirectoryFile = schedulerDirectory; 2881 } 2882 2883 public void setSchedulerDirectory(String schedulerDirectory) { 2884 setSchedulerDirectoryFile(new File(schedulerDirectory)); 2885 } 2886 2887 public int getSchedulePeriodForDestinationPurge() { 2888 return this.schedulePeriodForDestinationPurge; 2889 } 2890 2891 public void setSchedulePeriodForDestinationPurge(int schedulePeriodForDestinationPurge) { 2892 this.schedulePeriodForDestinationPurge = schedulePeriodForDestinationPurge; 2893 } 2894 2895 public void setSchedulePeriodForDiskUsageCheck( 2896 int schedulePeriodForDiskUsageCheck) { 2897 this.schedulePeriodForDiskUsageCheck = schedulePeriodForDiskUsageCheck; 2898 } 2899 2900 public int getMaxPurgedDestinationsPerSweep() { 2901 return this.maxPurgedDestinationsPerSweep; 2902 } 2903 2904 public void setMaxPurgedDestinationsPerSweep(int maxPurgedDestinationsPerSweep) { 2905 this.maxPurgedDestinationsPerSweep = maxPurgedDestinationsPerSweep; 2906 } 2907 2908 public BrokerContext getBrokerContext() { 2909 return brokerContext; 2910 } 2911 2912 public void setBrokerContext(BrokerContext brokerContext) { 2913 this.brokerContext = brokerContext; 2914 } 2915 2916 public void setBrokerId(String brokerId) { 2917 this.brokerId = new BrokerId(brokerId); 2918 } 2919 2920 public boolean isUseAuthenticatedPrincipalForJMSXUserID() { 2921 return useAuthenticatedPrincipalForJMSXUserID; 2922 } 2923 2924 public void setUseAuthenticatedPrincipalForJMSXUserID(boolean useAuthenticatedPrincipalForJMSXUserID) { 2925 this.useAuthenticatedPrincipalForJMSXUserID = useAuthenticatedPrincipalForJMSXUserID; 2926 } 2927 2928 /** 2929 * Should MBeans that support showing the Authenticated User Name information have this 2930 * value filled in or not. 2931 * 2932 * @return true if user names should be exposed in MBeans 2933 */ 2934 public boolean isPopulateUserNameInMBeans() { 2935 return this.populateUserNameInMBeans; 2936 } 2937 2938 /** 2939 * Sets whether Authenticated User Name information is shown in MBeans that support this field. 2940 * @param value if MBeans should expose user name information. 2941 */ 2942 public void setPopulateUserNameInMBeans(boolean value) { 2943 this.populateUserNameInMBeans = value; 2944 } 2945 2946 /** 2947 * Gets the time in Milliseconds that an invocation of an MBean method will wait before 2948 * failing. The default value is to wait forever (zero). 2949 * 2950 * @return timeout in milliseconds before MBean calls fail, (default is 0 or no timeout). 2951 */ 2952 public long getMbeanInvocationTimeout() { 2953 return mbeanInvocationTimeout; 2954 } 2955 2956 /** 2957 * Gets the time in Milliseconds that an invocation of an MBean method will wait before 2958 * failing. The default value is to wait forever (zero). 2959 * 2960 * @param mbeanInvocationTimeout 2961 * timeout in milliseconds before MBean calls fail, (default is 0 or no timeout). 2962 */ 2963 public void setMbeanInvocationTimeout(long mbeanInvocationTimeout) { 2964 this.mbeanInvocationTimeout = mbeanInvocationTimeout; 2965 } 2966 2967 public boolean isNetworkConnectorStartAsync() { 2968 return networkConnectorStartAsync; 2969 } 2970 2971 public void setNetworkConnectorStartAsync(boolean networkConnectorStartAsync) { 2972 this.networkConnectorStartAsync = networkConnectorStartAsync; 2973 } 2974 2975 public boolean isAllowTempAutoCreationOnSend() { 2976 return allowTempAutoCreationOnSend; 2977 } 2978 2979 /** 2980 * enable if temp destinations need to be propagated through a network when 2981 * advisorySupport==false. This is used in conjunction with the policy 2982 * gcInactiveDestinations for matching temps so they can get removed 2983 * when inactive 2984 * 2985 * @param allowTempAutoCreationOnSend 2986 */ 2987 public void setAllowTempAutoCreationOnSend(boolean allowTempAutoCreationOnSend) { 2988 this.allowTempAutoCreationOnSend = allowTempAutoCreationOnSend; 2989 } 2990 2991 public long getOfflineDurableSubscriberTimeout() { 2992 return offlineDurableSubscriberTimeout; 2993 } 2994 2995 public void setOfflineDurableSubscriberTimeout(long offlineDurableSubscriberTimeout) { 2996 this.offlineDurableSubscriberTimeout = offlineDurableSubscriberTimeout; 2997 } 2998 2999 public long getOfflineDurableSubscriberTaskSchedule() { 3000 return offlineDurableSubscriberTaskSchedule; 3001 } 3002 3003 public void setOfflineDurableSubscriberTaskSchedule(long offlineDurableSubscriberTaskSchedule) { 3004 this.offlineDurableSubscriberTaskSchedule = offlineDurableSubscriberTaskSchedule; 3005 } 3006 3007 public boolean shouldRecordVirtualDestination(ActiveMQDestination destination) { 3008 return isUseVirtualTopics() && destination.isQueue() && 3009 getVirtualTopicConsumerDestinationFilter().matches(destination); 3010 } 3011 3012 public Throwable getStartException() { 3013 return startException; 3014 } 3015 3016 public boolean isStartAsync() { 3017 return startAsync; 3018 } 3019 3020 public void setStartAsync(boolean startAsync) { 3021 this.startAsync = startAsync; 3022 } 3023 3024 public boolean isSlave() { 3025 return this.slave; 3026 } 3027 3028 public boolean isStopping() { 3029 return this.stopping.get(); 3030 } 3031 3032 /** 3033 * @return true if the broker allowed to restart on shutdown. 3034 */ 3035 public boolean isRestartAllowed() { 3036 return restartAllowed; 3037 } 3038 3039 /** 3040 * Sets if the broker allowed to restart on shutdown. 3041 */ 3042 public void setRestartAllowed(boolean restartAllowed) { 3043 this.restartAllowed = restartAllowed; 3044 } 3045 3046 /** 3047 * A lifecycle manager of the BrokerService should 3048 * inspect this property after a broker shutdown has occurred 3049 * to find out if the broker needs to be re-created and started 3050 * again. 3051 * 3052 * @return true if the broker wants to be restarted after it shuts down. 3053 */ 3054 public boolean isRestartRequested() { 3055 return restartRequested; 3056 } 3057 3058 public void requestRestart() { 3059 this.restartRequested = true; 3060 } 3061 3062 public int getStoreOpenWireVersion() { 3063 return storeOpenWireVersion; 3064 } 3065 3066 public void setStoreOpenWireVersion(int storeOpenWireVersion) { 3067 this.storeOpenWireVersion = storeOpenWireVersion; 3068 } 3069 3070 /** 3071 * @return the current number of connections on this Broker. 3072 */ 3073 public int getCurrentConnections() { 3074 return this.currentConnections.get(); 3075 } 3076 3077 /** 3078 * @return the total number of connections this broker has handled since startup. 3079 */ 3080 public long getTotalConnections() { 3081 return this.totalConnections.get(); 3082 } 3083 3084 public void incrementCurrentConnections() { 3085 this.currentConnections.incrementAndGet(); 3086 } 3087 3088 public void decrementCurrentConnections() { 3089 this.currentConnections.decrementAndGet(); 3090 } 3091 3092 public void incrementTotalConnections() { 3093 this.totalConnections.incrementAndGet(); 3094 } 3095 3096 public boolean isRejectDurableConsumers() { 3097 return rejectDurableConsumers; 3098 } 3099 3100 public void setRejectDurableConsumers(boolean rejectDurableConsumers) { 3101 this.rejectDurableConsumers = rejectDurableConsumers; 3102 } 3103}