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", "XAConnectionFactory", "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            if (DEFAULT_CONNECTION_FACTORY_NAMES[1].equals(name)) {
131                // don't try to mod environment, it may be readonly
132                temp.put("xa", String.valueOf(true));
133            }
134            String prefix = connectionPrefix + name + ".";
135            for (Iterator iter = environment.entrySet().iterator(); iter.hasNext();) {
136                Map.Entry entry = (Map.Entry)iter.next();
137                String key = (String)entry.getKey();
138                if (key.startsWith(prefix)) {
139                    // Rename the key...
140                    temp.remove(key);
141                    key = key.substring(prefix.length());
142                    temp.put(key, entry.getValue());
143                }
144            }
145            return createConnectionFactory(temp);
146        }
147    
148        protected String[] getConnectionFactoryNames(Map environment) {
149            String factoryNames = (String)environment.get("connectionFactoryNames");
150            if (factoryNames != null) {
151                List<String> list = new ArrayList<String>();
152                for (StringTokenizer enumeration = new StringTokenizer(factoryNames, ","); enumeration.hasMoreTokens();) {
153                    list.add(enumeration.nextToken().trim());
154                }
155                int size = list.size();
156                if (size > 0) {
157                    String[] answer = new String[size];
158                    list.toArray(answer);
159                    return answer;
160                }
161            }
162            return DEFAULT_CONNECTION_FACTORY_NAMES;
163        }
164    
165        protected void createQueues(Map<String, Object> data, Hashtable environment) {
166            for (Iterator iter = environment.entrySet().iterator(); iter.hasNext();) {
167                Map.Entry entry = (Map.Entry)iter.next();
168                String key = entry.getKey().toString();
169                if (key.startsWith(queuePrefix)) {
170                    String jndiName = key.substring(queuePrefix.length());
171                    data.put(jndiName, createQueue(entry.getValue().toString()));
172                }
173            }
174        }
175    
176        protected void createTopics(Map<String, Object> data, Hashtable environment) {
177            for (Iterator iter = environment.entrySet().iterator(); iter.hasNext();) {
178                Map.Entry entry = (Map.Entry)iter.next();
179                String key = entry.getKey().toString();
180                if (key.startsWith(topicPrefix)) {
181                    String jndiName = key.substring(topicPrefix.length());
182                    data.put(jndiName, createTopic(entry.getValue().toString()));
183                }
184            }
185        }
186    
187        /**
188         * Factory method to create new Queue instances
189         */
190        protected Queue createQueue(String name) {
191            return new ActiveMQQueue(name);
192        }
193    
194        /**
195         * Factory method to create new Topic instances
196         */
197        protected Topic createTopic(String name) {
198            return new ActiveMQTopic(name);
199        }
200    
201        /**
202         * Factory method to create a new connection factory from the given
203         * environment
204         */
205        protected ActiveMQConnectionFactory createConnectionFactory(Hashtable environment) throws URISyntaxException {
206            ActiveMQConnectionFactory answer = needsXA(environment) ? new ActiveMQXAConnectionFactory() : new ActiveMQConnectionFactory();
207            Properties properties = new Properties();
208            properties.putAll(environment);
209            answer.setProperties(properties);
210            return answer;
211        }
212    
213        private boolean needsXA(Hashtable environment) {
214            boolean isXA = Boolean.parseBoolean((String) environment.get("xa"));
215            // property not applicable to connectionfactory so remove
216            environment.remove("xa");
217            return isXA;
218        }
219    
220        public String getConnectionPrefix() {
221            return connectionPrefix;
222        }
223    
224        public void setConnectionPrefix(String connectionPrefix) {
225            this.connectionPrefix = connectionPrefix;
226        }
227    
228    }