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