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.camel.impl;
018
019import java.util.Hashtable;
020import java.util.LinkedHashMap;
021import java.util.LinkedHashSet;
022import java.util.Map;
023import java.util.Set;
024
025import javax.naming.Context;
026import javax.naming.InitialContext;
027import javax.naming.NameClassPair;
028import javax.naming.NameNotFoundException;
029import javax.naming.NamingEnumeration;
030import javax.naming.NamingException;
031
032import org.apache.camel.NoSuchBeanException;
033import org.apache.camel.RuntimeCamelException;
034import org.apache.camel.spi.Registry;
035import org.apache.camel.util.jndi.CamelInitialContextFactory;
036
037/**
038 * A {@link Registry} implementation which looks up the objects in JNDI
039 */
040public class JndiRegistry implements Registry {
041    private Context context;
042    private Map environment;
043    private final boolean standalone;
044
045    public JndiRegistry() {
046        this.standalone = false;
047    }
048
049    public JndiRegistry(Map environment) {
050        this.environment = environment;
051        this.standalone = false;
052    }
053
054    public JndiRegistry(Context context) {
055        this.context = context;
056        this.standalone = false;
057    }
058
059    /**
060     * Whether to use standalone mode, where the JNDI initial context factory is using
061     * {@link CamelInitialContextFactory}.
062     */
063    public JndiRegistry(boolean standalone) {
064        this.standalone = true;
065    }
066
067    public <T> T lookupByNameAndType(String name, Class<T> type) {
068        Object answer = lookupByName(name);
069
070        // just to be safe
071        if (answer == null) {
072            return null;
073        }
074
075        try {
076            return type.cast(answer);
077        } catch (Throwable e) {
078            String msg = "Found bean: " + name + " in JNDI Context: " + context
079                    + " of type: " + answer.getClass().getName() + " expected type was: " + type;
080            throw new NoSuchBeanException(name, msg, e);
081        }
082    }
083
084    public Object lookupByName(String name) {
085        try {
086            return getContext().lookup(name);
087        } catch (NameNotFoundException e) {
088            return null;
089        } catch (NamingException e) {
090            return null;
091        }
092    }
093
094    public <T> Map<String, T> findByTypeWithName(Class<T> type) {
095        Map<String, T> answer = new LinkedHashMap<>();
096        try {
097            NamingEnumeration<NameClassPair> list = getContext().list("");
098            while (list.hasMore()) {
099                NameClassPair pair = list.next();
100                Object instance = context.lookup(pair.getName());
101                if (type.isInstance(instance)) {
102                    answer.put(pair.getName(), type.cast(instance));
103                }
104            }
105        } catch (NamingException e) {
106            // ignore
107        }
108
109        return answer;
110    }
111
112    public <T> Set<T> findByType(Class<T> type) {
113        Set<T> answer = new LinkedHashSet<>();
114        try {
115            NamingEnumeration<NameClassPair> list = getContext().list("");
116            while (list.hasMore()) {
117                NameClassPair pair = list.next();
118                Object instance = context.lookup(pair.getName());
119                if (type.isInstance(instance)) {
120                    answer.add(type.cast(instance));
121                }
122            }
123        } catch (NamingException e) {
124            // ignore
125        }
126        return answer;
127    }
128
129    public Object lookup(String name) {
130        return lookupByName(name);
131    }
132
133    public <T> T lookup(String name, Class<T> type) {
134        return lookupByNameAndType(name, type);
135    }
136
137    public <T> Map<String, T> lookupByType(Class<T> type) {
138        return findByTypeWithName(type);
139    }
140
141    public void bind(String name, Object object) {
142        try {
143            getContext().bind(name, object);
144        } catch (NamingException e) {
145            throw new RuntimeCamelException(e);
146        }
147    }
148
149    public void close() throws NamingException {
150        if (context != null) {
151            context.close();
152        }
153    }
154
155    public Context getContext() throws NamingException {
156        if (context == null) {
157            context = createContext();
158        }
159        return context;
160    }
161
162    public void setContext(Context context) {
163        this.context = context;
164    }
165
166    protected Context createContext() throws NamingException {
167        Hashtable<Object, Object> properties = new Hashtable<>(System.getProperties());
168        if (environment != null) {
169            properties.putAll(environment);
170        }
171        // must include a factory if none provided in standalone mode
172        if (standalone && !properties.containsKey("java.naming.factory.initial")) {
173            properties.put("java.naming.factory.initial", "org.apache.camel.util.jndi.CamelInitialContextFactory");
174        }
175        return new InitialContext(properties);
176    }
177}