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.advisory; 018 019import java.util.ArrayList; 020import java.util.Collection; 021import java.util.Iterator; 022import java.util.LinkedHashMap; 023import java.util.Map; 024import java.util.Set; 025import java.util.concurrent.ConcurrentHashMap; 026import java.util.concurrent.ConcurrentMap; 027import java.util.concurrent.locks.ReentrantReadWriteLock; 028 029import org.apache.activemq.broker.Broker; 030import org.apache.activemq.broker.BrokerFilter; 031import org.apache.activemq.broker.BrokerService; 032import org.apache.activemq.broker.ConnectionContext; 033import org.apache.activemq.broker.ProducerBrokerExchange; 034import org.apache.activemq.broker.TransportConnector; 035import org.apache.activemq.broker.region.BaseDestination; 036import org.apache.activemq.broker.region.Destination; 037import org.apache.activemq.broker.region.DurableTopicSubscription; 038import org.apache.activemq.broker.region.MessageReference; 039import org.apache.activemq.broker.region.RegionBroker; 040import org.apache.activemq.broker.region.Subscription; 041import org.apache.activemq.broker.region.TopicRegion; 042import org.apache.activemq.broker.region.TopicSubscription; 043import org.apache.activemq.command.ActiveMQDestination; 044import org.apache.activemq.command.ActiveMQMessage; 045import org.apache.activemq.command.ActiveMQTopic; 046import org.apache.activemq.command.BrokerInfo; 047import org.apache.activemq.command.Command; 048import org.apache.activemq.command.ConnectionId; 049import org.apache.activemq.command.ConnectionInfo; 050import org.apache.activemq.command.ConsumerId; 051import org.apache.activemq.command.ConsumerInfo; 052import org.apache.activemq.command.DestinationInfo; 053import org.apache.activemq.command.Message; 054import org.apache.activemq.command.MessageId; 055import org.apache.activemq.command.ProducerId; 056import org.apache.activemq.command.ProducerInfo; 057import org.apache.activemq.command.RemoveSubscriptionInfo; 058import org.apache.activemq.security.SecurityContext; 059import org.apache.activemq.state.ProducerState; 060import org.apache.activemq.usage.Usage; 061import org.apache.activemq.util.IdGenerator; 062import org.apache.activemq.util.LongSequenceGenerator; 063import org.apache.activemq.util.SubscriptionKey; 064import org.slf4j.Logger; 065import org.slf4j.LoggerFactory; 066 067/** 068 * This broker filter handles tracking the state of the broker for purposes of 069 * publishing advisory messages to advisory consumers. 070 */ 071public class AdvisoryBroker extends BrokerFilter { 072 073 private static final Logger LOG = LoggerFactory.getLogger(AdvisoryBroker.class); 074 private static final IdGenerator ID_GENERATOR = new IdGenerator(); 075 076 protected final ConcurrentMap<ConnectionId, ConnectionInfo> connections = new ConcurrentHashMap<ConnectionId, ConnectionInfo>(); 077 078 private final ReentrantReadWriteLock consumersLock = new ReentrantReadWriteLock(); 079 protected final Map<ConsumerId, ConsumerInfo> consumers = new LinkedHashMap<ConsumerId, ConsumerInfo>(); 080 081 protected final ConcurrentMap<ProducerId, ProducerInfo> producers = new ConcurrentHashMap<ProducerId, ProducerInfo>(); 082 protected final ConcurrentMap<ActiveMQDestination, DestinationInfo> destinations = new ConcurrentHashMap<ActiveMQDestination, DestinationInfo>(); 083 protected final ConcurrentMap<BrokerInfo, ActiveMQMessage> networkBridges = new ConcurrentHashMap<BrokerInfo, ActiveMQMessage>(); 084 protected final ProducerId advisoryProducerId = new ProducerId(); 085 086 private final LongSequenceGenerator messageIdGenerator = new LongSequenceGenerator(); 087 088 public AdvisoryBroker(Broker next) { 089 super(next); 090 advisoryProducerId.setConnectionId(ID_GENERATOR.generateId()); 091 } 092 093 @Override 094 public void addConnection(ConnectionContext context, ConnectionInfo info) throws Exception { 095 super.addConnection(context, info); 096 097 ActiveMQTopic topic = AdvisorySupport.getConnectionAdvisoryTopic(); 098 // do not distribute passwords in advisory messages. usernames okay 099 ConnectionInfo copy = info.copy(); 100 copy.setPassword(""); 101 fireAdvisory(context, topic, copy); 102 connections.put(copy.getConnectionId(), copy); 103 } 104 105 @Override 106 public Subscription addConsumer(ConnectionContext context, ConsumerInfo info) throws Exception { 107 Subscription answer = super.addConsumer(context, info); 108 109 // Don't advise advisory topics. 110 if (!AdvisorySupport.isAdvisoryTopic(info.getDestination())) { 111 ActiveMQTopic topic = AdvisorySupport.getConsumerAdvisoryTopic(info.getDestination()); 112 consumersLock.writeLock().lock(); 113 try { 114 consumers.put(info.getConsumerId(), info); 115 } finally { 116 consumersLock.writeLock().unlock(); 117 } 118 fireConsumerAdvisory(context, info.getDestination(), topic, info); 119 } else { 120 // We need to replay all the previously collected state objects 121 // for this newly added consumer. 122 if (AdvisorySupport.isConnectionAdvisoryTopic(info.getDestination())) { 123 // Replay the connections. 124 for (Iterator<ConnectionInfo> iter = connections.values().iterator(); iter.hasNext(); ) { 125 ConnectionInfo value = iter.next(); 126 ActiveMQTopic topic = AdvisorySupport.getConnectionAdvisoryTopic(); 127 fireAdvisory(context, topic, value, info.getConsumerId()); 128 } 129 } 130 131 // We check here whether the Destination is Temporary Destination specific or not since we 132 // can avoid sending advisory messages to the consumer if it only wants Temporary Destination 133 // notifications. If its not just temporary destination related destinations then we have 134 // to send them all, a composite destination could want both. 135 if (AdvisorySupport.isTempDestinationAdvisoryTopic(info.getDestination())) { 136 // Replay the temporary destinations. 137 for (DestinationInfo destination : destinations.values()) { 138 if (destination.getDestination().isTemporary()) { 139 ActiveMQTopic topic = AdvisorySupport.getDestinationAdvisoryTopic(destination.getDestination()); 140 fireAdvisory(context, topic, destination, info.getConsumerId()); 141 } 142 } 143 } else if (AdvisorySupport.isDestinationAdvisoryTopic(info.getDestination())) { 144 // Replay all the destinations. 145 for (DestinationInfo destination : destinations.values()) { 146 ActiveMQTopic topic = AdvisorySupport.getDestinationAdvisoryTopic(destination.getDestination()); 147 fireAdvisory(context, topic, destination, info.getConsumerId()); 148 } 149 } 150 151 // Replay the producers. 152 if (AdvisorySupport.isProducerAdvisoryTopic(info.getDestination())) { 153 for (Iterator<ProducerInfo> iter = producers.values().iterator(); iter.hasNext(); ) { 154 ProducerInfo value = iter.next(); 155 ActiveMQTopic topic = AdvisorySupport.getProducerAdvisoryTopic(value.getDestination()); 156 fireProducerAdvisory(context, value.getDestination(), topic, value, info.getConsumerId()); 157 } 158 } 159 160 // Replay the consumers. 161 if (AdvisorySupport.isConsumerAdvisoryTopic(info.getDestination())) { 162 consumersLock.readLock().lock(); 163 try { 164 for (Iterator<ConsumerInfo> iter = consumers.values().iterator(); iter.hasNext(); ) { 165 ConsumerInfo value = iter.next(); 166 ActiveMQTopic topic = AdvisorySupport.getConsumerAdvisoryTopic(value.getDestination()); 167 fireConsumerAdvisory(context, value.getDestination(), topic, value, info.getConsumerId()); 168 } 169 } finally { 170 consumersLock.readLock().unlock(); 171 } 172 } 173 174 // Replay network bridges 175 if (AdvisorySupport.isNetworkBridgeAdvisoryTopic(info.getDestination())) { 176 for (Iterator<BrokerInfo> iter = networkBridges.keySet().iterator(); iter.hasNext(); ) { 177 BrokerInfo key = iter.next(); 178 ActiveMQTopic topic = AdvisorySupport.getNetworkBridgeAdvisoryTopic(); 179 fireAdvisory(context, topic, key, null, networkBridges.get(key)); 180 } 181 } 182 } 183 return answer; 184 } 185 186 @Override 187 public void addProducer(ConnectionContext context, ProducerInfo info) throws Exception { 188 super.addProducer(context, info); 189 190 // Don't advise advisory topics. 191 if (info.getDestination() != null && !AdvisorySupport.isAdvisoryTopic(info.getDestination())) { 192 ActiveMQTopic topic = AdvisorySupport.getProducerAdvisoryTopic(info.getDestination()); 193 fireProducerAdvisory(context, info.getDestination(), topic, info); 194 producers.put(info.getProducerId(), info); 195 } 196 } 197 198 @Override 199 public Destination addDestination(ConnectionContext context, ActiveMQDestination destination, boolean create) throws Exception { 200 Destination answer = super.addDestination(context, destination, create); 201 if (!AdvisorySupport.isAdvisoryTopic(destination)) { 202 DestinationInfo info = new DestinationInfo(context.getConnectionId(), DestinationInfo.ADD_OPERATION_TYPE, destination); 203 DestinationInfo previous = destinations.putIfAbsent(destination, info); 204 if (previous == null) { 205 ActiveMQTopic topic = AdvisorySupport.getDestinationAdvisoryTopic(destination); 206 fireAdvisory(context, topic, info); 207 } 208 } 209 return answer; 210 } 211 212 @Override 213 public void addDestinationInfo(ConnectionContext context, DestinationInfo info) throws Exception { 214 ActiveMQDestination destination = info.getDestination(); 215 next.addDestinationInfo(context, info); 216 217 if (!AdvisorySupport.isAdvisoryTopic(destination)) { 218 DestinationInfo previous = destinations.putIfAbsent(destination, info); 219 if (previous == null) { 220 ActiveMQTopic topic = AdvisorySupport.getDestinationAdvisoryTopic(destination); 221 fireAdvisory(context, topic, info); 222 } 223 } 224 } 225 226 @Override 227 public void removeDestination(ConnectionContext context, ActiveMQDestination destination, long timeout) throws Exception { 228 super.removeDestination(context, destination, timeout); 229 DestinationInfo info = destinations.remove(destination); 230 if (info != null) { 231 // ensure we don't modify (and loose/overwrite) an in-flight add advisory, so duplicate 232 info = info.copy(); 233 info.setDestination(destination); 234 info.setOperationType(DestinationInfo.REMOVE_OPERATION_TYPE); 235 ActiveMQTopic topic = AdvisorySupport.getDestinationAdvisoryTopic(destination); 236 fireAdvisory(context, topic, info); 237 ActiveMQTopic[] advisoryDestinations = AdvisorySupport.getAllDestinationAdvisoryTopics(destination); 238 for (ActiveMQTopic advisoryDestination : advisoryDestinations) { 239 try { 240 next.removeDestination(context, advisoryDestination, -1); 241 } catch (Exception expectedIfDestinationDidNotExistYet) { 242 } 243 } 244 } 245 } 246 247 @Override 248 public void removeDestinationInfo(ConnectionContext context, DestinationInfo destInfo) throws Exception { 249 super.removeDestinationInfo(context, destInfo); 250 DestinationInfo info = destinations.remove(destInfo.getDestination()); 251 if (info != null) { 252 // ensure we don't modify (and loose/overwrite) an in-flight add advisory, so duplicate 253 info = info.copy(); 254 info.setDestination(destInfo.getDestination()); 255 info.setOperationType(DestinationInfo.REMOVE_OPERATION_TYPE); 256 ActiveMQTopic topic = AdvisorySupport.getDestinationAdvisoryTopic(destInfo.getDestination()); 257 fireAdvisory(context, topic, info); 258 ActiveMQTopic[] advisoryDestinations = AdvisorySupport.getAllDestinationAdvisoryTopics(destInfo.getDestination()); 259 for (ActiveMQTopic advisoryDestination : advisoryDestinations) { 260 try { 261 next.removeDestination(context, advisoryDestination, -1); 262 } catch (Exception expectedIfDestinationDidNotExistYet) { 263 } 264 } 265 } 266 } 267 268 @Override 269 public void removeConnection(ConnectionContext context, ConnectionInfo info, Throwable error) throws Exception { 270 super.removeConnection(context, info, error); 271 272 ActiveMQTopic topic = AdvisorySupport.getConnectionAdvisoryTopic(); 273 fireAdvisory(context, topic, info.createRemoveCommand()); 274 connections.remove(info.getConnectionId()); 275 } 276 277 @Override 278 public void removeConsumer(ConnectionContext context, ConsumerInfo info) throws Exception { 279 super.removeConsumer(context, info); 280 281 // Don't advise advisory topics. 282 ActiveMQDestination dest = info.getDestination(); 283 if (!AdvisorySupport.isAdvisoryTopic(dest)) { 284 ActiveMQTopic topic = AdvisorySupport.getConsumerAdvisoryTopic(dest); 285 consumersLock.writeLock().lock(); 286 try { 287 consumers.remove(info.getConsumerId()); 288 } finally { 289 consumersLock.writeLock().unlock(); 290 } 291 if (!dest.isTemporary() || destinations.containsKey(dest)) { 292 fireConsumerAdvisory(context, dest, topic, info.createRemoveCommand()); 293 } 294 } 295 } 296 297 @Override 298 public void removeSubscription(ConnectionContext context, RemoveSubscriptionInfo info) throws Exception { 299 SubscriptionKey key = new SubscriptionKey(context.getClientId(), info.getSubscriptionName()); 300 301 RegionBroker regionBroker = null; 302 if (next instanceof RegionBroker) { 303 regionBroker = (RegionBroker) next; 304 } else { 305 BrokerService service = next.getBrokerService(); 306 regionBroker = (RegionBroker) service.getRegionBroker(); 307 } 308 309 if (regionBroker == null) { 310 LOG.warn("Cannot locate a RegionBroker instance to pass along the removeSubscription call"); 311 throw new IllegalStateException("No RegionBroker found."); 312 } 313 314 DurableTopicSubscription sub = ((TopicRegion) regionBroker.getTopicRegion()).getDurableSubscription(key); 315 316 super.removeSubscription(context, info); 317 318 if (sub == null) { 319 LOG.warn("We cannot send an advisory message for a durable sub removal when we don't know about the durable sub"); 320 return; 321 } 322 323 ActiveMQDestination dest = sub.getConsumerInfo().getDestination(); 324 325 // Don't advise advisory topics. 326 if (!AdvisorySupport.isAdvisoryTopic(dest)) { 327 ActiveMQTopic topic = AdvisorySupport.getConsumerAdvisoryTopic(dest); 328 fireConsumerAdvisory(context, dest, topic, info); 329 } 330 331 } 332 333 @Override 334 public void removeProducer(ConnectionContext context, ProducerInfo info) throws Exception { 335 super.removeProducer(context, info); 336 337 // Don't advise advisory topics. 338 ActiveMQDestination dest = info.getDestination(); 339 if (info.getDestination() != null && !AdvisorySupport.isAdvisoryTopic(dest)) { 340 ActiveMQTopic topic = AdvisorySupport.getProducerAdvisoryTopic(dest); 341 producers.remove(info.getProducerId()); 342 if (!dest.isTemporary() || destinations.containsKey(dest)) { 343 fireProducerAdvisory(context, dest, topic, info.createRemoveCommand()); 344 } 345 } 346 } 347 348 @Override 349 public void messageExpired(ConnectionContext context, MessageReference messageReference, Subscription subscription) { 350 super.messageExpired(context, messageReference, subscription); 351 try { 352 if (!messageReference.isAdvisory()) { 353 ActiveMQTopic topic = AdvisorySupport.getExpiredMessageTopic(messageReference.getMessage().getDestination()); 354 Message payload = messageReference.getMessage().copy(); 355 if (!isIncludeBodyForAdvisory(messageReference.getMessage().getDestination())) { 356 payload.clearBody(); 357 } 358 ActiveMQMessage advisoryMessage = new ActiveMQMessage(); 359 advisoryMessage.setStringProperty(AdvisorySupport.MSG_PROPERTY_MESSAGE_ID, payload.getMessageId().toString()); 360 fireAdvisory(context, topic, payload, null, advisoryMessage); 361 } 362 } catch (Exception e) { 363 handleFireFailure("expired", e); 364 } 365 } 366 367 @Override 368 public void messageConsumed(ConnectionContext context, MessageReference messageReference) { 369 super.messageConsumed(context, messageReference); 370 try { 371 if (!messageReference.isAdvisory()) { 372 ActiveMQTopic topic = AdvisorySupport.getMessageConsumedAdvisoryTopic(messageReference.getMessage().getDestination()); 373 Message payload = messageReference.getMessage().copy(); 374 if (!isIncludeBodyForAdvisory(messageReference.getMessage().getDestination())) { 375 payload.clearBody(); 376 } 377 ActiveMQMessage advisoryMessage = new ActiveMQMessage(); 378 advisoryMessage.setStringProperty(AdvisorySupport.MSG_PROPERTY_MESSAGE_ID, payload.getMessageId().toString()); 379 ActiveMQDestination destination = payload.getDestination(); 380 if (destination != null) { 381 advisoryMessage.setStringProperty(AdvisorySupport.MSG_PROPERTY_DESTINATION, destination.getQualifiedName()); 382 } 383 fireAdvisory(context, topic, payload, null, advisoryMessage); 384 } 385 } catch (Exception e) { 386 handleFireFailure("consumed", e); 387 } 388 } 389 390 @Override 391 public void messageDelivered(ConnectionContext context, MessageReference messageReference) { 392 super.messageDelivered(context, messageReference); 393 try { 394 if (!messageReference.isAdvisory()) { 395 ActiveMQTopic topic = AdvisorySupport.getMessageDeliveredAdvisoryTopic(messageReference.getMessage().getDestination()); 396 Message payload = messageReference.getMessage().copy(); 397 if (!isIncludeBodyForAdvisory(messageReference.getMessage().getDestination())) { 398 payload.clearBody(); 399 } 400 ActiveMQMessage advisoryMessage = new ActiveMQMessage(); 401 advisoryMessage.setStringProperty(AdvisorySupport.MSG_PROPERTY_MESSAGE_ID, payload.getMessageId().toString()); 402 ActiveMQDestination destination = payload.getDestination(); 403 if (destination != null) { 404 advisoryMessage.setStringProperty(AdvisorySupport.MSG_PROPERTY_DESTINATION, destination.getQualifiedName()); 405 } 406 fireAdvisory(context, topic, payload, null, advisoryMessage); 407 } 408 } catch (Exception e) { 409 handleFireFailure("delivered", e); 410 } 411 } 412 413 @Override 414 public void messageDiscarded(ConnectionContext context, Subscription sub, MessageReference messageReference) { 415 super.messageDiscarded(context, sub, messageReference); 416 try { 417 if (!messageReference.isAdvisory()) { 418 ActiveMQTopic topic = AdvisorySupport.getMessageDiscardedAdvisoryTopic(messageReference.getMessage().getDestination()); 419 Message payload = messageReference.getMessage().copy(); 420 if (!isIncludeBodyForAdvisory(messageReference.getMessage().getDestination())) { 421 payload.clearBody(); 422 } 423 ActiveMQMessage advisoryMessage = new ActiveMQMessage(); 424 if (sub instanceof TopicSubscription) { 425 advisoryMessage.setIntProperty(AdvisorySupport.MSG_PROPERTY_DISCARDED_COUNT, ((TopicSubscription) sub).discarded()); 426 } 427 advisoryMessage.setStringProperty(AdvisorySupport.MSG_PROPERTY_MESSAGE_ID, payload.getMessageId().toString()); 428 advisoryMessage.setStringProperty(AdvisorySupport.MSG_PROPERTY_CONSUMER_ID, sub.getConsumerInfo().getConsumerId().toString()); 429 ActiveMQDestination destination = payload.getDestination(); 430 if (destination != null) { 431 advisoryMessage.setStringProperty(AdvisorySupport.MSG_PROPERTY_DESTINATION, destination.getQualifiedName()); 432 } 433 fireAdvisory(context, topic, payload, null, advisoryMessage); 434 } 435 } catch (Exception e) { 436 handleFireFailure("discarded", e); 437 } 438 } 439 440 @Override 441 public void slowConsumer(ConnectionContext context, Destination destination, Subscription subs) { 442 super.slowConsumer(context, destination, subs); 443 try { 444 if (!AdvisorySupport.isAdvisoryTopic(destination.getActiveMQDestination())) { 445 ActiveMQTopic topic = AdvisorySupport.getSlowConsumerAdvisoryTopic(destination.getActiveMQDestination()); 446 ActiveMQMessage advisoryMessage = new ActiveMQMessage(); 447 advisoryMessage.setStringProperty(AdvisorySupport.MSG_PROPERTY_CONSUMER_ID, subs.getConsumerInfo().getConsumerId().toString()); 448 fireAdvisory(context, topic, subs.getConsumerInfo(), null, advisoryMessage); 449 } 450 } catch (Exception e) { 451 handleFireFailure("slow consumer", e); 452 } 453 } 454 455 @Override 456 public void fastProducer(ConnectionContext context, ProducerInfo producerInfo, ActiveMQDestination destination) { 457 super.fastProducer(context, producerInfo, destination); 458 try { 459 if (!AdvisorySupport.isAdvisoryTopic(destination)) { 460 ActiveMQTopic topic = AdvisorySupport.getFastProducerAdvisoryTopic(destination); 461 ActiveMQMessage advisoryMessage = new ActiveMQMessage(); 462 advisoryMessage.setStringProperty(AdvisorySupport.MSG_PROPERTY_PRODUCER_ID, producerInfo.getProducerId().toString()); 463 fireAdvisory(context, topic, producerInfo, null, advisoryMessage); 464 } 465 } catch (Exception e) { 466 handleFireFailure("fast producer", e); 467 } 468 } 469 470 @Override 471 public void isFull(ConnectionContext context, Destination destination, Usage usage) { 472 super.isFull(context, destination, usage); 473 if (AdvisorySupport.isAdvisoryTopic(destination.getActiveMQDestination()) == false) { 474 try { 475 476 ActiveMQTopic topic = AdvisorySupport.getFullAdvisoryTopic(destination.getActiveMQDestination()); 477 ActiveMQMessage advisoryMessage = new ActiveMQMessage(); 478 advisoryMessage.setStringProperty(AdvisorySupport.MSG_PROPERTY_USAGE_NAME, usage.getName()); 479 fireAdvisory(context, topic, null, null, advisoryMessage); 480 481 } catch (Exception e) { 482 handleFireFailure("is full", e); 483 } 484 } 485 } 486 487 @Override 488 public void nowMasterBroker() { 489 super.nowMasterBroker(); 490 try { 491 ActiveMQTopic topic = AdvisorySupport.getMasterBrokerAdvisoryTopic(); 492 ActiveMQMessage advisoryMessage = new ActiveMQMessage(); 493 ConnectionContext context = new ConnectionContext(); 494 context.setSecurityContext(SecurityContext.BROKER_SECURITY_CONTEXT); 495 context.setBroker(getBrokerService().getBroker()); 496 fireAdvisory(context, topic, null, null, advisoryMessage); 497 } catch (Exception e) { 498 handleFireFailure("now master broker", e); 499 } 500 } 501 502 @Override 503 public boolean sendToDeadLetterQueue(ConnectionContext context, MessageReference messageReference, 504 Subscription subscription, Throwable poisonCause) { 505 boolean wasDLQd = super.sendToDeadLetterQueue(context, messageReference, subscription, poisonCause); 506 if (wasDLQd) { 507 try { 508 if (!messageReference.isAdvisory()) { 509 ActiveMQTopic topic = AdvisorySupport.getMessageDLQdAdvisoryTopic(messageReference.getMessage().getDestination()); 510 Message payload = messageReference.getMessage().copy(); 511 if (!isIncludeBodyForAdvisory(messageReference.getMessage().getDestination())) { 512 payload.clearBody(); 513 } 514 fireAdvisory(context, topic, payload); 515 } 516 } catch (Exception e) { 517 handleFireFailure("add to DLQ", e); 518 } 519 } 520 521 return wasDLQd; 522 } 523 524 @Override 525 public void networkBridgeStarted(BrokerInfo brokerInfo, boolean createdByDuplex, String remoteIp) { 526 try { 527 if (brokerInfo != null) { 528 ActiveMQMessage advisoryMessage = new ActiveMQMessage(); 529 advisoryMessage.setBooleanProperty("started", true); 530 advisoryMessage.setBooleanProperty("createdByDuplex", createdByDuplex); 531 advisoryMessage.setStringProperty("remoteIp", remoteIp); 532 networkBridges.putIfAbsent(brokerInfo, advisoryMessage); 533 534 ActiveMQTopic topic = AdvisorySupport.getNetworkBridgeAdvisoryTopic(); 535 536 ConnectionContext context = new ConnectionContext(); 537 context.setSecurityContext(SecurityContext.BROKER_SECURITY_CONTEXT); 538 context.setBroker(getBrokerService().getBroker()); 539 fireAdvisory(context, topic, brokerInfo, null, advisoryMessage); 540 } 541 } catch (Exception e) { 542 handleFireFailure("network bridge started", e); 543 } 544 } 545 546 @Override 547 public void networkBridgeStopped(BrokerInfo brokerInfo) { 548 try { 549 if (brokerInfo != null) { 550 ActiveMQMessage advisoryMessage = new ActiveMQMessage(); 551 advisoryMessage.setBooleanProperty("started", false); 552 networkBridges.remove(brokerInfo); 553 554 ActiveMQTopic topic = AdvisorySupport.getNetworkBridgeAdvisoryTopic(); 555 556 ConnectionContext context = new ConnectionContext(); 557 context.setSecurityContext(SecurityContext.BROKER_SECURITY_CONTEXT); 558 context.setBroker(getBrokerService().getBroker()); 559 fireAdvisory(context, topic, brokerInfo, null, advisoryMessage); 560 } 561 } catch (Exception e) { 562 handleFireFailure("network bridge stopped", e); 563 } 564 } 565 566 protected boolean isIncludeBodyForAdvisory(ActiveMQDestination activemqDestination) { 567 Destination destination = next.getDestinationMap(activemqDestination).get(activemqDestination); 568 return (destination instanceof BaseDestination && 569 ((BaseDestination) destination).isIncludeBodyForAdvisory()) ? true : false; 570 } 571 572 private void handleFireFailure(String message, Throwable cause) { 573 LOG.warn("Failed to fire {} advisory, reason: {}", message, cause); 574 LOG.debug("{} detail: {}", message, cause); 575 } 576 577 protected void fireAdvisory(ConnectionContext context, ActiveMQTopic topic, Command command) throws Exception { 578 fireAdvisory(context, topic, command, null); 579 } 580 581 protected void fireAdvisory(ConnectionContext context, ActiveMQTopic topic, Command command, ConsumerId targetConsumerId) throws Exception { 582 ActiveMQMessage advisoryMessage = new ActiveMQMessage(); 583 fireAdvisory(context, topic, command, targetConsumerId, advisoryMessage); 584 } 585 586 protected void fireConsumerAdvisory(ConnectionContext context, ActiveMQDestination consumerDestination, ActiveMQTopic topic, Command command) throws Exception { 587 fireConsumerAdvisory(context, consumerDestination, topic, command, null); 588 } 589 590 protected void fireConsumerAdvisory(ConnectionContext context, ActiveMQDestination consumerDestination, ActiveMQTopic topic, Command command, ConsumerId targetConsumerId) throws Exception { 591 ActiveMQMessage advisoryMessage = new ActiveMQMessage(); 592 int count = 0; 593 Set<Destination> set = getDestinations(consumerDestination); 594 if (set != null) { 595 for (Destination dest : set) { 596 count += dest.getDestinationStatistics().getConsumers().getCount(); 597 } 598 } 599 advisoryMessage.setIntProperty(AdvisorySupport.MSG_PROPERTY_CONSUMER_COUNT, count); 600 601 fireAdvisory(context, topic, command, targetConsumerId, advisoryMessage); 602 } 603 604 protected void fireProducerAdvisory(ConnectionContext context, ActiveMQDestination producerDestination, ActiveMQTopic topic, Command command) throws Exception { 605 fireProducerAdvisory(context, producerDestination, topic, command, null); 606 } 607 608 protected void fireProducerAdvisory(ConnectionContext context, ActiveMQDestination producerDestination, ActiveMQTopic topic, Command command, ConsumerId targetConsumerId) throws Exception { 609 ActiveMQMessage advisoryMessage = new ActiveMQMessage(); 610 int count = 0; 611 if (producerDestination != null) { 612 Set<Destination> set = getDestinations(producerDestination); 613 if (set != null) { 614 for (Destination dest : set) { 615 count += dest.getDestinationStatistics().getProducers().getCount(); 616 } 617 } 618 } 619 advisoryMessage.setIntProperty("producerCount", count); 620 fireAdvisory(context, topic, command, targetConsumerId, advisoryMessage); 621 } 622 623 public void fireAdvisory(ConnectionContext context, ActiveMQTopic topic, Command command, ConsumerId targetConsumerId, ActiveMQMessage advisoryMessage) throws Exception { 624 if (getBrokerService().isStarted()) { 625 //set properties 626 advisoryMessage.setStringProperty(AdvisorySupport.MSG_PROPERTY_ORIGIN_BROKER_NAME, getBrokerName()); 627 String id = getBrokerId() != null ? getBrokerId().getValue() : "NOT_SET"; 628 advisoryMessage.setStringProperty(AdvisorySupport.MSG_PROPERTY_ORIGIN_BROKER_ID, id); 629 630 String url = getBrokerService().getVmConnectorURI().toString(); 631 //try and find the URL on the transport connector and use if it exists else 632 //try and find a default URL 633 if (context.getConnector() instanceof TransportConnector 634 && ((TransportConnector) context.getConnector()).getPublishableConnectString() != null) { 635 url = ((TransportConnector) context.getConnector()).getPublishableConnectString(); 636 } else if (getBrokerService().getDefaultSocketURIString() != null) { 637 url = getBrokerService().getDefaultSocketURIString(); 638 } 639 advisoryMessage.setStringProperty(AdvisorySupport.MSG_PROPERTY_ORIGIN_BROKER_URL, url); 640 641 //set the data structure 642 advisoryMessage.setDataStructure(command); 643 advisoryMessage.setPersistent(false); 644 advisoryMessage.setType(AdvisorySupport.ADIVSORY_MESSAGE_TYPE); 645 advisoryMessage.setMessageId(new MessageId(advisoryProducerId, messageIdGenerator.getNextSequenceId())); 646 advisoryMessage.setTargetConsumerId(targetConsumerId); 647 advisoryMessage.setDestination(topic); 648 advisoryMessage.setResponseRequired(false); 649 advisoryMessage.setProducerId(advisoryProducerId); 650 boolean originalFlowControl = context.isProducerFlowControl(); 651 final ProducerBrokerExchange producerExchange = new ProducerBrokerExchange(); 652 producerExchange.setConnectionContext(context); 653 producerExchange.setMutable(true); 654 producerExchange.setProducerState(new ProducerState(new ProducerInfo())); 655 try { 656 context.setProducerFlowControl(false); 657 next.send(producerExchange, advisoryMessage); 658 } finally { 659 context.setProducerFlowControl(originalFlowControl); 660 } 661 } 662 } 663 664 public Map<ConnectionId, ConnectionInfo> getAdvisoryConnections() { 665 return connections; 666 } 667 668 public Collection<ConsumerInfo> getAdvisoryConsumers() { 669 consumersLock.readLock().lock(); 670 try { 671 return new ArrayList<ConsumerInfo>(consumers.values()); 672 } finally { 673 consumersLock.readLock().unlock(); 674 } 675 } 676 677 public Map<ProducerId, ProducerInfo> getAdvisoryProducers() { 678 return producers; 679 } 680 681 public Map<ActiveMQDestination, DestinationInfo> getAdvisoryDestinations() { 682 return destinations; 683 } 684}