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", new Object[]{ 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", new Object[]{ 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", new Object[]{ 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 {}", new Object[]{ getBrokerVersion(), getBrokerName(), brokerId, getUptime()}); 906 } 907 LOG.info("Apache ActiveMQ {} ({}, {}) is shutdown", new Object[]{ 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: {}", new Object[]{ 970 connectorName, queueName, timeout, pollInterval 971 }); 972 TransportConnector connector; 973 for (int i = 0; i < transportConnectors.size(); i++) { 974 connector = transportConnectors.get(i); 975 if (connector != null && connector.getName() != null && connector.getName().matches(connectorName)) { 976 connector.stop(); 977 } 978 } 979 long start = System.currentTimeMillis(); 980 while (System.currentTimeMillis() - start < timeout * 1000) { 981 // check quesize until it gets zero 982 if (checkQueueSize(queueName)) { 983 stop(); 984 break; 985 } else { 986 Thread.sleep(pollInterval * 1000); 987 } 988 } 989 if (stopped.get()) { 990 LOG.info("Successfully stop the broker."); 991 } else { 992 LOG.info("There is still pending message on the queue. Please check and stop the broker manually."); 993 } 994 } 995 } 996 997 /** 998 * A helper method to block the caller thread until the broker has been 999 * stopped 1000 */ 1001 public void waitUntilStopped() { 1002 while (isStarted() && !stopped.get()) { 1003 try { 1004 stoppedLatch.await(); 1005 } catch (InterruptedException e) { 1006 // ignore 1007 } 1008 } 1009 } 1010 1011 public boolean isStopped() { 1012 return stopped.get(); 1013 } 1014 1015 /** 1016 * A helper method to block the caller thread until the broker has fully started 1017 * @return boolean true if wait succeeded false if broker was not started or was stopped 1018 */ 1019 public boolean waitUntilStarted() { 1020 return waitUntilStarted(DEFAULT_START_TIMEOUT); 1021 } 1022 1023 /** 1024 * A helper method to block the caller thread until the broker has fully started 1025 * 1026 * @param timeout 1027 * the amount of time to wait before giving up and returning false. 1028 * 1029 * @return boolean true if wait succeeded false if broker was not started or was stopped 1030 */ 1031 public boolean waitUntilStarted(long timeout) { 1032 boolean waitSucceeded = isStarted(); 1033 long expiration = Math.max(0, timeout + System.currentTimeMillis()); 1034 while (!isStarted() && !stopped.get() && !waitSucceeded && expiration > System.currentTimeMillis()) { 1035 try { 1036 if (getStartException() != null) { 1037 return waitSucceeded; 1038 } 1039 waitSucceeded = startedLatch.await(100L, TimeUnit.MILLISECONDS); 1040 } catch (InterruptedException ignore) { 1041 } 1042 } 1043 return waitSucceeded; 1044 } 1045 1046 // Properties 1047 // ------------------------------------------------------------------------- 1048 /** 1049 * Returns the message broker 1050 */ 1051 public Broker getBroker() throws Exception { 1052 if (broker == null) { 1053 checkStartException(); 1054 broker = createBroker(); 1055 } 1056 return broker; 1057 } 1058 1059 /** 1060 * Returns the administration view of the broker; used to create and destroy 1061 * resources such as queues and topics. Note this method returns null if JMX 1062 * is disabled. 1063 */ 1064 public BrokerView getAdminView() throws Exception { 1065 if (adminView == null) { 1066 // force lazy creation 1067 getBroker(); 1068 } 1069 return adminView; 1070 } 1071 1072 public void setAdminView(BrokerView adminView) { 1073 this.adminView = adminView; 1074 } 1075 1076 public String getBrokerName() { 1077 return brokerName; 1078 } 1079 1080 /** 1081 * Sets the name of this broker; which must be unique in the network 1082 * 1083 * @param brokerName 1084 */ 1085 private static final String brokerNameReplacedCharsRegExp = "[^a-zA-Z0-9\\.\\_\\-\\:]"; 1086 public void setBrokerName(String brokerName) { 1087 if (brokerName == null) { 1088 throw new NullPointerException("The broker name cannot be null"); 1089 } 1090 String str = brokerName.replaceAll(brokerNameReplacedCharsRegExp, "_"); 1091 if (!str.equals(brokerName)) { 1092 LOG.error("Broker Name: {} contained illegal characters matching regExp: {} - replaced with {}", brokerName, brokerNameReplacedCharsRegExp, str); 1093 } 1094 this.brokerName = str.trim(); 1095 } 1096 1097 public PersistenceAdapterFactory getPersistenceFactory() { 1098 return persistenceFactory; 1099 } 1100 1101 public File getDataDirectoryFile() { 1102 if (dataDirectoryFile == null) { 1103 dataDirectoryFile = new File(IOHelper.getDefaultDataDirectory()); 1104 } 1105 return dataDirectoryFile; 1106 } 1107 1108 public File getBrokerDataDirectory() { 1109 String brokerDir = getBrokerName(); 1110 return new File(getDataDirectoryFile(), brokerDir); 1111 } 1112 1113 /** 1114 * Sets the directory in which the data files will be stored by default for 1115 * the JDBC and Journal persistence adaptors. 1116 * 1117 * @param dataDirectory 1118 * the directory to store data files 1119 */ 1120 public void setDataDirectory(String dataDirectory) { 1121 setDataDirectoryFile(new File(dataDirectory)); 1122 } 1123 1124 /** 1125 * Sets the directory in which the data files will be stored by default for 1126 * the JDBC and Journal persistence adaptors. 1127 * 1128 * @param dataDirectoryFile 1129 * the directory to store data files 1130 */ 1131 public void setDataDirectoryFile(File dataDirectoryFile) { 1132 this.dataDirectoryFile = dataDirectoryFile; 1133 } 1134 1135 /** 1136 * @return the tmpDataDirectory 1137 */ 1138 public File getTmpDataDirectory() { 1139 if (tmpDataDirectory == null) { 1140 tmpDataDirectory = new File(getBrokerDataDirectory(), "tmp_storage"); 1141 } 1142 return tmpDataDirectory; 1143 } 1144 1145 /** 1146 * @param tmpDataDirectory 1147 * the tmpDataDirectory to set 1148 */ 1149 public void setTmpDataDirectory(File tmpDataDirectory) { 1150 this.tmpDataDirectory = tmpDataDirectory; 1151 } 1152 1153 public void setPersistenceFactory(PersistenceAdapterFactory persistenceFactory) { 1154 this.persistenceFactory = persistenceFactory; 1155 } 1156 1157 public void setDestinationFactory(DestinationFactory destinationFactory) { 1158 this.destinationFactory = destinationFactory; 1159 } 1160 1161 public boolean isPersistent() { 1162 return persistent; 1163 } 1164 1165 /** 1166 * Sets whether or not persistence is enabled or disabled. 1167 * @org.apache.xbean.Property propertyEditor="org.apache.activemq.util.BooleanEditor" 1168 */ 1169 public void setPersistent(boolean persistent) { 1170 this.persistent = persistent; 1171 } 1172 1173 public boolean isPopulateJMSXUserID() { 1174 return populateJMSXUserID; 1175 } 1176 1177 /** 1178 * Sets whether or not the broker should populate the JMSXUserID header. 1179 */ 1180 public void setPopulateJMSXUserID(boolean populateJMSXUserID) { 1181 this.populateJMSXUserID = populateJMSXUserID; 1182 } 1183 1184 public SystemUsage getSystemUsage() { 1185 try { 1186 if (systemUsage == null) { 1187 1188 systemUsage = new SystemUsage("Main", getPersistenceAdapter(), getTempDataStore(), getJobSchedulerStore()); 1189 systemUsage.setExecutor(getExecutor()); 1190 systemUsage.getMemoryUsage().setLimit(1024L * 1024 * 1024 * 1); // 1 GB 1191 systemUsage.getTempUsage().setLimit(1024L * 1024 * 1024 * 50); // 50 GB 1192 systemUsage.getStoreUsage().setLimit(1024L * 1024 * 1024 * 100); // 100 GB 1193 systemUsage.getJobSchedulerUsage().setLimit(1024L * 1024 * 1024 * 50); // 50 GB 1194 addService(this.systemUsage); 1195 } 1196 return systemUsage; 1197 } catch (IOException e) { 1198 LOG.error("Cannot create SystemUsage", e); 1199 throw new RuntimeException("Fatally failed to create SystemUsage" + e.getMessage(), e); 1200 } 1201 } 1202 1203 public void setSystemUsage(SystemUsage memoryManager) { 1204 if (this.systemUsage != null) { 1205 removeService(this.systemUsage); 1206 } 1207 this.systemUsage = memoryManager; 1208 if (this.systemUsage.getExecutor()==null) { 1209 this.systemUsage.setExecutor(getExecutor()); 1210 } 1211 addService(this.systemUsage); 1212 } 1213 1214 /** 1215 * @return the consumerUsageManager 1216 * @throws IOException 1217 */ 1218 public SystemUsage getConsumerSystemUsage() throws IOException { 1219 if (this.consumerSystemUsage == null) { 1220 if (splitSystemUsageForProducersConsumers) { 1221 this.consumerSystemUsage = new SystemUsage(getSystemUsage(), "Consumer"); 1222 float portion = consumerSystemUsagePortion / 100f; 1223 this.consumerSystemUsage.getMemoryUsage().setUsagePortion(portion); 1224 addService(this.consumerSystemUsage); 1225 } else { 1226 consumerSystemUsage = getSystemUsage(); 1227 } 1228 } 1229 return this.consumerSystemUsage; 1230 } 1231 1232 /** 1233 * @param consumerSystemUsage 1234 * the storeSystemUsage to set 1235 */ 1236 public void setConsumerSystemUsage(SystemUsage consumerSystemUsage) { 1237 if (this.consumerSystemUsage != null) { 1238 removeService(this.consumerSystemUsage); 1239 } 1240 this.consumerSystemUsage = consumerSystemUsage; 1241 addService(this.consumerSystemUsage); 1242 } 1243 1244 /** 1245 * @return the producerUsageManager 1246 * @throws IOException 1247 */ 1248 public SystemUsage getProducerSystemUsage() throws IOException { 1249 if (producerSystemUsage == null) { 1250 if (splitSystemUsageForProducersConsumers) { 1251 producerSystemUsage = new SystemUsage(getSystemUsage(), "Producer"); 1252 float portion = producerSystemUsagePortion / 100f; 1253 producerSystemUsage.getMemoryUsage().setUsagePortion(portion); 1254 addService(producerSystemUsage); 1255 } else { 1256 producerSystemUsage = getSystemUsage(); 1257 } 1258 } 1259 return producerSystemUsage; 1260 } 1261 1262 /** 1263 * @param producerUsageManager 1264 * the producerUsageManager to set 1265 */ 1266 public void setProducerSystemUsage(SystemUsage producerUsageManager) { 1267 if (this.producerSystemUsage != null) { 1268 removeService(this.producerSystemUsage); 1269 } 1270 this.producerSystemUsage = producerUsageManager; 1271 addService(this.producerSystemUsage); 1272 } 1273 1274 public synchronized PersistenceAdapter getPersistenceAdapter() throws IOException { 1275 if (persistenceAdapter == null && !hasStartException()) { 1276 persistenceAdapter = createPersistenceAdapter(); 1277 configureService(persistenceAdapter); 1278 this.persistenceAdapter = registerPersistenceAdapterMBean(persistenceAdapter); 1279 } 1280 return persistenceAdapter; 1281 } 1282 1283 /** 1284 * Sets the persistence adaptor implementation to use for this broker 1285 * 1286 * @throws IOException 1287 */ 1288 public void setPersistenceAdapter(PersistenceAdapter persistenceAdapter) throws IOException { 1289 if (!isPersistent() && ! (persistenceAdapter instanceof MemoryPersistenceAdapter)) { 1290 LOG.warn("persistent=\"false\", ignoring configured persistenceAdapter: {}", persistenceAdapter); 1291 return; 1292 } 1293 this.persistenceAdapter = persistenceAdapter; 1294 configureService(this.persistenceAdapter); 1295 this.persistenceAdapter = registerPersistenceAdapterMBean(persistenceAdapter); 1296 } 1297 1298 public TaskRunnerFactory getTaskRunnerFactory() { 1299 if (this.taskRunnerFactory == null) { 1300 this.taskRunnerFactory = new TaskRunnerFactory("ActiveMQ BrokerService["+getBrokerName()+"] Task", getTaskRunnerPriority(), true, 1000, 1301 isDedicatedTaskRunner()); 1302 this.taskRunnerFactory.setThreadClassLoader(this.getClass().getClassLoader()); 1303 } 1304 return this.taskRunnerFactory; 1305 } 1306 1307 public void setTaskRunnerFactory(TaskRunnerFactory taskRunnerFactory) { 1308 this.taskRunnerFactory = taskRunnerFactory; 1309 } 1310 1311 public TaskRunnerFactory getPersistenceTaskRunnerFactory() { 1312 if (taskRunnerFactory == null) { 1313 persistenceTaskRunnerFactory = new TaskRunnerFactory("Persistence Adaptor Task", persistenceThreadPriority, 1314 true, 1000, isDedicatedTaskRunner()); 1315 } 1316 return persistenceTaskRunnerFactory; 1317 } 1318 1319 public void setPersistenceTaskRunnerFactory(TaskRunnerFactory persistenceTaskRunnerFactory) { 1320 this.persistenceTaskRunnerFactory = persistenceTaskRunnerFactory; 1321 } 1322 1323 public boolean isUseJmx() { 1324 return useJmx; 1325 } 1326 1327 public boolean isEnableStatistics() { 1328 return enableStatistics; 1329 } 1330 1331 /** 1332 * Sets whether or not the Broker's services enable statistics or not. 1333 */ 1334 public void setEnableStatistics(boolean enableStatistics) { 1335 this.enableStatistics = enableStatistics; 1336 } 1337 1338 /** 1339 * Sets whether or not the Broker's services should be exposed into JMX or 1340 * not. 1341 * @org.apache.xbean.Property propertyEditor="org.apache.activemq.util.BooleanEditor" 1342 */ 1343 public void setUseJmx(boolean useJmx) { 1344 this.useJmx = useJmx; 1345 } 1346 1347 public ObjectName getBrokerObjectName() throws MalformedObjectNameException { 1348 if (brokerObjectName == null) { 1349 brokerObjectName = createBrokerObjectName(); 1350 } 1351 return brokerObjectName; 1352 } 1353 1354 /** 1355 * Sets the JMX ObjectName for this broker 1356 */ 1357 public void setBrokerObjectName(ObjectName brokerObjectName) { 1358 this.brokerObjectName = brokerObjectName; 1359 } 1360 1361 public ManagementContext getManagementContext() { 1362 if (managementContext == null) { 1363 checkStartException(); 1364 managementContext = new ManagementContext(); 1365 } 1366 return managementContext; 1367 } 1368 1369 synchronized private void checkStartException() { 1370 if (startException != null) { 1371 throw new BrokerStoppedException(startException); 1372 } 1373 } 1374 1375 synchronized private boolean hasStartException() { 1376 return startException != null; 1377 } 1378 1379 synchronized private void setStartException(Throwable t) { 1380 startException = t; 1381 } 1382 1383 public void setManagementContext(ManagementContext managementContext) { 1384 this.managementContext = managementContext; 1385 } 1386 1387 public NetworkConnector getNetworkConnectorByName(String connectorName) { 1388 for (NetworkConnector connector : networkConnectors) { 1389 if (connector.getName().equals(connectorName)) { 1390 return connector; 1391 } 1392 } 1393 return null; 1394 } 1395 1396 public String[] getNetworkConnectorURIs() { 1397 return networkConnectorURIs; 1398 } 1399 1400 public void setNetworkConnectorURIs(String[] networkConnectorURIs) { 1401 this.networkConnectorURIs = networkConnectorURIs; 1402 } 1403 1404 public TransportConnector getConnectorByName(String connectorName) { 1405 for (TransportConnector connector : transportConnectors) { 1406 if (connector.getName().equals(connectorName)) { 1407 return connector; 1408 } 1409 } 1410 return null; 1411 } 1412 1413 public Map<String, String> getTransportConnectorURIsAsMap() { 1414 Map<String, String> answer = new HashMap<>(); 1415 for (TransportConnector connector : transportConnectors) { 1416 try { 1417 URI uri = connector.getConnectUri(); 1418 if (uri != null) { 1419 String scheme = uri.getScheme(); 1420 if (scheme != null) { 1421 answer.put(scheme.toLowerCase(Locale.ENGLISH), uri.toString()); 1422 } 1423 } 1424 } catch (Exception e) { 1425 LOG.debug("Failed to read URI to build transportURIsAsMap", e); 1426 } 1427 } 1428 return answer; 1429 } 1430 1431 public ProducerBrokerExchange getProducerBrokerExchange(ProducerInfo producerInfo){ 1432 ProducerBrokerExchange result = null; 1433 1434 for (TransportConnector connector : transportConnectors) { 1435 for (TransportConnection tc: connector.getConnections()){ 1436 result = tc.getProducerBrokerExchangeIfExists(producerInfo); 1437 if (result !=null){ 1438 return result; 1439 } 1440 } 1441 } 1442 return result; 1443 } 1444 1445 public String[] getTransportConnectorURIs() { 1446 return transportConnectorURIs; 1447 } 1448 1449 public void setTransportConnectorURIs(String[] transportConnectorURIs) { 1450 this.transportConnectorURIs = transportConnectorURIs; 1451 } 1452 1453 /** 1454 * @return Returns the jmsBridgeConnectors. 1455 */ 1456 public JmsConnector[] getJmsBridgeConnectors() { 1457 return jmsBridgeConnectors; 1458 } 1459 1460 /** 1461 * @param jmsConnectors 1462 * The jmsBridgeConnectors to set. 1463 */ 1464 public void setJmsBridgeConnectors(JmsConnector[] jmsConnectors) { 1465 this.jmsBridgeConnectors = jmsConnectors; 1466 } 1467 1468 public Service[] getServices() { 1469 return services.toArray(new Service[0]); 1470 } 1471 1472 /** 1473 * Sets the services associated with this broker. 1474 */ 1475 public void setServices(Service[] services) { 1476 this.services.clear(); 1477 if (services != null) { 1478 for (int i = 0; i < services.length; i++) { 1479 this.services.add(services[i]); 1480 } 1481 } 1482 } 1483 1484 /** 1485 * Adds a new service so that it will be started as part of the broker 1486 * lifecycle 1487 */ 1488 public void addService(Service service) { 1489 services.add(service); 1490 } 1491 1492 public void removeService(Service service) { 1493 services.remove(service); 1494 } 1495 1496 public boolean isUseLoggingForShutdownErrors() { 1497 return useLoggingForShutdownErrors; 1498 } 1499 1500 /** 1501 * Sets whether or not we should use commons-logging when reporting errors 1502 * when shutting down the broker 1503 */ 1504 public void setUseLoggingForShutdownErrors(boolean useLoggingForShutdownErrors) { 1505 this.useLoggingForShutdownErrors = useLoggingForShutdownErrors; 1506 } 1507 1508 public boolean isUseShutdownHook() { 1509 return useShutdownHook; 1510 } 1511 1512 /** 1513 * Sets whether or not we should use a shutdown handler to close down the 1514 * broker cleanly if the JVM is terminated. It is recommended you leave this 1515 * enabled. 1516 */ 1517 public void setUseShutdownHook(boolean useShutdownHook) { 1518 this.useShutdownHook = useShutdownHook; 1519 } 1520 1521 public boolean isAdvisorySupport() { 1522 return advisorySupport; 1523 } 1524 1525 /** 1526 * Allows the support of advisory messages to be disabled for performance 1527 * reasons. 1528 * @org.apache.xbean.Property propertyEditor="org.apache.activemq.util.BooleanEditor" 1529 */ 1530 public void setAdvisorySupport(boolean advisorySupport) { 1531 this.advisorySupport = advisorySupport; 1532 } 1533 1534 public boolean isAnonymousProducerAdvisorySupport() { 1535 return anonymousProducerAdvisorySupport; 1536 } 1537 1538 public void setAnonymousProducerAdvisorySupport(boolean anonymousProducerAdvisorySupport) { 1539 this.anonymousProducerAdvisorySupport = anonymousProducerAdvisorySupport; 1540 } 1541 1542 public List<TransportConnector> getTransportConnectors() { 1543 return new ArrayList<>(transportConnectors); 1544 } 1545 1546 /** 1547 * Sets the transport connectors which this broker will listen on for new 1548 * clients 1549 * 1550 * @org.apache.xbean.Property 1551 * nestedType="org.apache.activemq.broker.TransportConnector" 1552 */ 1553 public void setTransportConnectors(List<TransportConnector> transportConnectors) throws Exception { 1554 for (TransportConnector connector : transportConnectors) { 1555 addConnector(connector); 1556 } 1557 } 1558 1559 public TransportConnector getTransportConnectorByName(String name){ 1560 for (TransportConnector transportConnector : transportConnectors){ 1561 if (name.equals(transportConnector.getName())){ 1562 return transportConnector; 1563 } 1564 } 1565 return null; 1566 } 1567 1568 public TransportConnector getTransportConnectorByScheme(String scheme){ 1569 for (TransportConnector transportConnector : transportConnectors){ 1570 if (scheme.equals(transportConnector.getUri().getScheme())){ 1571 return transportConnector; 1572 } 1573 } 1574 return null; 1575 } 1576 1577 public List<NetworkConnector> getNetworkConnectors() { 1578 return new ArrayList<>(networkConnectors); 1579 } 1580 1581 public List<ProxyConnector> getProxyConnectors() { 1582 return new ArrayList<>(proxyConnectors); 1583 } 1584 1585 /** 1586 * Sets the network connectors which this broker will use to connect to 1587 * other brokers in a federated network 1588 * 1589 * @org.apache.xbean.Property 1590 * nestedType="org.apache.activemq.network.NetworkConnector" 1591 */ 1592 public void setNetworkConnectors(List<?> networkConnectors) throws Exception { 1593 for (Object connector : networkConnectors) { 1594 addNetworkConnector((NetworkConnector) connector); 1595 } 1596 } 1597 1598 /** 1599 * Sets the network connectors which this broker will use to connect to 1600 * other brokers in a federated network 1601 */ 1602 public void setProxyConnectors(List<?> proxyConnectors) throws Exception { 1603 for (Object connector : proxyConnectors) { 1604 addProxyConnector((ProxyConnector) connector); 1605 } 1606 } 1607 1608 public PolicyMap getDestinationPolicy() { 1609 return destinationPolicy; 1610 } 1611 1612 /** 1613 * Sets the destination specific policies available either for exact 1614 * destinations or for wildcard areas of destinations. 1615 */ 1616 public void setDestinationPolicy(PolicyMap policyMap) { 1617 this.destinationPolicy = policyMap; 1618 } 1619 1620 public BrokerPlugin[] getPlugins() { 1621 return plugins; 1622 } 1623 1624 /** 1625 * Sets a number of broker plugins to install such as for security 1626 * authentication or authorization 1627 */ 1628 public void setPlugins(BrokerPlugin[] plugins) { 1629 this.plugins = plugins; 1630 } 1631 1632 public MessageAuthorizationPolicy getMessageAuthorizationPolicy() { 1633 return messageAuthorizationPolicy; 1634 } 1635 1636 /** 1637 * Sets the policy used to decide if the current connection is authorized to 1638 * consume a given message 1639 */ 1640 public void setMessageAuthorizationPolicy(MessageAuthorizationPolicy messageAuthorizationPolicy) { 1641 this.messageAuthorizationPolicy = messageAuthorizationPolicy; 1642 } 1643 1644 /** 1645 * Delete all messages from the persistent store 1646 * 1647 * @throws IOException 1648 */ 1649 public void deleteAllMessages() throws IOException { 1650 getPersistenceAdapter().deleteAllMessages(); 1651 } 1652 1653 public boolean isDeleteAllMessagesOnStartup() { 1654 return deleteAllMessagesOnStartup; 1655 } 1656 1657 /** 1658 * Sets whether or not all messages are deleted on startup - mostly only 1659 * useful for testing. 1660 * @org.apache.xbean.Property propertyEditor="org.apache.activemq.util.BooleanEditor" 1661 */ 1662 public void setDeleteAllMessagesOnStartup(boolean deletePersistentMessagesOnStartup) { 1663 this.deleteAllMessagesOnStartup = deletePersistentMessagesOnStartup; 1664 } 1665 1666 public URI getVmConnectorURI() { 1667 if (vmConnectorURI == null) { 1668 try { 1669 vmConnectorURI = new URI("vm://" + getBrokerName()); 1670 } catch (URISyntaxException e) { 1671 LOG.error("Badly formed URI from {}", getBrokerName(), e); 1672 } 1673 } 1674 return vmConnectorURI; 1675 } 1676 1677 public void setVmConnectorURI(URI vmConnectorURI) { 1678 this.vmConnectorURI = vmConnectorURI; 1679 } 1680 1681 public String getDefaultSocketURIString() { 1682 if (started.get()) { 1683 if (this.defaultSocketURIString == null) { 1684 for (TransportConnector tc:this.transportConnectors) { 1685 String result = null; 1686 try { 1687 result = tc.getPublishableConnectString(); 1688 } catch (Exception e) { 1689 LOG.warn("Failed to get the ConnectURI for {}", tc, e); 1690 } 1691 if (result != null) { 1692 // find first publishable uri 1693 if (tc.isUpdateClusterClients() || tc.isRebalanceClusterClients()) { 1694 this.defaultSocketURIString = result; 1695 break; 1696 } else { 1697 // or use the first defined 1698 if (this.defaultSocketURIString == null) { 1699 this.defaultSocketURIString = result; 1700 } 1701 } 1702 } 1703 } 1704 1705 } 1706 return this.defaultSocketURIString; 1707 } 1708 return null; 1709 } 1710 1711 /** 1712 * @return Returns the shutdownOnMasterFailure. 1713 */ 1714 public boolean isShutdownOnMasterFailure() { 1715 return shutdownOnMasterFailure; 1716 } 1717 1718 /** 1719 * @param shutdownOnMasterFailure 1720 * The shutdownOnMasterFailure to set. 1721 */ 1722 public void setShutdownOnMasterFailure(boolean shutdownOnMasterFailure) { 1723 this.shutdownOnMasterFailure = shutdownOnMasterFailure; 1724 } 1725 1726 public boolean isKeepDurableSubsActive() { 1727 return keepDurableSubsActive; 1728 } 1729 1730 public void setKeepDurableSubsActive(boolean keepDurableSubsActive) { 1731 this.keepDurableSubsActive = keepDurableSubsActive; 1732 } 1733 1734 public boolean isEnableMessageExpirationOnActiveDurableSubs() { 1735 return enableMessageExpirationOnActiveDurableSubs; 1736 } 1737 1738 public void setEnableMessageExpirationOnActiveDurableSubs(boolean enableMessageExpirationOnActiveDurableSubs) { 1739 this.enableMessageExpirationOnActiveDurableSubs = enableMessageExpirationOnActiveDurableSubs; 1740 } 1741 1742 public boolean isUseVirtualTopics() { 1743 return useVirtualTopics; 1744 } 1745 1746 /** 1747 * Sets whether or not <a 1748 * href="http://activemq.apache.org/virtual-destinations.html">Virtual 1749 * Topics</a> should be supported by default if they have not been 1750 * explicitly configured. 1751 */ 1752 public void setUseVirtualTopics(boolean useVirtualTopics) { 1753 this.useVirtualTopics = useVirtualTopics; 1754 } 1755 1756 public DestinationInterceptor[] getDestinationInterceptors() { 1757 return destinationInterceptors; 1758 } 1759 1760 public boolean isUseMirroredQueues() { 1761 return useMirroredQueues; 1762 } 1763 1764 /** 1765 * Sets whether or not <a 1766 * href="http://activemq.apache.org/mirrored-queues.html">Mirrored 1767 * Queues</a> should be supported by default if they have not been 1768 * explicitly configured. 1769 */ 1770 public void setUseMirroredQueues(boolean useMirroredQueues) { 1771 this.useMirroredQueues = useMirroredQueues; 1772 } 1773 1774 /** 1775 * Sets the destination interceptors to use 1776 */ 1777 public void setDestinationInterceptors(DestinationInterceptor[] destinationInterceptors) { 1778 this.destinationInterceptors = destinationInterceptors; 1779 } 1780 1781 public ActiveMQDestination[] getDestinations() { 1782 return destinations; 1783 } 1784 1785 /** 1786 * Sets the destinations which should be loaded/created on startup 1787 */ 1788 public void setDestinations(ActiveMQDestination[] destinations) { 1789 this.destinations = destinations; 1790 } 1791 1792 /** 1793 * @return the tempDataStore 1794 */ 1795 public synchronized PListStore getTempDataStore() { 1796 if (tempDataStore == null && !hasStartException()) { 1797 if (!isPersistent()) { 1798 return null; 1799 } 1800 1801 try { 1802 PersistenceAdapter pa = getPersistenceAdapter(); 1803 if( pa!=null && pa instanceof PListStore) { 1804 return (PListStore) pa; 1805 } 1806 } catch (IOException e) { 1807 throw new RuntimeException(e); 1808 } 1809 1810 try { 1811 String clazz = "org.apache.activemq.store.kahadb.plist.PListStoreImpl"; 1812 this.tempDataStore = (PListStore) getClass().getClassLoader().loadClass(clazz).newInstance(); 1813 this.tempDataStore.setDirectory(getTmpDataDirectory()); 1814 configureService(tempDataStore); 1815 } catch (ClassNotFoundException e) { 1816 throw new RuntimeException("Kahadb class PListStoreImpl not found. Add activemq-kahadb jar or set persistent to false on BrokerService.", e); 1817 } catch (Exception e) { 1818 throw new RuntimeException(e); 1819 } 1820 } 1821 return tempDataStore; 1822 } 1823 1824 /** 1825 * @param tempDataStore 1826 * the tempDataStore to set 1827 */ 1828 public void setTempDataStore(PListStore tempDataStore) { 1829 this.tempDataStore = tempDataStore; 1830 if (tempDataStore != null) { 1831 if (tmpDataDirectory == null) { 1832 tmpDataDirectory = tempDataStore.getDirectory(); 1833 } else if (tempDataStore.getDirectory() == null) { 1834 tempDataStore.setDirectory(tmpDataDirectory); 1835 } 1836 } 1837 configureService(tempDataStore); 1838 } 1839 1840 public int getPersistenceThreadPriority() { 1841 return persistenceThreadPriority; 1842 } 1843 1844 public void setPersistenceThreadPriority(int persistenceThreadPriority) { 1845 this.persistenceThreadPriority = persistenceThreadPriority; 1846 } 1847 1848 /** 1849 * @return the useLocalHostBrokerName 1850 */ 1851 public boolean isUseLocalHostBrokerName() { 1852 return this.useLocalHostBrokerName; 1853 } 1854 1855 /** 1856 * @param useLocalHostBrokerName 1857 * the useLocalHostBrokerName to set 1858 */ 1859 public void setUseLocalHostBrokerName(boolean useLocalHostBrokerName) { 1860 this.useLocalHostBrokerName = useLocalHostBrokerName; 1861 if (useLocalHostBrokerName && !started.get() && brokerName == null || brokerName == DEFAULT_BROKER_NAME) { 1862 brokerName = LOCAL_HOST_NAME; 1863 } 1864 } 1865 1866 /** 1867 * Looks up and lazily creates if necessary the destination for the given 1868 * JMS name 1869 */ 1870 public Destination getDestination(ActiveMQDestination destination) throws Exception { 1871 return getBroker().addDestination(getAdminConnectionContext(), destination,false); 1872 } 1873 1874 public void removeDestination(ActiveMQDestination destination) throws Exception { 1875 getBroker().removeDestination(getAdminConnectionContext(), destination, 0); 1876 } 1877 1878 public int getProducerSystemUsagePortion() { 1879 return producerSystemUsagePortion; 1880 } 1881 1882 public void setProducerSystemUsagePortion(int producerSystemUsagePortion) { 1883 this.producerSystemUsagePortion = producerSystemUsagePortion; 1884 } 1885 1886 public int getConsumerSystemUsagePortion() { 1887 return consumerSystemUsagePortion; 1888 } 1889 1890 public void setConsumerSystemUsagePortion(int consumerSystemUsagePortion) { 1891 this.consumerSystemUsagePortion = consumerSystemUsagePortion; 1892 } 1893 1894 public boolean isSplitSystemUsageForProducersConsumers() { 1895 return splitSystemUsageForProducersConsumers; 1896 } 1897 1898 public void setSplitSystemUsageForProducersConsumers(boolean splitSystemUsageForProducersConsumers) { 1899 this.splitSystemUsageForProducersConsumers = splitSystemUsageForProducersConsumers; 1900 } 1901 1902 public boolean isMonitorConnectionSplits() { 1903 return monitorConnectionSplits; 1904 } 1905 1906 public void setMonitorConnectionSplits(boolean monitorConnectionSplits) { 1907 this.monitorConnectionSplits = monitorConnectionSplits; 1908 } 1909 1910 public int getTaskRunnerPriority() { 1911 return taskRunnerPriority; 1912 } 1913 1914 public void setTaskRunnerPriority(int taskRunnerPriority) { 1915 this.taskRunnerPriority = taskRunnerPriority; 1916 } 1917 1918 public boolean isDedicatedTaskRunner() { 1919 return dedicatedTaskRunner; 1920 } 1921 1922 public void setDedicatedTaskRunner(boolean dedicatedTaskRunner) { 1923 this.dedicatedTaskRunner = dedicatedTaskRunner; 1924 } 1925 1926 public boolean isCacheTempDestinations() { 1927 return cacheTempDestinations; 1928 } 1929 1930 public void setCacheTempDestinations(boolean cacheTempDestinations) { 1931 this.cacheTempDestinations = cacheTempDestinations; 1932 } 1933 1934 public int getTimeBeforePurgeTempDestinations() { 1935 return timeBeforePurgeTempDestinations; 1936 } 1937 1938 public void setTimeBeforePurgeTempDestinations(int timeBeforePurgeTempDestinations) { 1939 this.timeBeforePurgeTempDestinations = timeBeforePurgeTempDestinations; 1940 } 1941 1942 public boolean isUseTempMirroredQueues() { 1943 return useTempMirroredQueues; 1944 } 1945 1946 public void setUseTempMirroredQueues(boolean useTempMirroredQueues) { 1947 this.useTempMirroredQueues = useTempMirroredQueues; 1948 } 1949 1950 public synchronized JobSchedulerStore getJobSchedulerStore() { 1951 1952 // If support is off don't allow any scheduler even is user configured their own. 1953 if (!isSchedulerSupport()) { 1954 return null; 1955 } 1956 1957 // If the user configured their own we use it even if persistence is disabled since 1958 // we don't know anything about their implementation. 1959 if (jobSchedulerStore == null && !hasStartException()) { 1960 1961 if (!isPersistent()) { 1962 this.jobSchedulerStore = new InMemoryJobSchedulerStore(); 1963 configureService(jobSchedulerStore); 1964 return this.jobSchedulerStore; 1965 } 1966 1967 try { 1968 PersistenceAdapter pa = getPersistenceAdapter(); 1969 if (pa != null) { 1970 this.jobSchedulerStore = pa.createJobSchedulerStore(); 1971 jobSchedulerStore.setDirectory(getSchedulerDirectoryFile()); 1972 configureService(jobSchedulerStore); 1973 return this.jobSchedulerStore; 1974 } 1975 } catch (IOException e) { 1976 throw new RuntimeException(e); 1977 } catch (UnsupportedOperationException ex) { 1978 // It's ok if the store doesn't implement a scheduler. 1979 } catch (Exception e) { 1980 throw new RuntimeException(e); 1981 } 1982 1983 try { 1984 PersistenceAdapter pa = getPersistenceAdapter(); 1985 if (pa != null && pa instanceof JobSchedulerStore) { 1986 this.jobSchedulerStore = (JobSchedulerStore) pa; 1987 configureService(jobSchedulerStore); 1988 return this.jobSchedulerStore; 1989 } 1990 } catch (IOException e) { 1991 throw new RuntimeException(e); 1992 } 1993 1994 // Load the KahaDB store as a last resort, this only works if KahaDB is 1995 // included at runtime, otherwise this will fail. User should disable 1996 // scheduler support if this fails. 1997 try { 1998 String clazz = "org.apache.activemq.store.kahadb.KahaDBPersistenceAdapter"; 1999 PersistenceAdapter adaptor = (PersistenceAdapter)getClass().getClassLoader().loadClass(clazz).newInstance(); 2000 jobSchedulerStore = adaptor.createJobSchedulerStore(); 2001 jobSchedulerStore.setDirectory(getSchedulerDirectoryFile()); 2002 configureService(jobSchedulerStore); 2003 LOG.info("JobScheduler using directory: {}", getSchedulerDirectoryFile()); 2004 } catch (Exception e) { 2005 throw new RuntimeException(e); 2006 } 2007 } 2008 return jobSchedulerStore; 2009 } 2010 2011 public void setJobSchedulerStore(JobSchedulerStore jobSchedulerStore) { 2012 this.jobSchedulerStore = jobSchedulerStore; 2013 configureService(jobSchedulerStore); 2014 } 2015 2016 // 2017 // Implementation methods 2018 // ------------------------------------------------------------------------- 2019 /** 2020 * Handles any lazy-creation helper properties which are added to make 2021 * things easier to configure inside environments such as Spring 2022 * 2023 * @throws Exception 2024 */ 2025 protected void processHelperProperties() throws Exception { 2026 if (transportConnectorURIs != null) { 2027 for (int i = 0; i < transportConnectorURIs.length; i++) { 2028 String uri = transportConnectorURIs[i]; 2029 addConnector(uri); 2030 } 2031 } 2032 if (networkConnectorURIs != null) { 2033 for (int i = 0; i < networkConnectorURIs.length; i++) { 2034 String uri = networkConnectorURIs[i]; 2035 addNetworkConnector(uri); 2036 } 2037 } 2038 if (jmsBridgeConnectors != null) { 2039 for (int i = 0; i < jmsBridgeConnectors.length; i++) { 2040 addJmsConnector(jmsBridgeConnectors[i]); 2041 } 2042 } 2043 } 2044 2045 /** 2046 * Check that the store usage limit is not greater than max usable 2047 * space and adjust if it is 2048 */ 2049 protected void checkStoreUsageLimits() throws Exception { 2050 final SystemUsage usage = getSystemUsage(); 2051 2052 if (getPersistenceAdapter() != null) { 2053 PersistenceAdapter adapter = getPersistenceAdapter(); 2054 checkUsageLimit(adapter.getDirectory(), usage.getStoreUsage(), usage.getStoreUsage().getPercentLimit()); 2055 2056 long maxJournalFileSize = 0; 2057 long storeLimit = usage.getStoreUsage().getLimit(); 2058 2059 if (adapter instanceof JournaledStore) { 2060 maxJournalFileSize = ((JournaledStore) adapter).getJournalMaxFileLength(); 2061 } 2062 2063 if (storeLimit > 0 && storeLimit < maxJournalFileSize) { 2064 LOG.error("Store limit is " + storeLimit / (1024 * 1024) + 2065 " mb, whilst the max journal file size for the store is: " + 2066 maxJournalFileSize / (1024 * 1024) + " mb, " + 2067 "the store will not accept any data when used."); 2068 2069 } 2070 } 2071 } 2072 2073 /** 2074 * Check that temporary usage limit is not greater than max usable 2075 * space and adjust if it is 2076 */ 2077 protected void checkTmpStoreUsageLimits() throws Exception { 2078 final SystemUsage usage = getSystemUsage(); 2079 2080 File tmpDir = getTmpDataDirectory(); 2081 2082 if (tmpDir != null) { 2083 checkUsageLimit(tmpDir, usage.getTempUsage(), usage.getTempUsage().getPercentLimit()); 2084 2085 if (isPersistent()) { 2086 long maxJournalFileSize; 2087 2088 PListStore store = usage.getTempUsage().getStore(); 2089 if (store != null && store instanceof JournaledStore) { 2090 maxJournalFileSize = ((JournaledStore) store).getJournalMaxFileLength(); 2091 } else { 2092 maxJournalFileSize = DEFAULT_MAX_FILE_LENGTH; 2093 } 2094 long storeLimit = usage.getTempUsage().getLimit(); 2095 2096 if (storeLimit > 0 && storeLimit < maxJournalFileSize) { 2097 LOG.error("Temporary Store limit is " + storeLimit / (1024 * 1024) + 2098 " mb, whilst the max journal file size for the temporary store is: " + 2099 maxJournalFileSize / (1024 * 1024) + " mb, " + 2100 "the temp store will not accept any data when used."); 2101 } 2102 } 2103 } 2104 } 2105 2106 protected void checkUsageLimit(File dir, PercentLimitUsage<?> storeUsage, int percentLimit) throws ConfigurationException { 2107 if (dir != null) { 2108 dir = StoreUtil.findParentDirectory(dir); 2109 String storeName = storeUsage instanceof StoreUsage ? "Store" : "Temporary Store"; 2110 long storeLimit = storeUsage.getLimit(); 2111 long storeCurrent = storeUsage.getUsage(); 2112 long totalSpace = storeUsage.getTotal() > 0 ? storeUsage.getTotal() : dir.getTotalSpace(); 2113 long totalUsableSpace = (storeUsage.getTotal() > 0 ? storeUsage.getTotal() : dir.getUsableSpace()) + storeCurrent; 2114 if (totalUsableSpace < 0 || totalSpace < 0) { 2115 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"; 2116 LOG.error(message); 2117 throw new ConfigurationException(message); 2118 } 2119 //compute byte value of the percent limit 2120 long bytePercentLimit = totalSpace * percentLimit / 100; 2121 int oneMeg = 1024 * 1024; 2122 2123 //Check if the store limit is less than the percent Limit that was set and also 2124 //the usable space...this means we can grow the store larger 2125 //Changes in partition size (total space) as well as changes in usable space should 2126 //be detected here 2127 if (diskUsageCheckRegrowThreshold > -1 && percentLimit > 0 2128 && storeUsage.getTotal() == 0 2129 && storeLimit < bytePercentLimit && storeLimit < totalUsableSpace){ 2130 2131 // set the limit to be bytePercentLimit or usableSpace if 2132 // usableSpace is less than the percentLimit 2133 long newLimit = bytePercentLimit > totalUsableSpace ? totalUsableSpace : bytePercentLimit; 2134 2135 //To prevent changing too often, check threshold 2136 if (newLimit - storeLimit >= diskUsageCheckRegrowThreshold) { 2137 LOG.info("Usable disk space has been increased, attempting to regrow " + storeName + " limit to " 2138 + percentLimit + "% of the partition size."); 2139 storeUsage.setLimit(newLimit); 2140 LOG.info(storeName + " limit has been increased to " + newLimit * 100 / totalSpace 2141 + "% (" + newLimit / oneMeg + " mb) of the partition size."); 2142 } 2143 2144 //check if the limit is too large for the amount of usable space 2145 } else if (storeLimit > totalUsableSpace) { 2146 final String message = storeName + " limit is " + storeLimit / oneMeg 2147 + " mb (current store usage is " + storeCurrent / oneMeg 2148 + " mb). The data directory: " + dir.getAbsolutePath() 2149 + " only has " + totalUsableSpace / oneMeg 2150 + " mb of usable space."; 2151 2152 if (!isAdjustUsageLimits()) { 2153 LOG.error(message); 2154 throw new ConfigurationException(message); 2155 } 2156 2157 if (percentLimit > 0) { 2158 LOG.warn(storeName + " limit has been set to " 2159 + percentLimit + "% (" + bytePercentLimit / oneMeg + " mb)" 2160 + " of the partition size but there is not enough usable space." 2161 + " The current store limit (which may have been adjusted by a" 2162 + " previous usage limit check) is set to (" + storeLimit / oneMeg + " mb)" 2163 + " but only " + totalUsableSpace * 100 / totalSpace + "% (" + totalUsableSpace / oneMeg + " mb)" 2164 + " is available - resetting limit"); 2165 } else { 2166 LOG.warn(message + " - resetting to maximum available disk space: " + 2167 totalUsableSpace / oneMeg + " mb"); 2168 } 2169 storeUsage.setLimit(totalUsableSpace); 2170 } 2171 } 2172 } 2173 2174 /** 2175 * Schedules a periodic task based on schedulePeriodForDiskLimitCheck to 2176 * update store and temporary store limits if the amount of available space 2177 * plus current store size is less than the existing configured limit 2178 */ 2179 protected void scheduleDiskUsageLimitsCheck() throws IOException { 2180 if (schedulePeriodForDiskUsageCheck > 0 && 2181 (getPersistenceAdapter() != null || getTmpDataDirectory() != null)) { 2182 Runnable diskLimitCheckTask = new Runnable() { 2183 @Override 2184 public void run() { 2185 try { 2186 checkStoreUsageLimits(); 2187 } catch (Throwable e) { 2188 LOG.error("Failed to check persistent disk usage limits", e); 2189 } 2190 2191 try { 2192 checkTmpStoreUsageLimits(); 2193 } catch (Throwable e) { 2194 LOG.error("Failed to check temporary store usage limits", e); 2195 } 2196 } 2197 }; 2198 scheduler.executePeriodically(diskLimitCheckTask, schedulePeriodForDiskUsageCheck); 2199 } 2200 } 2201 2202 protected void checkMemorySystemUsageLimits() throws Exception { 2203 final SystemUsage usage = getSystemUsage(); 2204 long memLimit = usage.getMemoryUsage().getLimit(); 2205 long jvmLimit = Runtime.getRuntime().maxMemory(); 2206 2207 if (memLimit > jvmLimit) { 2208 final String message = "Memory Usage for the Broker (" + memLimit / (1024 * 1024) 2209 + "mb) is more than the maximum available for the JVM: " + jvmLimit / (1024 * 1024); 2210 2211 if (adjustUsageLimits) { 2212 usage.getMemoryUsage().setPercentOfJvmHeap(70); 2213 LOG.warn(message + " mb - resetting to 70% of maximum available: " + (usage.getMemoryUsage().getLimit() / (1024 * 1024)) + " mb"); 2214 } else { 2215 LOG.error(message); 2216 throw new ConfigurationException(message); 2217 } 2218 } 2219 } 2220 2221 protected void checkStoreSystemUsageLimits() throws Exception { 2222 final SystemUsage usage = getSystemUsage(); 2223 2224 //Check the persistent store and temp store limits if they exist 2225 //and schedule a periodic check to update disk limits if 2226 //schedulePeriodForDiskLimitCheck is set 2227 checkStoreUsageLimits(); 2228 checkTmpStoreUsageLimits(); 2229 scheduleDiskUsageLimitsCheck(); 2230 2231 if (getJobSchedulerStore() != null) { 2232 JobSchedulerStore scheduler = getJobSchedulerStore(); 2233 File schedulerDir = scheduler.getDirectory(); 2234 if (schedulerDir != null) { 2235 2236 String schedulerDirPath = schedulerDir.getAbsolutePath(); 2237 if (!schedulerDir.isAbsolute()) { 2238 schedulerDir = new File(schedulerDirPath); 2239 } 2240 2241 while (schedulerDir != null && !schedulerDir.isDirectory()) { 2242 schedulerDir = schedulerDir.getParentFile(); 2243 } 2244 long schedulerLimit = usage.getJobSchedulerUsage().getLimit(); 2245 long dirFreeSpace = schedulerDir.getUsableSpace(); 2246 if (schedulerLimit > dirFreeSpace) { 2247 LOG.warn("Job Scheduler Store limit is " + schedulerLimit / (1024 * 1024) + 2248 " mb, whilst the data directory: " + schedulerDir.getAbsolutePath() + 2249 " only has " + dirFreeSpace / (1024 * 1024) + " mb of usable space - resetting to " + 2250 dirFreeSpace / (1024 * 1024) + " mb."); 2251 usage.getJobSchedulerUsage().setLimit(dirFreeSpace); 2252 } 2253 } 2254 } 2255 } 2256 2257 public void stopAllConnectors(ServiceStopper stopper) { 2258 for (Iterator<NetworkConnector> iter = getNetworkConnectors().iterator(); iter.hasNext();) { 2259 NetworkConnector connector = iter.next(); 2260 unregisterNetworkConnectorMBean(connector); 2261 stopper.stop(connector); 2262 } 2263 for (Iterator<ProxyConnector> iter = getProxyConnectors().iterator(); iter.hasNext();) { 2264 ProxyConnector connector = iter.next(); 2265 stopper.stop(connector); 2266 } 2267 for (Iterator<JmsConnector> iter = jmsConnectors.iterator(); iter.hasNext();) { 2268 JmsConnector connector = iter.next(); 2269 stopper.stop(connector); 2270 } 2271 for (Iterator<TransportConnector> iter = getTransportConnectors().iterator(); iter.hasNext();) { 2272 TransportConnector connector = iter.next(); 2273 try { 2274 unregisterConnectorMBean(connector); 2275 } catch (IOException e) { 2276 } 2277 stopper.stop(connector); 2278 } 2279 } 2280 2281 protected TransportConnector registerConnectorMBean(TransportConnector connector) throws IOException { 2282 try { 2283 ObjectName objectName = createConnectorObjectName(connector); 2284 connector = connector.asManagedConnector(getManagementContext(), objectName); 2285 ConnectorViewMBean view = new ConnectorView(connector); 2286 AnnotatedMBean.registerMBean(getManagementContext(), view, objectName); 2287 return connector; 2288 } catch (Throwable e) { 2289 throw IOExceptionSupport.create("Transport Connector could not be registered in JMX: " + e, e); 2290 } 2291 } 2292 2293 protected void unregisterConnectorMBean(TransportConnector connector) throws IOException { 2294 if (isUseJmx()) { 2295 try { 2296 ObjectName objectName = createConnectorObjectName(connector); 2297 getManagementContext().unregisterMBean(objectName); 2298 } catch (Throwable e) { 2299 throw IOExceptionSupport.create( 2300 "Transport Connector could not be unregistered in JMX: " + e.getMessage(), e); 2301 } 2302 } 2303 } 2304 2305 protected PersistenceAdapter registerPersistenceAdapterMBean(PersistenceAdapter adaptor) throws IOException { 2306 return adaptor; 2307 } 2308 2309 protected void unregisterPersistenceAdapterMBean(PersistenceAdapter adaptor) throws IOException { 2310 if (isUseJmx()) {} 2311 } 2312 2313 private ObjectName createConnectorObjectName(TransportConnector connector) throws MalformedObjectNameException { 2314 return BrokerMBeanSupport.createConnectorName(getBrokerObjectName(), "clientConnectors", connector.getName()); 2315 } 2316 2317 public void registerNetworkConnectorMBean(NetworkConnector connector) throws IOException { 2318 NetworkConnectorViewMBean view = new NetworkConnectorView(connector); 2319 try { 2320 ObjectName objectName = createNetworkConnectorObjectName(connector); 2321 connector.setObjectName(objectName); 2322 AnnotatedMBean.registerMBean(getManagementContext(), view, objectName); 2323 } catch (Throwable e) { 2324 throw IOExceptionSupport.create("Network Connector could not be registered in JMX: " + e.getMessage(), e); 2325 } 2326 } 2327 2328 public ObjectName createNetworkConnectorObjectName(NetworkConnector connector) throws MalformedObjectNameException { 2329 return BrokerMBeanSupport.createNetworkConnectorName(getBrokerObjectName(), "networkConnectors", connector.getName()); 2330 } 2331 2332 public ObjectName createDuplexNetworkConnectorObjectName(String transport) throws MalformedObjectNameException { 2333 return BrokerMBeanSupport.createNetworkConnectorName(getBrokerObjectName(), "duplexNetworkConnectors", transport); 2334 } 2335 2336 protected void unregisterNetworkConnectorMBean(NetworkConnector connector) { 2337 if (isUseJmx()) { 2338 try { 2339 ObjectName objectName = createNetworkConnectorObjectName(connector); 2340 getManagementContext().unregisterMBean(objectName); 2341 } catch (Exception e) { 2342 LOG.warn("Network Connector could not be unregistered from JMX due " + e.getMessage() + ". This exception is ignored.", e); 2343 } 2344 } 2345 } 2346 2347 protected void registerProxyConnectorMBean(ProxyConnector connector) throws IOException { 2348 ProxyConnectorView view = new ProxyConnectorView(connector); 2349 try { 2350 ObjectName objectName = BrokerMBeanSupport.createNetworkConnectorName(getBrokerObjectName(), "proxyConnectors", connector.getName()); 2351 AnnotatedMBean.registerMBean(getManagementContext(), view, objectName); 2352 } catch (Throwable e) { 2353 throw IOExceptionSupport.create("Broker could not be registered in JMX: " + e.getMessage(), e); 2354 } 2355 } 2356 2357 protected void registerJmsConnectorMBean(JmsConnector connector) throws IOException { 2358 JmsConnectorView view = new JmsConnectorView(connector); 2359 try { 2360 ObjectName objectName = BrokerMBeanSupport.createNetworkConnectorName(getBrokerObjectName(), "jmsConnectors", connector.getName()); 2361 AnnotatedMBean.registerMBean(getManagementContext(), view, objectName); 2362 } catch (Throwable e) { 2363 throw IOExceptionSupport.create("Broker could not be registered in JMX: " + e.getMessage(), e); 2364 } 2365 } 2366 2367 /** 2368 * Factory method to create a new broker 2369 * 2370 * @throws Exception 2371 */ 2372 protected Broker createBroker() throws Exception { 2373 regionBroker = createRegionBroker(); 2374 Broker broker = addInterceptors(regionBroker); 2375 // Add a filter that will stop access to the broker once stopped 2376 broker = new MutableBrokerFilter(broker) { 2377 Broker old; 2378 2379 @Override 2380 public void stop() throws Exception { 2381 old = this.next.getAndSet(new ErrorBroker("Broker has been stopped: " + this) { 2382 // Just ignore additional stop actions. 2383 @Override 2384 public void stop() throws Exception { 2385 } 2386 }); 2387 old.stop(); 2388 } 2389 2390 @Override 2391 public void start() throws Exception { 2392 if (forceStart && old != null) { 2393 this.next.set(old); 2394 } 2395 getNext().start(); 2396 } 2397 }; 2398 return broker; 2399 } 2400 2401 /** 2402 * Factory method to create the core region broker onto which interceptors 2403 * are added 2404 * 2405 * @throws Exception 2406 */ 2407 protected Broker createRegionBroker() throws Exception { 2408 if (destinationInterceptors == null) { 2409 destinationInterceptors = createDefaultDestinationInterceptor(); 2410 } 2411 configureServices(destinationInterceptors); 2412 DestinationInterceptor destinationInterceptor = new CompositeDestinationInterceptor(destinationInterceptors); 2413 if (destinationFactory == null) { 2414 destinationFactory = new DestinationFactoryImpl(this, getTaskRunnerFactory(), getPersistenceAdapter()); 2415 } 2416 return createRegionBroker(destinationInterceptor); 2417 } 2418 2419 protected Broker createRegionBroker(DestinationInterceptor destinationInterceptor) throws IOException { 2420 RegionBroker regionBroker; 2421 if (isUseJmx()) { 2422 try { 2423 regionBroker = new ManagedRegionBroker(this, getManagementContext(), getBrokerObjectName(), 2424 getTaskRunnerFactory(), getConsumerSystemUsage(), destinationFactory, destinationInterceptor,getScheduler(),getExecutor()); 2425 } catch(MalformedObjectNameException me){ 2426 LOG.warn("Cannot create ManagedRegionBroker due " + me.getMessage(), me); 2427 throw new IOException(me); 2428 } 2429 } else { 2430 regionBroker = new RegionBroker(this, getTaskRunnerFactory(), getConsumerSystemUsage(), destinationFactory, 2431 destinationInterceptor,getScheduler(),getExecutor()); 2432 } 2433 destinationFactory.setRegionBroker(regionBroker); 2434 regionBroker.setKeepDurableSubsActive(keepDurableSubsActive); 2435 regionBroker.setBrokerName(getBrokerName()); 2436 regionBroker.getDestinationStatistics().setEnabled(enableStatistics); 2437 regionBroker.setAllowTempAutoCreationOnSend(isAllowTempAutoCreationOnSend()); 2438 if (brokerId != null) { 2439 regionBroker.setBrokerId(brokerId); 2440 } 2441 return regionBroker; 2442 } 2443 2444 /** 2445 * Create the default destination interceptor 2446 */ 2447 protected DestinationInterceptor[] createDefaultDestinationInterceptor() { 2448 List<DestinationInterceptor> answer = new ArrayList<>(); 2449 if (isUseVirtualTopics()) { 2450 VirtualDestinationInterceptor interceptor = new VirtualDestinationInterceptor(); 2451 VirtualTopic virtualTopic = new VirtualTopic(); 2452 virtualTopic.setName("VirtualTopic.>"); 2453 VirtualDestination[] virtualDestinations = { virtualTopic }; 2454 interceptor.setVirtualDestinations(virtualDestinations); 2455 answer.add(interceptor); 2456 } 2457 if (isUseMirroredQueues()) { 2458 MirroredQueue interceptor = new MirroredQueue(); 2459 answer.add(interceptor); 2460 } 2461 DestinationInterceptor[] array = new DestinationInterceptor[answer.size()]; 2462 answer.toArray(array); 2463 return array; 2464 } 2465 2466 /** 2467 * Strategy method to add interceptors to the broker 2468 * 2469 * @throws IOException 2470 */ 2471 protected Broker addInterceptors(Broker broker) throws Exception { 2472 if (isSchedulerSupport()) { 2473 SchedulerBroker sb = new SchedulerBroker(this, broker, getJobSchedulerStore()); 2474 sb.setMaxRepeatAllowed(maxSchedulerRepeatAllowed); 2475 if (isUseJmx()) { 2476 JobSchedulerViewMBean view = new JobSchedulerView(sb.getJobScheduler()); 2477 try { 2478 ObjectName objectName = BrokerMBeanSupport.createJobSchedulerServiceName(getBrokerObjectName()); 2479 AnnotatedMBean.registerMBean(getManagementContext(), view, objectName); 2480 this.adminView.setJMSJobScheduler(objectName); 2481 } catch (Throwable e) { 2482 throw IOExceptionSupport.create("JobScheduler could not be registered in JMX: " 2483 + e.getMessage(), e); 2484 } 2485 } 2486 broker = sb; 2487 } 2488 if (isUseJmx()) { 2489 HealthViewMBean statusView = new HealthView((ManagedRegionBroker)getRegionBroker()); 2490 try { 2491 ObjectName objectName = BrokerMBeanSupport.createHealthServiceName(getBrokerObjectName()); 2492 AnnotatedMBean.registerMBean(getManagementContext(), statusView, objectName); 2493 } catch (Throwable e) { 2494 throw IOExceptionSupport.create("Status MBean could not be registered in JMX: " 2495 + e.getMessage(), e); 2496 } 2497 } 2498 if (isAdvisorySupport()) { 2499 broker = new AdvisoryBroker(broker); 2500 } 2501 broker = new CompositeDestinationBroker(broker); 2502 broker = new TransactionBroker(broker, getPersistenceAdapter().createTransactionStore()); 2503 if (isPopulateJMSXUserID()) { 2504 UserIDBroker userIDBroker = new UserIDBroker(broker); 2505 userIDBroker.setUseAuthenticatePrincipal(isUseAuthenticatedPrincipalForJMSXUserID()); 2506 broker = userIDBroker; 2507 } 2508 if (isMonitorConnectionSplits()) { 2509 broker = new ConnectionSplitBroker(broker); 2510 } 2511 if (plugins != null) { 2512 for (int i = 0; i < plugins.length; i++) { 2513 BrokerPlugin plugin = plugins[i]; 2514 broker = plugin.installPlugin(broker); 2515 } 2516 } 2517 return broker; 2518 } 2519 2520 protected PersistenceAdapter createPersistenceAdapter() throws IOException { 2521 if (isPersistent()) { 2522 PersistenceAdapterFactory fac = getPersistenceFactory(); 2523 if (fac != null) { 2524 return fac.createPersistenceAdapter(); 2525 } else { 2526 try { 2527 String clazz = "org.apache.activemq.store.kahadb.KahaDBPersistenceAdapter"; 2528 PersistenceAdapter adaptor = (PersistenceAdapter)getClass().getClassLoader().loadClass(clazz).newInstance(); 2529 File dir = new File(getBrokerDataDirectory(),"KahaDB"); 2530 adaptor.setDirectory(dir); 2531 return adaptor; 2532 } catch (Throwable e) { 2533 throw IOExceptionSupport.create(e); 2534 } 2535 } 2536 } else { 2537 return new MemoryPersistenceAdapter(); 2538 } 2539 } 2540 2541 protected ObjectName createBrokerObjectName() throws MalformedObjectNameException { 2542 return BrokerMBeanSupport.createBrokerObjectName(getManagementContext().getJmxDomainName(), getBrokerName()); 2543 } 2544 2545 protected TransportConnector createTransportConnector(URI brokerURI) throws Exception { 2546 TransportServer transport = TransportFactorySupport.bind(this, brokerURI); 2547 return new TransportConnector(transport); 2548 } 2549 2550 /** 2551 * Extracts the port from the options 2552 */ 2553 protected Object getPort(Map<?,?> options) { 2554 Object port = options.get("port"); 2555 if (port == null) { 2556 port = DEFAULT_PORT; 2557 LOG.warn("No port specified so defaulting to: {}", port); 2558 } 2559 return port; 2560 } 2561 2562 protected void addShutdownHook() { 2563 if (useShutdownHook) { 2564 shutdownHook = new Thread("ActiveMQ ShutdownHook") { 2565 @Override 2566 public void run() { 2567 containerShutdown(); 2568 } 2569 }; 2570 Runtime.getRuntime().addShutdownHook(shutdownHook); 2571 } 2572 } 2573 2574 protected void removeShutdownHook() { 2575 if (shutdownHook != null) { 2576 try { 2577 Runtime.getRuntime().removeShutdownHook(shutdownHook); 2578 } catch (Exception e) { 2579 LOG.debug("Caught exception, must be shutting down. This exception is ignored.", e); 2580 } 2581 } 2582 } 2583 2584 /** 2585 * Sets hooks to be executed when broker shut down 2586 * 2587 * @org.apache.xbean.Property 2588 */ 2589 public void setShutdownHooks(List<Runnable> hooks) throws Exception { 2590 for (Runnable hook : hooks) { 2591 addShutdownHook(hook); 2592 } 2593 } 2594 2595 /** 2596 * Causes a clean shutdown of the container when the VM is being shut down 2597 */ 2598 protected void containerShutdown() { 2599 try { 2600 stop(); 2601 } catch (IOException e) { 2602 Throwable linkedException = e.getCause(); 2603 if (linkedException != null) { 2604 logError("Failed to shut down: " + e + ". Reason: " + linkedException, linkedException); 2605 } else { 2606 logError("Failed to shut down: " + e, e); 2607 } 2608 if (!useLoggingForShutdownErrors) { 2609 e.printStackTrace(System.err); 2610 } 2611 } catch (Exception e) { 2612 logError("Failed to shut down: " + e, e); 2613 } 2614 } 2615 2616 protected void logError(String message, Throwable e) { 2617 if (useLoggingForShutdownErrors) { 2618 LOG.error("Failed to shut down: " + e); 2619 } else { 2620 System.err.println("Failed to shut down: " + e); 2621 } 2622 } 2623 2624 /** 2625 * Starts any configured destinations on startup 2626 */ 2627 protected void startDestinations() throws Exception { 2628 if (destinations != null) { 2629 ConnectionContext adminConnectionContext = getAdminConnectionContext(); 2630 for (int i = 0; i < destinations.length; i++) { 2631 ActiveMQDestination destination = destinations[i]; 2632 getBroker().addDestination(adminConnectionContext, destination,true); 2633 } 2634 } 2635 if (isUseVirtualTopics()) { 2636 startVirtualConsumerDestinations(); 2637 } 2638 } 2639 2640 /** 2641 * Returns the broker's administration connection context used for 2642 * configuring the broker at startup 2643 */ 2644 public ConnectionContext getAdminConnectionContext() throws Exception { 2645 return BrokerSupport.getConnectionContext(getBroker()); 2646 } 2647 2648 protected void startManagementContext() throws Exception { 2649 getManagementContext().setBrokerName(brokerName); 2650 getManagementContext().start(); 2651 adminView = new BrokerView(this, null); 2652 ObjectName objectName = getBrokerObjectName(); 2653 AnnotatedMBean.registerMBean(getManagementContext(), adminView, objectName); 2654 } 2655 2656 /** 2657 * Start all transport and network connections, proxies and bridges 2658 * 2659 * @throws Exception 2660 */ 2661 public void startAllConnectors() throws Exception { 2662 final Set<ActiveMQDestination> durableDestinations = getBroker().getDurableDestinations(); 2663 List<TransportConnector> al = new ArrayList<>(); 2664 for (Iterator<TransportConnector> iter = getTransportConnectors().iterator(); iter.hasNext();) { 2665 TransportConnector connector = iter.next(); 2666 al.add(startTransportConnector(connector)); 2667 } 2668 if (al.size() > 0) { 2669 // let's clear the transportConnectors list and replace it with 2670 // the started transportConnector instances 2671 this.transportConnectors.clear(); 2672 setTransportConnectors(al); 2673 } 2674 this.slave = false; 2675 if (!stopped.get()) { 2676 ThreadPoolExecutor networkConnectorStartExecutor = null; 2677 if (isNetworkConnectorStartAsync()) { 2678 // spin up as many threads as needed 2679 networkConnectorStartExecutor = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 2680 10, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(), 2681 new ThreadFactory() { 2682 int count=0; 2683 @Override 2684 public Thread newThread(Runnable runnable) { 2685 Thread thread = new Thread(runnable, "NetworkConnector Start Thread-" +(count++)); 2686 thread.setDaemon(true); 2687 return thread; 2688 } 2689 }); 2690 } 2691 2692 for (Iterator<NetworkConnector> iter = getNetworkConnectors().iterator(); iter.hasNext();) { 2693 final NetworkConnector connector = iter.next(); 2694 connector.setLocalUri(getVmConnectorURI()); 2695 startNetworkConnector(connector, durableDestinations, networkConnectorStartExecutor); 2696 } 2697 if (networkConnectorStartExecutor != null) { 2698 // executor done when enqueued tasks are complete 2699 ThreadPoolUtils.shutdown(networkConnectorStartExecutor); 2700 } 2701 2702 for (Iterator<ProxyConnector> iter = getProxyConnectors().iterator(); iter.hasNext();) { 2703 ProxyConnector connector = iter.next(); 2704 connector.start(); 2705 } 2706 for (Iterator<JmsConnector> iter = jmsConnectors.iterator(); iter.hasNext();) { 2707 JmsConnector connector = iter.next(); 2708 connector.start(); 2709 } 2710 for (Service service : services) { 2711 configureService(service); 2712 service.start(); 2713 } 2714 } 2715 } 2716 2717 public void startNetworkConnector(final NetworkConnector connector, 2718 final ThreadPoolExecutor networkConnectorStartExecutor) throws Exception { 2719 startNetworkConnector(connector, getBroker().getDurableDestinations(), networkConnectorStartExecutor); 2720 } 2721 2722 public void startNetworkConnector(final NetworkConnector connector, 2723 final Set<ActiveMQDestination> durableDestinations, 2724 final ThreadPoolExecutor networkConnectorStartExecutor) throws Exception { 2725 connector.setBrokerName(getBrokerName()); 2726 //set the durable destinations to match the broker if not set on the connector 2727 if (connector.getDurableDestinations() == null) { 2728 connector.setDurableDestinations(durableDestinations); 2729 } 2730 String defaultSocketURI = getDefaultSocketURIString(); 2731 if (defaultSocketURI != null) { 2732 connector.setBrokerURL(defaultSocketURI); 2733 } 2734 //If using the runtime plugin to start a network connector then the mbean needs 2735 //to be added, under normal start it will already exist so check for InstanceNotFoundException 2736 if (isUseJmx()) { 2737 ObjectName networkMbean = createNetworkConnectorObjectName(connector); 2738 try { 2739 getManagementContext().getObjectInstance(networkMbean); 2740 } catch (InstanceNotFoundException e) { 2741 LOG.debug("Network connector MBean {} not found, registering", networkMbean); 2742 registerNetworkConnectorMBean(connector); 2743 } 2744 } 2745 if (networkConnectorStartExecutor != null) { 2746 networkConnectorStartExecutor.execute(new Runnable() { 2747 @Override 2748 public void run() { 2749 try { 2750 LOG.info("Async start of {}", connector); 2751 connector.start(); 2752 } catch(Exception e) { 2753 LOG.error("Async start of network connector: {} failed", connector, e); 2754 } 2755 } 2756 }); 2757 } else { 2758 connector.start(); 2759 } 2760 } 2761 2762 public TransportConnector startTransportConnector(TransportConnector connector) throws Exception { 2763 connector.setBrokerService(this); 2764 connector.setTaskRunnerFactory(getTaskRunnerFactory()); 2765 MessageAuthorizationPolicy policy = getMessageAuthorizationPolicy(); 2766 if (policy != null) { 2767 connector.setMessageAuthorizationPolicy(policy); 2768 } 2769 if (isUseJmx()) { 2770 connector = registerConnectorMBean(connector); 2771 } 2772 connector.getStatistics().setEnabled(enableStatistics); 2773 connector.start(); 2774 return connector; 2775 } 2776 2777 /** 2778 * Perform any custom dependency injection 2779 */ 2780 protected void configureServices(Object[] services) { 2781 for (Object service : services) { 2782 configureService(service); 2783 } 2784 } 2785 2786 /** 2787 * Perform any custom dependency injection 2788 */ 2789 protected void configureService(Object service) { 2790 if (service instanceof BrokerServiceAware) { 2791 BrokerServiceAware serviceAware = (BrokerServiceAware) service; 2792 serviceAware.setBrokerService(this); 2793 } 2794 } 2795 2796 public void handleIOException(IOException exception) { 2797 if (ioExceptionHandler != null) { 2798 ioExceptionHandler.handle(exception); 2799 } else { 2800 LOG.info("No IOExceptionHandler registered, ignoring IO exception", exception); 2801 } 2802 } 2803 2804 protected void startVirtualConsumerDestinations() throws Exception { 2805 checkStartException(); 2806 ConnectionContext adminConnectionContext = getAdminConnectionContext(); 2807 Set<ActiveMQDestination> destinations = destinationFactory.getDestinations(); 2808 DestinationFilter filter = getVirtualTopicConsumerDestinationFilter(); 2809 if (!destinations.isEmpty()) { 2810 for (ActiveMQDestination destination : destinations) { 2811 if (filter.matches(destination) == true) { 2812 broker.addDestination(adminConnectionContext, destination, false); 2813 } 2814 } 2815 } 2816 } 2817 2818 private DestinationFilter getVirtualTopicConsumerDestinationFilter() { 2819 // created at startup, so no sync needed 2820 if (virtualConsumerDestinationFilter == null) { 2821 Set <ActiveMQQueue> consumerDestinations = new HashSet<>(); 2822 if (destinationInterceptors != null) { 2823 for (DestinationInterceptor interceptor : destinationInterceptors) { 2824 if (interceptor instanceof VirtualDestinationInterceptor) { 2825 VirtualDestinationInterceptor virtualDestinationInterceptor = (VirtualDestinationInterceptor) interceptor; 2826 for (VirtualDestination virtualDestination: virtualDestinationInterceptor.getVirtualDestinations()) { 2827 if (virtualDestination instanceof VirtualTopic) { 2828 consumerDestinations.add(new ActiveMQQueue(((VirtualTopic) virtualDestination).getPrefix() + DestinationFilter.ANY_DESCENDENT)); 2829 } 2830 if (isUseVirtualDestSubs()) { 2831 try { 2832 broker.virtualDestinationAdded(getAdminConnectionContext(), virtualDestination); 2833 LOG.debug("Adding virtual destination: {}", virtualDestination); 2834 } catch (Exception e) { 2835 LOG.warn("Could not fire virtual destination consumer advisory", e); 2836 } 2837 } 2838 } 2839 } 2840 } 2841 } 2842 ActiveMQQueue filter = new ActiveMQQueue(); 2843 filter.setCompositeDestinations(consumerDestinations.toArray(new ActiveMQDestination[]{})); 2844 virtualConsumerDestinationFilter = DestinationFilter.parseFilter(filter); 2845 } 2846 return virtualConsumerDestinationFilter; 2847 } 2848 2849 protected synchronized ThreadPoolExecutor getExecutor() { 2850 if (this.executor == null) { 2851 this.executor = new ThreadPoolExecutor(1, 10, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(), new ThreadFactory() { 2852 2853 private long i = 0; 2854 2855 @Override 2856 public Thread newThread(Runnable runnable) { 2857 this.i++; 2858 Thread thread = new Thread(runnable, "ActiveMQ BrokerService.worker." + this.i); 2859 thread.setDaemon(true); 2860 thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { 2861 @Override 2862 public void uncaughtException(final Thread t, final Throwable e) { 2863 LOG.error("Error in thread '{}'", t.getName(), e); 2864 } 2865 }); 2866 return thread; 2867 } 2868 }, new RejectedExecutionHandler() { 2869 @Override 2870 public void rejectedExecution(final Runnable r, final ThreadPoolExecutor executor) { 2871 try { 2872 if (!executor.getQueue().offer(r, 60, TimeUnit.SECONDS)) { 2873 throw new RejectedExecutionException("Timed Out while attempting to enqueue Task."); 2874 } 2875 } catch (InterruptedException e) { 2876 throw new RejectedExecutionException("Interrupted waiting for BrokerService.worker"); 2877 } 2878 } 2879 }); 2880 } 2881 return this.executor; 2882 } 2883 2884 public synchronized Scheduler getScheduler() { 2885 if (this.scheduler==null) { 2886 this.scheduler = new Scheduler("ActiveMQ Broker["+getBrokerName()+"] Scheduler"); 2887 try { 2888 this.scheduler.start(); 2889 } catch (Exception e) { 2890 LOG.error("Failed to start Scheduler", e); 2891 } 2892 } 2893 return this.scheduler; 2894 } 2895 2896 public Broker getRegionBroker() { 2897 return regionBroker; 2898 } 2899 2900 public void setRegionBroker(Broker regionBroker) { 2901 this.regionBroker = regionBroker; 2902 } 2903 2904 public final void removePreShutdownHook(final Runnable hook) { 2905 preShutdownHooks.remove(hook); 2906 } 2907 2908 public void addShutdownHook(Runnable hook) { 2909 synchronized (shutdownHooks) { 2910 shutdownHooks.add(hook); 2911 } 2912 } 2913 2914 public void removeShutdownHook(Runnable hook) { 2915 synchronized (shutdownHooks) { 2916 shutdownHooks.remove(hook); 2917 } 2918 } 2919 2920 public boolean isSystemExitOnShutdown() { 2921 return systemExitOnShutdown; 2922 } 2923 2924 /** 2925 * @org.apache.xbean.Property propertyEditor="org.apache.activemq.util.BooleanEditor" 2926 */ 2927 public void setSystemExitOnShutdown(boolean systemExitOnShutdown) { 2928 this.systemExitOnShutdown = systemExitOnShutdown; 2929 } 2930 2931 public int getSystemExitOnShutdownExitCode() { 2932 return systemExitOnShutdownExitCode; 2933 } 2934 2935 public void setSystemExitOnShutdownExitCode(int systemExitOnShutdownExitCode) { 2936 this.systemExitOnShutdownExitCode = systemExitOnShutdownExitCode; 2937 } 2938 2939 public SslContext getSslContext() { 2940 return sslContext; 2941 } 2942 2943 public void setSslContext(SslContext sslContext) { 2944 this.sslContext = sslContext; 2945 } 2946 2947 public boolean isShutdownOnSlaveFailure() { 2948 return shutdownOnSlaveFailure; 2949 } 2950 2951 /** 2952 * @org.apache.xbean.Property propertyEditor="org.apache.activemq.util.BooleanEditor" 2953 */ 2954 public void setShutdownOnSlaveFailure(boolean shutdownOnSlaveFailure) { 2955 this.shutdownOnSlaveFailure = shutdownOnSlaveFailure; 2956 } 2957 2958 public boolean isWaitForSlave() { 2959 return waitForSlave; 2960 } 2961 2962 /** 2963 * @org.apache.xbean.Property propertyEditor="org.apache.activemq.util.BooleanEditor" 2964 */ 2965 public void setWaitForSlave(boolean waitForSlave) { 2966 this.waitForSlave = waitForSlave; 2967 } 2968 2969 public long getWaitForSlaveTimeout() { 2970 return this.waitForSlaveTimeout; 2971 } 2972 2973 public void setWaitForSlaveTimeout(long waitForSlaveTimeout) { 2974 this.waitForSlaveTimeout = waitForSlaveTimeout; 2975 } 2976 2977 /** 2978 * Get the passiveSlave 2979 * @return the passiveSlave 2980 */ 2981 public boolean isPassiveSlave() { 2982 return this.passiveSlave; 2983 } 2984 2985 /** 2986 * Set the passiveSlave 2987 * @param passiveSlave the passiveSlave to set 2988 * @org.apache.xbean.Property propertyEditor="org.apache.activemq.util.BooleanEditor" 2989 */ 2990 public void setPassiveSlave(boolean passiveSlave) { 2991 this.passiveSlave = passiveSlave; 2992 } 2993 2994 /** 2995 * override the Default IOException handler, called when persistence adapter 2996 * has experiences File or JDBC I/O Exceptions 2997 * 2998 * @param ioExceptionHandler 2999 */ 3000 public void setIoExceptionHandler(IOExceptionHandler ioExceptionHandler) { 3001 configureService(ioExceptionHandler); 3002 this.ioExceptionHandler = ioExceptionHandler; 3003 } 3004 3005 public IOExceptionHandler getIoExceptionHandler() { 3006 return ioExceptionHandler; 3007 } 3008 3009 /** 3010 * @return the schedulerSupport 3011 */ 3012 public boolean isSchedulerSupport() { 3013 return this.schedulerSupport; 3014 } 3015 3016 /** 3017 * @param schedulerSupport the schedulerSupport to set 3018 * @org.apache.xbean.Property propertyEditor="org.apache.activemq.util.BooleanEditor" 3019 */ 3020 public void setSchedulerSupport(boolean schedulerSupport) { 3021 this.schedulerSupport = schedulerSupport; 3022 } 3023 3024 /** 3025 * @return the schedulerDirectory 3026 */ 3027 public File getSchedulerDirectoryFile() { 3028 if (this.schedulerDirectoryFile == null) { 3029 this.schedulerDirectoryFile = new File(getBrokerDataDirectory(), "scheduler"); 3030 } 3031 return schedulerDirectoryFile; 3032 } 3033 3034 /** 3035 * @param schedulerDirectory the schedulerDirectory to set 3036 */ 3037 public void setSchedulerDirectoryFile(File schedulerDirectory) { 3038 this.schedulerDirectoryFile = schedulerDirectory; 3039 } 3040 3041 public void setSchedulerDirectory(String schedulerDirectory) { 3042 setSchedulerDirectoryFile(new File(schedulerDirectory)); 3043 } 3044 3045 public int getSchedulePeriodForDestinationPurge() { 3046 return this.schedulePeriodForDestinationPurge; 3047 } 3048 3049 public void setSchedulePeriodForDestinationPurge(int schedulePeriodForDestinationPurge) { 3050 this.schedulePeriodForDestinationPurge = schedulePeriodForDestinationPurge; 3051 } 3052 3053 /** 3054 * @param schedulePeriodForDiskUsageCheck 3055 */ 3056 public void setSchedulePeriodForDiskUsageCheck( 3057 int schedulePeriodForDiskUsageCheck) { 3058 this.schedulePeriodForDiskUsageCheck = schedulePeriodForDiskUsageCheck; 3059 } 3060 3061 public int getDiskUsageCheckRegrowThreshold() { 3062 return diskUsageCheckRegrowThreshold; 3063 } 3064 3065 /** 3066 * @param diskUsageCheckRegrowThreshold 3067 * @org.apache.xbean.Property propertyEditor="org.apache.activemq.util.MemoryPropertyEditor" 3068 */ 3069 public void setDiskUsageCheckRegrowThreshold(int diskUsageCheckRegrowThreshold) { 3070 this.diskUsageCheckRegrowThreshold = diskUsageCheckRegrowThreshold; 3071 } 3072 3073 public int getMaxPurgedDestinationsPerSweep() { 3074 return this.maxPurgedDestinationsPerSweep; 3075 } 3076 3077 public void setMaxPurgedDestinationsPerSweep(int maxPurgedDestinationsPerSweep) { 3078 this.maxPurgedDestinationsPerSweep = maxPurgedDestinationsPerSweep; 3079 } 3080 3081 public BrokerContext getBrokerContext() { 3082 return brokerContext; 3083 } 3084 3085 public void setBrokerContext(BrokerContext brokerContext) { 3086 this.brokerContext = brokerContext; 3087 } 3088 3089 public void setBrokerId(String brokerId) { 3090 this.brokerId = new BrokerId(brokerId); 3091 } 3092 3093 public boolean isUseAuthenticatedPrincipalForJMSXUserID() { 3094 return useAuthenticatedPrincipalForJMSXUserID; 3095 } 3096 3097 public void setUseAuthenticatedPrincipalForJMSXUserID(boolean useAuthenticatedPrincipalForJMSXUserID) { 3098 this.useAuthenticatedPrincipalForJMSXUserID = useAuthenticatedPrincipalForJMSXUserID; 3099 } 3100 3101 /** 3102 * Should MBeans that support showing the Authenticated User Name information have this 3103 * value filled in or not. 3104 * 3105 * @return true if user names should be exposed in MBeans 3106 */ 3107 public boolean isPopulateUserNameInMBeans() { 3108 return this.populateUserNameInMBeans; 3109 } 3110 3111 /** 3112 * Sets whether Authenticated User Name information is shown in MBeans that support this field. 3113 * @param value if MBeans should expose user name information. 3114 */ 3115 public void setPopulateUserNameInMBeans(boolean value) { 3116 this.populateUserNameInMBeans = value; 3117 } 3118 3119 /** 3120 * Gets the time in Milliseconds that an invocation of an MBean method will wait before 3121 * failing. The default value is to wait forever (zero). 3122 * 3123 * @return timeout in milliseconds before MBean calls fail, (default is 0 or no timeout). 3124 */ 3125 public long getMbeanInvocationTimeout() { 3126 return mbeanInvocationTimeout; 3127 } 3128 3129 /** 3130 * Gets the time in Milliseconds that an invocation of an MBean method will wait before 3131 * failing. The default value is to wait forever (zero). 3132 * 3133 * @param mbeanInvocationTimeout 3134 * timeout in milliseconds before MBean calls fail, (default is 0 or no timeout). 3135 */ 3136 public void setMbeanInvocationTimeout(long mbeanInvocationTimeout) { 3137 this.mbeanInvocationTimeout = mbeanInvocationTimeout; 3138 } 3139 3140 public boolean isNetworkConnectorStartAsync() { 3141 return networkConnectorStartAsync; 3142 } 3143 3144 public void setNetworkConnectorStartAsync(boolean networkConnectorStartAsync) { 3145 this.networkConnectorStartAsync = networkConnectorStartAsync; 3146 } 3147 3148 public boolean isAllowTempAutoCreationOnSend() { 3149 return allowTempAutoCreationOnSend; 3150 } 3151 3152 /** 3153 * enable if temp destinations need to be propagated through a network when 3154 * advisorySupport==false. This is used in conjunction with the policy 3155 * gcInactiveDestinations for matching temps so they can get removed 3156 * when inactive 3157 * 3158 * @param allowTempAutoCreationOnSend 3159 */ 3160 public void setAllowTempAutoCreationOnSend(boolean allowTempAutoCreationOnSend) { 3161 this.allowTempAutoCreationOnSend = allowTempAutoCreationOnSend; 3162 } 3163 3164 public long getOfflineDurableSubscriberTimeout() { 3165 return offlineDurableSubscriberTimeout; 3166 } 3167 3168 public void setOfflineDurableSubscriberTimeout(long offlineDurableSubscriberTimeout) { 3169 this.offlineDurableSubscriberTimeout = offlineDurableSubscriberTimeout; 3170 } 3171 3172 public long getOfflineDurableSubscriberTaskSchedule() { 3173 return offlineDurableSubscriberTaskSchedule; 3174 } 3175 3176 public void setOfflineDurableSubscriberTaskSchedule(long offlineDurableSubscriberTaskSchedule) { 3177 this.offlineDurableSubscriberTaskSchedule = offlineDurableSubscriberTaskSchedule; 3178 } 3179 3180 public boolean shouldRecordVirtualDestination(ActiveMQDestination destination) { 3181 return isUseVirtualTopics() && destination.isQueue() && 3182 getVirtualTopicConsumerDestinationFilter().matches(destination); 3183 } 3184 3185 synchronized public Throwable getStartException() { 3186 return startException; 3187 } 3188 3189 public boolean isStartAsync() { 3190 return startAsync; 3191 } 3192 3193 public void setStartAsync(boolean startAsync) { 3194 this.startAsync = startAsync; 3195 } 3196 3197 public boolean isSlave() { 3198 return this.slave; 3199 } 3200 3201 public boolean isStopping() { 3202 return this.stopping.get(); 3203 } 3204 3205 /** 3206 * @return true if the broker allowed to restart on shutdown. 3207 */ 3208 public boolean isRestartAllowed() { 3209 return restartAllowed; 3210 } 3211 3212 /** 3213 * Sets if the broker allowed to restart on shutdown. 3214 */ 3215 public void setRestartAllowed(boolean restartAllowed) { 3216 this.restartAllowed = restartAllowed; 3217 } 3218 3219 /** 3220 * A lifecycle manager of the BrokerService should 3221 * inspect this property after a broker shutdown has occurred 3222 * to find out if the broker needs to be re-created and started 3223 * again. 3224 * 3225 * @return true if the broker wants to be restarted after it shuts down. 3226 */ 3227 public boolean isRestartRequested() { 3228 return restartRequested; 3229 } 3230 3231 public void requestRestart() { 3232 this.restartRequested = true; 3233 } 3234 3235 public int getStoreOpenWireVersion() { 3236 return storeOpenWireVersion; 3237 } 3238 3239 public void setStoreOpenWireVersion(int storeOpenWireVersion) { 3240 this.storeOpenWireVersion = storeOpenWireVersion; 3241 } 3242 3243 /** 3244 * @return the current number of connections on this Broker. 3245 */ 3246 public int getCurrentConnections() { 3247 return this.currentConnections.get(); 3248 } 3249 3250 /** 3251 * @return the total number of connections this broker has handled since startup. 3252 */ 3253 public long getTotalConnections() { 3254 return this.totalConnections.get(); 3255 } 3256 3257 public void incrementCurrentConnections() { 3258 this.currentConnections.incrementAndGet(); 3259 } 3260 3261 public void decrementCurrentConnections() { 3262 this.currentConnections.decrementAndGet(); 3263 } 3264 3265 public void incrementTotalConnections() { 3266 this.totalConnections.incrementAndGet(); 3267 } 3268 3269 public boolean isRejectDurableConsumers() { 3270 return rejectDurableConsumers; 3271 } 3272 3273 public void setRejectDurableConsumers(boolean rejectDurableConsumers) { 3274 this.rejectDurableConsumers = rejectDurableConsumers; 3275 } 3276 3277 public boolean isUseVirtualDestSubs() { 3278 return useVirtualDestSubs; 3279 } 3280 3281 public void setUseVirtualDestSubs( 3282 boolean useVirtualDestSubs) { 3283 this.useVirtualDestSubs = useVirtualDestSubs; 3284 } 3285 3286 public boolean isUseVirtualDestSubsOnCreation() { 3287 return useVirtualDestSubsOnCreation; 3288 } 3289 3290 public void setUseVirtualDestSubsOnCreation( 3291 boolean useVirtualDestSubsOnCreation) { 3292 this.useVirtualDestSubsOnCreation = useVirtualDestSubsOnCreation; 3293 } 3294 3295 public boolean isAdjustUsageLimits() { 3296 return adjustUsageLimits; 3297 } 3298 3299 public void setAdjustUsageLimits(boolean adjustUsageLimits) { 3300 this.adjustUsageLimits = adjustUsageLimits; 3301 } 3302 3303 public void setRollbackOnlyOnAsyncException(boolean rollbackOnlyOnAsyncException) { 3304 this.rollbackOnlyOnAsyncException = rollbackOnlyOnAsyncException; 3305 } 3306 3307 public boolean isRollbackOnlyOnAsyncException() { 3308 return rollbackOnlyOnAsyncException; 3309 } 3310 3311 public int getMaxSchedulerRepeatAllowed() { 3312 return maxSchedulerRepeatAllowed; 3313 } 3314 3315 public void setMaxSchedulerRepeatAllowed(int maxSchedulerRepeatAllowed) { 3316 this.maxSchedulerRepeatAllowed = maxSchedulerRepeatAllowed; 3317 } 3318}