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