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