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