001package gu.simplemq.activemq; 002 003import java.util.HashMap; 004import java.util.Iterator; 005 006import javax.jms.Connection; 007import javax.jms.JMSException; 008import javax.jms.Message; 009import javax.jms.MessageConsumer; 010import javax.jms.MessageListener; 011import javax.jms.Session; 012 013import org.apache.activemq.advisory.AdvisorySupport; 014import org.apache.activemq.command.ActiveMQDestination; 015import org.apache.activemq.command.ActiveMQQueue; 016import org.apache.activemq.command.ActiveMQTopic; 017 018import com.google.common.cache.CacheBuilder; 019import com.google.common.cache.CacheLoader; 020import com.google.common.cache.LoadingCache; 021import com.google.common.collect.Maps; 022 023import gu.simplemq.IConsumerAdvisor; 024 025import static com.google.common.base.Preconditions.*; 026/** 027 * threadSafe 028 * @author guyadong 029 * 030 */ 031public class AdvisoryMessageManager implements AutoCloseable,IConsumerAdvisor,ActivemqConstants{ 032 private final HashMap<String, MessageConsumer> advisoryConsumers = Maps.newHashMap(); 033 private static final LoadingCache<ActivemqPoolLazy,AdvisoryMessageManager> CACHE = CacheBuilder.newBuilder().build(new CacheLoader<ActivemqPoolLazy, AdvisoryMessageManager>(){ 034 035 @Override 036 public AdvisoryMessageManager load(ActivemqPoolLazy key) throws Exception { 037 return new AdvisoryMessageManager(key); 038 }}); 039 private volatile Connection advisoryConnection; 040 private volatile Session advisorySession; 041 private final ActivemqPoolLazy poolLazy; 042 private AdvisoryMessageManager(ActivemqPoolLazy poolLazy) { 043 this.poolLazy = checkNotNull(poolLazy, "poolLazy is null"); 044 } 045 private void init() throws JMSException{ 046 if(advisoryConnection == null){ 047 advisoryConnection = this.poolLazy.borrow(); 048 advisoryConnection.start(); 049 advisorySession = advisoryConnection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE); 050 } 051 } 052 053 void addAdvisoryConsumerIfAbsent(ActiveMQDestination destination) throws JMSException { 054 String name = destination.getPhysicalName(); 055 synchronized (this) { 056 if(!advisoryConsumers.containsKey(name)){ 057 init(); 058 ActiveMQTopic advisoryTopic = AdvisorySupport.getConsumerAdvisoryTopic(destination); 059 MessageConsumer advisoryConsumer = advisorySession.createConsumer(advisoryTopic); 060 advisoryConsumer.setMessageListener(new AdvisoryListener()); 061 advisoryConsumers.put(name, advisoryConsumer); 062 } 063 } 064 } 065 @Override 066 public void addAdvisoryTopicIfAbsent(String name) { 067 try { 068 addAdvisoryConsumerIfAbsent(new ActiveMQTopic(name)); 069 } catch (JMSException e) { 070 throw new RuntimeException(e); 071 } 072 } 073 @Override 074 public void addAdvisoryQueueIfAbsent(String name) { 075 try { 076 addAdvisoryConsumerIfAbsent(new ActiveMQQueue(name)); 077 } catch (JMSException e) { 078 throw new RuntimeException(e); 079 } 080 } 081 /** 082 * 返回指定频道的 advisory message<br> 083 * @param channelName 084 * @return advisory message,没有收到消息返回{@code null} 085 * @throws JMSException 086 */ 087 Message advisoryMessageOf(String channelName) throws JMSException{ 088 synchronized (this) { 089 if(advisoryConsumers.containsKey(channelName)){ 090 MessageConsumer advisoryConsumer = advisoryConsumers.get(channelName); 091 AdvisoryListener advisoryListener = (AdvisoryListener) advisoryConsumer.getMessageListener(); 092 if(advisoryListener.message == null){ 093 synchronized (advisoryListener) { 094 try { 095 advisoryListener.wait(5000); 096 } catch (InterruptedException e) { 097 } 098 } 099 } 100 return advisoryListener.message; 101 } 102 return null; 103 } 104 } 105 @Override 106 public void close() { 107 synchronized (this) { 108 // 关闭所有 MessageConsumer 实例 109 for(Iterator<MessageConsumer> itor = advisoryConsumers.values().iterator();itor.hasNext();){ 110 try { 111 itor.next().close(); 112 } catch (JMSException e) { 113 e.printStackTrace(); 114 } 115 itor.remove(); 116 } 117 try { 118 if(null != advisorySession){ 119 advisorySession.close(); 120 advisorySession = null; 121 } 122 } catch (JMSException e) { 123 e.printStackTrace(); 124 } 125 if(null != advisoryConnection){ 126 this.poolLazy.release(advisoryConnection); 127 advisoryConnection = null; 128 } 129 } 130 } 131 132 @Override 133 public int consumerCountOf(String channelName) { 134 try { 135 Message message = advisoryMessageOf(channelName); 136 return message == null ? 0 : message.getIntProperty(PROP_CONSUMER_COUNT); 137 } catch (JMSException e) { 138 throw new RuntimeException(e); 139 } 140 } 141 142 public static AdvisoryMessageManager instanceOf(ActivemqPoolLazy pool){ 143 return CACHE.getUnchecked(pool); 144 } 145 /** 146 * 关闭并删除所有资源池中的{@link AdvisoryMessageManager}实例 147 */ 148 public synchronized static void closeAll(){ 149 for(Iterator<AdvisoryMessageManager> itor = CACHE.asMap().values().iterator();itor.hasNext();){ 150 AdvisoryMessageManager p = itor.next(); 151 itor.remove(); 152 p.close(); 153 } 154 } 155 private static class AdvisoryListener implements MessageListener{ 156 /** 最近一次收到的 advisory 消息 */ 157 private Message message ; 158 159 @Override 160 public void onMessage(Message message) { 161 this.message = message; 162 synchronized (this) { 163 this.notifyAll(); 164 } 165 } 166 } 167}