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 }