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