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