001 /**
002 *
003 * Licensed to the Apache Software Foundation (ASF) under one or more
004 * contributor license agreements. See the NOTICE file distributed with
005 * this work for additional information regarding copyright ownership.
006 * The ASF licenses this file to You under the Apache License, Version 2.0
007 * (the "License"); you may not use this file except in compliance with
008 * the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018 package org.apache.camel.util;
019
020 import org.apache.camel.spi.Injector;
021
022 import java.io.BufferedInputStream;
023 import java.io.IOException;
024 import java.io.InputStream;
025 import java.util.Properties;
026 import java.util.concurrent.ConcurrentHashMap;
027
028 public class FactoryFinder {
029 private final String path;
030 private final ConcurrentHashMap classMap = new ConcurrentHashMap();
031
032 public FactoryFinder() {
033 this("META-INF/services/org/apache/camel/");
034 }
035
036 public FactoryFinder(String path) {
037 this.path = path;
038 }
039
040 /**
041 * Creates a new instance of the given key
042 *
043 * @param key is the key to add to the path to find a text file
044 * containing the factory name
045 * @return a newly created instance
046 */
047 public Object newInstance(String key)
048 throws IllegalAccessException, InstantiationException, IOException, ClassNotFoundException {
049 return newInstance(key, (String) null);
050 }
051
052 public Object newInstance(String key, String propertyPrefix)
053 throws IllegalAccessException, InstantiationException, IOException, ClassNotFoundException {
054 Class clazz = findClass(key, propertyPrefix);
055 return clazz.newInstance();
056 }
057
058 public Object newInstance(String key, Injector injector) throws IOException, ClassNotFoundException {
059 return newInstance(key, injector, null);
060 }
061
062 public Object newInstance(String key, Injector injector, String propertyPrefix) throws IOException, ClassNotFoundException {
063 Class type = findClass(key, propertyPrefix);
064 return injector.newInstance(type);
065 }
066
067 public Class findClass(String key) throws ClassNotFoundException, IOException {
068 return findClass(key, null);
069 }
070
071 public Class findClass(String key, String propertyPrefix) throws ClassNotFoundException, IOException {
072 if (propertyPrefix == null) {
073 propertyPrefix = "";
074 }
075
076 Class clazz = (Class) classMap.get(propertyPrefix + key);
077 if (clazz == null) {
078 clazz = newInstance(doFindFactoryProperies(key), propertyPrefix);
079 classMap.put(propertyPrefix + key, clazz);
080 }
081 return clazz;
082 }
083
084 private Class newInstance(Properties properties, String propertyPrefix) throws ClassNotFoundException, IOException {
085
086 String className = properties.getProperty(propertyPrefix + "class");
087 if (className == null) {
088 throw new IOException("Expected property is missing: " + propertyPrefix + "class");
089 }
090 Class clazz = null;
091 ClassLoader loader = Thread.currentThread().getContextClassLoader();
092 if (loader != null) {
093 try {
094 clazz = loader.loadClass(className);
095 }
096 catch (ClassNotFoundException e) {
097 // ignore
098 }
099 }
100 if (clazz == null) {
101 clazz = FactoryFinder.class.getClassLoader().loadClass(className);
102 }
103 return clazz;
104 }
105
106 private Properties doFindFactoryProperies(String key) throws IOException {
107 String uri = path + key;
108
109 // lets try the thread context class loader first
110 ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
111 if (classLoader == null) {
112 classLoader = getClass().getClassLoader();
113 }
114 InputStream in = classLoader.getResourceAsStream(uri);
115 if (in == null) {
116 in = FactoryFinder.class.getClassLoader().getResourceAsStream(uri);
117 if (in == null) {
118 throw new NoFactoryAvailableException(uri);
119 }
120 }
121
122 // lets load the file
123 BufferedInputStream reader = null;
124 try {
125 reader = new BufferedInputStream(in);
126 Properties properties = new Properties();
127 properties.load(reader);
128 return properties;
129 }
130 finally {
131 try {
132 reader.close();
133 }
134 catch (Exception e) {
135 }
136 }
137 }
138 }