001package gu.simplemq.activemq;
002
003import java.net.URI;
004import java.util.Iterator;
005import java.util.Map;
006import java.util.Properties;
007import java.util.concurrent.ConcurrentMap;
008
009import javax.jms.Connection;
010
011import com.google.common.collect.Maps;
012
013import static org.apache.activemq.ActiveMQConnectionFactory.DEFAULT_BROKER_BIND_URL;
014import static com.google.common.base.Preconditions.checkNotNull;
015
016
017/**
018 * 延迟初始化的 {@link Connection}资源池(线程安全),使用方法:<br>
019 * 通过 {@link #getDefaultInstance()} 和getInstance(...)系列静态方法获取{@link ActivemqPoolLazy}实例<br>
020 * 通过{@link #apply()} 和 {@link #free()}方法实现{@link Connection}对象的申请和释放
021 * @author guyadong
022 *
023 */
024public class ActivemqPoolLazys implements ActivemqConstants{
025        /** {@link ActivemqPoolLazy }实例集合 */
026        static final ConcurrentMap<URI,ActivemqPoolLazy> POOLS = Maps.newConcurrentMap();
027        /** 
028         * redis缺省连接参数<br>
029         * 这里没有使用guava的ImmutableMap,因为HashMap允许Value为null, ImmutableMap不允许 
030         **/
031        static final Properties DEFAULT_PARAMETERS = new Properties(){
032                private static final long serialVersionUID = 1L;
033                {
034                        put(ACON_BROKER_URL, DEFAULT_BROKER_BIND_URL);
035                }
036        };
037        /** 默认连接池实例 */
038        private static volatile ActivemqPoolLazy defaultInstance;
039        
040        /**
041         * 返回默认实例,如果 {@link #defaultInstance}为null则创建默认实例
042         * @return
043         * @see #createDefaultInstance(Map)
044         */
045        public static ActivemqPoolLazy getDefaultInstance() {
046                return null == defaultInstance
047                                ? createDefaultInstance(null) 
048                                : defaultInstance;
049        }
050
051        /**
052         * 设置默认{@link ActivemqPoolLazy}实例<br>
053         * 仅当默认实例未初始化(为{@code null})且输入参数不为{@code null}时有效(返回{@code true})
054         * 如果默认实例已经初始化,则输出警告日志,返回{@code false}
055         * @param poolLazy 为{@code null}返回{@code false}
056         * @return  设置成功返回{@code true},否则返回{@code false}
057         */
058        public static boolean setDefaultInstance(ActivemqPoolLazy poolLazy) {
059                // double checking
060                if(null == defaultInstance){
061                        synchronized(ActivemqPoolLazys.class){
062                                if(null == defaultInstance && null != poolLazy){
063                                        defaultInstance = poolLazy;
064                                        return true;
065                                }
066                        }
067                }
068                logger.warn("INVALID INVOCATION,default instance was initialized already before this invocation");
069                return false;
070        }
071
072        /**
073         * 检测默认实例是否初始化
074         * @return 默认实例已经初始化则返回{@code true},否则返回false
075         */
076        public static boolean defaultInstanceInitialized(){
077                return defaultInstance != null;
078        }
079        /**
080         * 根据指定的连接参数创建默认实例,只能被调用一次(线程安全)
081         * @param props
082         * @return
083         */
084        public static final ActivemqPoolLazy createDefaultInstance(Properties props){
085                setDefaultInstance( getInstance(props));
086                return defaultInstance;
087        }
088        
089        static ActivemqPoolLazy createInstance(Properties props) {
090                return new ActivemqPoolLazy(props);
091        }
092        /**
093         * 查找在连接池对象集合中查找对应的匹配的对象,找不到就创建新实例
094         * @param props
095         * @return
096         */
097        public static synchronized ActivemqPoolLazy getInstance(Properties props) {
098                // 查找在连接池对象集合中查找对应的匹配的对象,找不到就创建新实例
099                URI location =  PropertiesHelper.AHELPER.getLocationlURI(props);
100                ActivemqPoolLazy found = POOLS.get(location);
101                return found == null ? createInstance(props) : found;
102        
103        }
104        
105        /**
106         * 根据uri查找在连接池对象集合中查找对应的匹配的对象,找不到就创建新实例
107         * @param uri
108         * @return
109         */
110        public static ActivemqPoolLazy getInstance(URI uri) {
111                Properties props = new Properties();
112                props.setProperty(ACON_BROKER_URL, checkNotNull(uri,"uri is null").toString());
113                return getInstance(props);
114        }
115        
116        public static  ActivemqPoolLazy getInstanceByURI(String uri) {
117                 return getInstance(URI.create(uri));
118        }
119        /**
120         * 关闭并删除所有资源池中的{@link ActivemqPoolLazy}实例
121         */
122        public synchronized static void closeAll(){
123                for(Iterator<ActivemqPoolLazy> itor = POOLS.values().iterator();itor.hasNext();){
124                        ActivemqPoolLazy p = itor.next();
125                        itor.remove();
126                        p.close();
127                }
128        }
129}