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