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 javax.jms.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 */ 047public class ActiveMQInitialContextFactory implements InitialContextFactory { 048 049 private static final String[] DEFAULT_CONNECTION_FACTORY_NAMES = {"ConnectionFactory", "XAConnectionFactory", "QueueConnectionFactory", "TopicConnectionFactory"}; 050 051 private String connectionPrefix = "connection."; 052 private String queuePrefix = "queue."; 053 private String topicPrefix = "topic."; 054 055 @Override 056 public Context getInitialContext(Hashtable environment) throws NamingException { 057 // lets create a factory 058 Map<String, Object> data = new ConcurrentHashMap<String, Object>(); 059 String[] names = getConnectionFactoryNames(environment); 060 for (int i = 0; i < names.length; i++) { 061 ActiveMQConnectionFactory factory = null; 062 String name = names[i]; 063 064 try { 065 factory = createConnectionFactory(name, environment); 066 } catch (Exception e) { 067 throw new NamingException("Invalid broker URL"); 068 069 } 070 /* 071 * if( broker==null ) { try { broker = factory.getEmbeddedBroker(); } 072 * catch (JMSException e) { log.warn("Failed to get embedded 073 * broker", e); } } 074 */ 075 data.put(name, factory); 076 } 077 078 createQueues(data, environment); 079 createTopics(data, environment); 080 /* 081 * if (broker != null) { data.put("destinations", 082 * broker.getDestinationContext(environment)); } 083 */ 084 data.put("dynamicQueues", new LazyCreateContext() { 085 private static final long serialVersionUID = 6503881346214855588L; 086 087 @Override 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 @Override 096 protected Object createEntry(String name) { 097 return new ActiveMQTopic(name); 098 } 099 }); 100 101 return createContext(environment, data); 102 } 103 104 // Properties 105 // ------------------------------------------------------------------------- 106 public String getTopicPrefix() { 107 return topicPrefix; 108 } 109 110 public void setTopicPrefix(String topicPrefix) { 111 this.topicPrefix = topicPrefix; 112 } 113 114 public String getQueuePrefix() { 115 return queuePrefix; 116 } 117 118 public void setQueuePrefix(String queuePrefix) { 119 this.queuePrefix = queuePrefix; 120 } 121 122 // Implementation methods 123 // ------------------------------------------------------------------------- 124 125 protected ReadOnlyContext createContext(Hashtable environment, Map<String, Object> data) { 126 return new ReadOnlyContext(environment, data); 127 } 128 129 protected ActiveMQConnectionFactory createConnectionFactory(String name, Hashtable environment) throws URISyntaxException { 130 Hashtable temp = new Hashtable(environment); 131 if (DEFAULT_CONNECTION_FACTORY_NAMES[1].equals(name)) { 132 // don't try to mod environment, it may be readonly 133 temp.put("xa", String.valueOf(true)); 134 } 135 String prefix = connectionPrefix + name + "."; 136 for (Iterator iter = environment.entrySet().iterator(); iter.hasNext();) { 137 Map.Entry entry = (Map.Entry)iter.next(); 138 String key = (String)entry.getKey(); 139 if (key.startsWith(prefix)) { 140 // Rename the key... 141 temp.remove(key); 142 key = key.substring(prefix.length()); 143 temp.put(key, entry.getValue()); 144 } 145 } 146 return createConnectionFactory(temp); 147 } 148 149 protected String[] getConnectionFactoryNames(Map environment) { 150 String factoryNames = (String)environment.get("connectionFactoryNames"); 151 if (factoryNames != null) { 152 List<String> list = new ArrayList<String>(); 153 for (StringTokenizer enumeration = new StringTokenizer(factoryNames, ","); enumeration.hasMoreTokens();) { 154 list.add(enumeration.nextToken().trim()); 155 } 156 int size = list.size(); 157 if (size > 0) { 158 String[] answer = new String[size]; 159 list.toArray(answer); 160 return answer; 161 } 162 } 163 return DEFAULT_CONNECTION_FACTORY_NAMES; 164 } 165 166 protected void createQueues(Map<String, Object> data, Hashtable environment) { 167 for (Iterator iter = environment.entrySet().iterator(); iter.hasNext();) { 168 Map.Entry entry = (Map.Entry)iter.next(); 169 String key = entry.getKey().toString(); 170 if (key.startsWith(queuePrefix)) { 171 String jndiName = key.substring(queuePrefix.length()); 172 data.put(jndiName, createQueue(entry.getValue().toString())); 173 } 174 } 175 } 176 177 protected void createTopics(Map<String, Object> data, Hashtable environment) { 178 for (Iterator iter = environment.entrySet().iterator(); iter.hasNext();) { 179 Map.Entry entry = (Map.Entry)iter.next(); 180 String key = entry.getKey().toString(); 181 if (key.startsWith(topicPrefix)) { 182 String jndiName = key.substring(topicPrefix.length()); 183 data.put(jndiName, createTopic(entry.getValue().toString())); 184 } 185 } 186 } 187 188 /** 189 * Factory method to create new Queue instances 190 */ 191 protected Queue createQueue(String name) { 192 return new ActiveMQQueue(name); 193 } 194 195 /** 196 * Factory method to create new Topic instances 197 */ 198 protected Topic createTopic(String name) { 199 return new ActiveMQTopic(name); 200 } 201 202 /** 203 * Factory method to create a new connection factory from the given 204 * environment 205 */ 206 protected ActiveMQConnectionFactory createConnectionFactory(Hashtable environment) throws URISyntaxException { 207 ActiveMQConnectionFactory answer = needsXA(environment) ? new ActiveMQXAConnectionFactory() : new ActiveMQConnectionFactory(); 208 Properties properties = new Properties(); 209 properties.putAll(environment); 210 answer.setProperties(properties); 211 return answer; 212 } 213 214 private boolean needsXA(Hashtable environment) { 215 boolean isXA = Boolean.parseBoolean((String) environment.get("xa")); 216 // property not applicable to connectionfactory so remove 217 environment.remove("xa"); 218 return isXA; 219 } 220 221 public String getConnectionPrefix() { 222 return connectionPrefix; 223 } 224 225 public void setConnectionPrefix(String connectionPrefix) { 226 this.connectionPrefix = connectionPrefix; 227 } 228}