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