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 */
017 package org.apache.servicemix.finder;
018
019 import java.io.BufferedInputStream;
020 import java.io.IOException;
021 import java.io.InputStream;
022 import java.util.Map;
023 import java.util.Properties;
024
025 import java.util.concurrent.ConcurrentHashMap;
026
027 public class FactoryFinder {
028
029 private final String path;
030
031 private final Map<String, Class<?>> classMap = new ConcurrentHashMap<String, Class<?>>();
032
033 public FactoryFinder(String path) {
034 this.path = path;
035 }
036
037 /**
038 * Creates a new instance of the given key
039 *
040 * @param key is the key to add to the path to find a text file
041 * containing the factory name
042 * @return a newly created instance
043 */
044 public Object newInstance(String key) throws IllegalAccessException, InstantiationException, IOException,
045 ClassNotFoundException {
046 return newInstance(key, null);
047 }
048
049 public Object newInstance(String key, String propertyPrefix) throws IllegalAccessException, InstantiationException,
050 IOException, ClassNotFoundException {
051 if (propertyPrefix == null) {
052 propertyPrefix = "";
053 }
054 Class clazz = classMap.get(propertyPrefix + key);
055 if (clazz == null) {
056 clazz = newInstance(doFindFactoryProperies(key), propertyPrefix);
057 classMap.put(propertyPrefix + key, clazz);
058 }
059 return clazz.newInstance();
060 }
061
062 private Class newInstance(Properties properties, String propertyPrefix) throws ClassNotFoundException, IOException {
063
064 String className = properties.getProperty(propertyPrefix + "class");
065 if (className == null) {
066 throw new IOException("Expected property is missing: " + propertyPrefix + "class");
067 }
068 Class clazz;
069 try {
070 clazz = Thread.currentThread().getContextClassLoader().loadClass(className);
071 } catch (ClassNotFoundException e) {
072 clazz = FactoryFinder.class.getClassLoader().loadClass(className);
073 }
074
075 return clazz;
076 }
077
078 private Properties doFindFactoryProperies(String key) throws IOException {
079 String uri = path + key;
080
081 // lets try the thread context class loader first
082 InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream(uri);
083 if (in == null) {
084 in = FactoryFinder.class.getClassLoader().getResourceAsStream(uri);
085 if (in == null) {
086 throw new IOException("Could not find factory class for resource: " + uri);
087 }
088 }
089
090 // lets load the file
091 BufferedInputStream reader = null;
092 try {
093 reader = new BufferedInputStream(in);
094 Properties properties = new Properties();
095 properties.load(reader);
096 return properties;
097 } finally {
098 try {
099 reader.close();
100 } catch (Exception e) {
101 // Do nothing
102 }
103 }
104 }
105 }