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