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 }