001    /** 
002     * 
003     * Copyright 2004 Protique Ltd
004     * 
005     * Licensed under the Apache License, Version 2.0 (the "License"); 
006     * you may not use this file except in compliance with the License. 
007     * 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     **/
018    package org.activemq.jndi;
019    
020    import java.util.ArrayList;
021    import java.util.Hashtable;
022    import java.util.Iterator;
023    import java.util.List;
024    import java.util.Map;
025    import java.util.Properties;
026    import java.util.StringTokenizer;
027    
028    import javax.jms.ConnectionFactory;
029    import javax.jms.JMSException;
030    import javax.jms.Queue;
031    import javax.jms.Topic;
032    import javax.naming.Context;
033    import javax.naming.NamingException;
034    import javax.naming.spi.InitialContextFactory;
035    
036    import org.activemq.ActiveMQConnectionFactory;
037    import org.activemq.broker.Broker;
038    import org.activemq.message.ActiveMQQueue;
039    import org.activemq.message.ActiveMQTopic;
040    import org.apache.commons.logging.Log;
041    import org.apache.commons.logging.LogFactory;
042    
043    import EDU.oswego.cs.dl.util.concurrent.ConcurrentHashMap;
044    
045    /**
046     * A factory of the ActiveMQ InitialContext which contains {@link ConnectionFactory}
047     * instances as well as a child context called <i>destinations</i> which contain all of the
048     * current active destinations, in child context depending on the QoS such as
049     * transient or durable and queue or topic.
050     *
051     * @version $Revision: 1.1.1.1 $
052     */
053    public class ActiveMQInitialContextFactory implements InitialContextFactory {
054        private static final transient Log log = LogFactory.getLog(ActiveMQInitialContextFactory.class);
055    
056        protected static final String[] defaultConnectionFactoryNames = {
057            "ConnectionFactory", "QueueConnectionFactory", "TopicConnectionFactory"
058        };
059    
060        private String connectionPrefix = "connection.";
061        private String queuePrefix = "queue.";
062        private String topicPrefix = "topic.";
063    
064        public Context getInitialContext(Hashtable environment) throws NamingException {
065            // lets create a factory
066            Map data = new ConcurrentHashMap();
067            Broker broker = null;
068            
069            String[] names = getConnectionFactoryNames(environment);
070            for (int i = 0; i < names.length; i++) {
071                
072                String name = names[i];
073                ActiveMQConnectionFactory factory = createConnectionFactory(name, environment);
074                
075                if( broker==null ) {
076                    try {
077                        broker = factory.getEmbeddedBroker();
078                    }
079                    catch (JMSException e) {
080                        log.warn("Failed to get embedded broker", e);
081                    }
082                }
083                data.put(name,factory);
084            }
085                    
086            createQueues(data, environment);
087            createTopics(data, environment);
088            if (broker != null) {
089                data.put("destinations", broker.getDestinationContext(environment));
090            }
091    
092            data.put("dynamicQueues", new LazyCreateContext() {
093                protected Object createEntry(String name) {
094                    return new ActiveMQQueue(name);
095                }
096            });
097            data.put("dynamicTopics", new LazyCreateContext() {
098                protected Object createEntry(String name) {
099                    return new ActiveMQTopic(name);
100                }
101            });
102    
103            return new ReadOnlyContext(environment, data);
104        }
105    
106        private ActiveMQConnectionFactory createConnectionFactory(String name, Hashtable environment) {
107            Hashtable temp = new Hashtable(environment);
108            String prefix = connectionPrefix+name+".";
109            for (Iterator iter = environment.keySet().iterator(); iter.hasNext();) {
110                String key = (String) iter.next();
111                if( key.startsWith(prefix) ) {
112                    Object value = environment.get(key);
113                    // Rename the key...
114                    temp.remove(key);
115                    key = key.substring(prefix.length());
116                    temp.put(key, value);
117                }
118            }
119            return createConnectionFactory(temp);
120        }
121    
122        // Properties
123        //-------------------------------------------------------------------------
124        public String getTopicPrefix() {
125            return topicPrefix;
126        }
127    
128        public void setTopicPrefix(String topicPrefix) {
129            this.topicPrefix = topicPrefix;
130        }
131    
132        public String getQueuePrefix() {
133            return queuePrefix;
134        }
135    
136        public void setQueuePrefix(String queuePrefix) {
137            this.queuePrefix = queuePrefix;
138        }
139    
140        // Implementation methods
141        //-------------------------------------------------------------------------
142        protected String[] getConnectionFactoryNames(Map environment) {
143            String factoryNames = (String) environment.get("connectionFactoryNames");
144            if (factoryNames != null) {
145                List list = new ArrayList();
146                for (StringTokenizer enumeration = new StringTokenizer(factoryNames, ","); enumeration.hasMoreTokens();) {
147                    list.add(enumeration.nextToken().trim());
148                }
149                int size = list.size();
150                if (size > 0) {
151                    String[] answer = new String[size];
152                    list.toArray(answer);
153                    return answer;
154                }
155            }
156            return defaultConnectionFactoryNames;
157        }
158    
159        protected void createQueues(Map data, Hashtable environment) {
160            for (Iterator iter = environment.entrySet().iterator(); iter.hasNext();) {
161                Map.Entry entry = (Map.Entry) iter.next();
162                String key = entry.getKey().toString();
163                if (key.startsWith(queuePrefix)) {
164                    String jndiName = key.substring(queuePrefix.length());
165                    data.put(jndiName, createQueue(entry.getValue().toString()));
166                }
167            }
168        }
169    
170        protected void createTopics(Map data, Hashtable environment) {
171            for (Iterator iter = environment.entrySet().iterator(); iter.hasNext();) {
172                Map.Entry entry = (Map.Entry) iter.next();
173                String key = entry.getKey().toString();
174                if (key.startsWith(topicPrefix)) {
175                    String jndiName = key.substring(topicPrefix.length());
176                    data.put(jndiName, createTopic(entry.getValue().toString()));
177                }
178            }
179        }
180    
181        /**
182         * Factory method to create new Queue instances
183         */
184        protected Queue createQueue(String name) {
185            return new ActiveMQQueue(name);
186        }
187    
188        /**
189         * Factory method to create new Topic instances
190         */
191        protected Topic createTopic(String name) {
192            return new ActiveMQTopic(name);
193        }
194            
195        /**
196         * Factory method to create a new connection factory from the given environment
197         */
198        protected ActiveMQConnectionFactory createConnectionFactory(Hashtable environment) {
199            ActiveMQConnectionFactory answer = new ActiveMQConnectionFactory();
200            Properties properties = new Properties();
201            properties.putAll(environment);
202            answer.setProperties(properties);
203            return answer;
204        }
205    
206        public String getConnectionPrefix() {
207            return connectionPrefix;
208        }
209        
210    
211        public void setConnectionPrefix(String connectionPrefix) {
212            this.connectionPrefix = connectionPrefix;
213        }
214        
215    }