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 */
017package org.apache.activemq.jndi;
018
019import java.net.URISyntaxException;
020import java.util.ArrayList;
021import java.util.Hashtable;
022import java.util.Iterator;
023import java.util.List;
024import java.util.Map;
025import java.util.Properties;
026import java.util.StringTokenizer;
027import java.util.concurrent.ConcurrentHashMap;
028
029import javax.jms.Queue;
030import javax.jms.Topic;
031import javax.naming.Context;
032import javax.naming.NamingException;
033import javax.naming.spi.InitialContextFactory;
034
035import org.apache.activemq.ActiveMQConnectionFactory;
036import org.apache.activemq.ActiveMQXAConnectionFactory;
037import org.apache.activemq.command.ActiveMQQueue;
038import 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 */
049public 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}