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", "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}