| /** |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.qpid.jms.jndi; |
| |
| import java.net.URISyntaxException; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collections; |
| import java.util.Hashtable; |
| import java.util.Iterator; |
| import java.util.LinkedHashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Map.Entry; |
| import java.util.concurrent.ConcurrentHashMap; |
| |
| import javax.jms.Queue; |
| import javax.jms.Topic; |
| import javax.naming.Context; |
| import javax.naming.NamingException; |
| import javax.naming.spi.InitialContextFactory; |
| |
| import org.apache.qpid.jms.JmsConnectionFactory; |
| import org.apache.qpid.jms.JmsQueue; |
| import org.apache.qpid.jms.JmsTopic; |
| |
| /** |
| * A factory of the StompJms InitialContext which contains |
| * {@link javax.jms.ConnectionFactory} instances as well as a child context |
| * called <i>destinations</i> which contain all of the current active |
| * destinations, in child context depending on the QoS such as transient or |
| * durable and queue or topic. |
| * |
| * @since 1.0 |
| */ |
| public class JmsInitialContextFactory implements InitialContextFactory { |
| |
| static final String[] DEFAULT_CONNECTION_FACTORY_NAMES = { |
| "ConnectionFactory", "QueueConnectionFactory", "TopicConnectionFactory" }; |
| |
| static final String DEFAULT_REMOTE_URI = "amqp://localhost:5672"; |
| |
| static final String CONNECTION_FACTORY_KEY_PREFIX = "connectionfactory."; |
| static final String QUEUE_KEY_PREFIX = "queue."; |
| static final String TOPIC_KEY_PREFIX = "topic."; |
| static final String CONNECTION_FACTORY_DEFAULT_KEY_PREFIX = "default." + CONNECTION_FACTORY_KEY_PREFIX; |
| static final String CONNECTION_FACTORY_PROPERTY_KEY_PREFIX = "property." + CONNECTION_FACTORY_KEY_PREFIX; |
| |
| @SuppressWarnings("unchecked") |
| @Override |
| public Context getInitialContext(Hashtable<?, ?> environment) throws NamingException { |
| // Copy the environment to ensure we don't modify/reference it, it belongs to the caller. |
| Hashtable<Object, Object> environmentCopy = new Hashtable<Object, Object>(); |
| environmentCopy.putAll(environment); |
| |
| Map<String, Object> bindings = new ConcurrentHashMap<String, Object>(); |
| createConnectionFactories(environmentCopy, bindings); |
| createQueues(environmentCopy, bindings); |
| createTopics(environmentCopy, bindings); |
| |
| // Add sub-contexts for dynamic creation on lookup. |
| // "dynamicQueues/<queue-name>" |
| bindings.put("dynamicQueues", new LazyCreateContext() { |
| private static final long serialVersionUID = 6503881346214855588L; |
| |
| @Override |
| protected Object createEntry(String name) { |
| return new JmsQueue(name); |
| } |
| }); |
| |
| // "dynamicTopics/<topic-name>" |
| bindings.put("dynamicTopics", new LazyCreateContext() { |
| private static final long serialVersionUID = 2019166796234979615L; |
| |
| @Override |
| protected Object createEntry(String name) { |
| return new JmsTopic(name); |
| } |
| }); |
| |
| return createContext(environmentCopy, bindings); |
| } |
| |
| private void createConnectionFactories(Hashtable<Object, Object> environment, Map<String, Object> bindings) throws NamingException { |
| List<String> names = getConnectionFactoryNames(environment); |
| Map<String, String> defaults = getConnectionFactoryDefaults(environment); |
| for (String name : names) { |
| JmsConnectionFactory factory = null; |
| |
| try { |
| factory = createConnectionFactory(name, defaults, environment); |
| } catch (Exception e) { |
| NamingException ne = new NamingException("Exception while creating ConnectionFactory '" + name + "'."); |
| ne.initCause(e); |
| throw ne; |
| } |
| |
| bindings.put(name, factory); |
| } |
| } |
| |
| // Implementation methods |
| // ------------------------------------------------------------------------- |
| |
| protected ReadOnlyContext createContext(Hashtable<Object, Object> environment, Map<String, Object> bindings) { |
| return new ReadOnlyContext(environment, bindings); |
| } |
| |
| protected JmsConnectionFactory createConnectionFactory(String name, Map<String, String> defaults, Hashtable<Object, Object> environment) throws URISyntaxException { |
| String cfNameKey = CONNECTION_FACTORY_KEY_PREFIX + name; |
| Map<String, String> props = new LinkedHashMap<String, String>(); |
| |
| // Add the defaults which apply to all connection factories |
| props.putAll(defaults); |
| |
| // Add any URI entry for this specific factory name |
| Object o = environment.get(cfNameKey); |
| if (o != null) { |
| String value = String.valueOf(o); |
| if (value.trim().length() != 0) { |
| props.put(JmsConnectionFactory.REMOTE_URI_PROP, value); |
| } |
| } |
| |
| // Add any factory-specific additional properties |
| props.putAll(getConnectionFactoryProperties(name, environment)); |
| |
| return createConnectionFactory(props); |
| } |
| |
| protected List<String> getConnectionFactoryNames(Map<Object, Object> environment) { |
| List<String> list = new ArrayList<String>(); |
| for (Iterator<Entry<Object, Object>> iter = environment.entrySet().iterator(); iter.hasNext();) { |
| Map.Entry<Object, Object> entry = iter.next(); |
| String key = String.valueOf(entry.getKey()); |
| if (key.startsWith(CONNECTION_FACTORY_KEY_PREFIX)) { |
| String jndiName = key.substring(CONNECTION_FACTORY_KEY_PREFIX.length()); |
| list.add(jndiName); |
| } |
| } |
| |
| if(list.isEmpty()) |
| { |
| list.addAll(Arrays.asList(DEFAULT_CONNECTION_FACTORY_NAMES)); |
| } |
| |
| return list; |
| } |
| |
| protected Map<String, String> getConnectionFactoryDefaults(Map<Object, Object> environment) { |
| Map<String, String> map = new LinkedHashMap<String, String>(); |
| map.put(JmsConnectionFactory.REMOTE_URI_PROP, DEFAULT_REMOTE_URI); |
| |
| for (Iterator<Entry<Object, Object>> iter = environment.entrySet().iterator(); iter.hasNext();) { |
| Map.Entry<Object, Object> entry = iter.next(); |
| String key = String.valueOf(entry.getKey()); |
| if (key.startsWith(CONNECTION_FACTORY_DEFAULT_KEY_PREFIX)) { |
| String jndiName = key.substring(CONNECTION_FACTORY_DEFAULT_KEY_PREFIX.length()); |
| map.put(jndiName, String.valueOf(entry.getValue())); |
| } |
| } |
| |
| return Collections.unmodifiableMap(map); |
| } |
| |
| protected Map<String, String> getConnectionFactoryProperties(String factoryName, Map<Object, Object> environment) { |
| Map<String, String> map = new LinkedHashMap<String, String>(); |
| |
| String factoryPropertiesPrefix = CONNECTION_FACTORY_PROPERTY_KEY_PREFIX + factoryName + "."; |
| |
| for (Iterator<Entry<Object, Object>> iter = environment.entrySet().iterator(); iter.hasNext();) { |
| Map.Entry<Object, Object> entry = iter.next(); |
| String key = String.valueOf(entry.getKey()); |
| if (key.startsWith(factoryPropertiesPrefix)) { |
| String propertyName = key.substring(factoryPropertiesPrefix.length()); |
| map.put(propertyName, String.valueOf(entry.getValue())); |
| } |
| } |
| |
| return map; |
| } |
| |
| protected void createQueues(Hashtable<Object, Object> environment, Map<String, Object> bindings) { |
| for (Iterator<Entry<Object, Object>> iter = environment.entrySet().iterator(); iter.hasNext();) { |
| Map.Entry<Object, Object> entry = iter.next(); |
| String key = entry.getKey().toString(); |
| if (key.startsWith(QUEUE_KEY_PREFIX)) { |
| String jndiName = key.substring(QUEUE_KEY_PREFIX.length()); |
| bindings.put(jndiName, createQueue(entry.getValue().toString())); |
| } |
| } |
| } |
| |
| protected void createTopics(Hashtable<Object, Object> environment, Map<String, Object> bindings) { |
| for (Iterator<Entry<Object, Object>> iter = environment.entrySet().iterator(); iter.hasNext();) { |
| Map.Entry<Object, Object> entry = iter.next(); |
| String key = entry.getKey().toString(); |
| if (key.startsWith(TOPIC_KEY_PREFIX)) { |
| String jndiName = key.substring(TOPIC_KEY_PREFIX.length()); |
| bindings.put(jndiName, createTopic(entry.getValue().toString())); |
| } |
| } |
| } |
| |
| /** |
| * Factory method to create new Queue instances |
| */ |
| protected Queue createQueue(String name) { |
| return new JmsQueue(name); |
| } |
| |
| /** |
| * Factory method to create new Topic instances |
| */ |
| protected Topic createTopic(String name) { |
| return new JmsTopic(name); |
| } |
| |
| /** |
| * Factory method to create a new connection factory using the given properties |
| */ |
| protected JmsConnectionFactory createConnectionFactory(Map<String, String> properties) { |
| JmsConnectionFactory factory = new JmsConnectionFactory(); |
| Map<String, String> unused = factory.setProperties(properties); |
| if (!unused.isEmpty()) { |
| String msg = |
| " Not all properties could be set on the ConnectionFactory." |
| + " Check the properties are spelled correctly." |
| + " Unused properties=[" + unused + "]."; |
| throw new IllegalArgumentException(msg); |
| } |
| |
| return factory; |
| } |
| } |