blob: 44c9adb77b808cb4310bee45bd541591e908f942 [file] [log] [blame]
/**
* 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.camel.impl;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.camel.NoFactoryAvailableException;
import org.apache.camel.spi.ClassResolver;
import org.apache.camel.spi.FactoryFinder;
import org.apache.camel.spi.Injector;
import org.apache.camel.util.CastUtils;
import org.apache.camel.util.IOHelper;
/**
* Default factory finder.
*/
public class DefaultFactoryFinder implements FactoryFinder {
protected final ConcurrentHashMap<String, Class<?>> classMap = new ConcurrentHashMap<String, Class<?>>();
private final ClassResolver classResolver;
private final String path;
public DefaultFactoryFinder(ClassResolver classResolver, String resourcePath) {
this.classResolver = classResolver;
this.path = resourcePath;
}
public String getResourcePath() {
return path;
}
public Object newInstance(String key) throws NoFactoryAvailableException {
try {
return newInstance(key, null);
} catch (Exception e) {
throw new NoFactoryAvailableException(key, e);
}
}
public <T> List<T> newInstances(String key, Injector injector, Class<T> type) throws ClassNotFoundException, IOException {
List<Class<T>> list = CastUtils.cast(findClasses(key));
List<T> answer = new ArrayList<T>(list.size());
answer.add(newInstance(key, injector, type));
return answer;
}
public Class<?> findClass(String key) throws ClassNotFoundException, IOException {
return findClass(key, null);
}
public Class<?> findClass(String key, String propertyPrefix) throws ClassNotFoundException, IOException {
String prefix = propertyPrefix != null ? propertyPrefix : "";
Class<?> clazz = classMap.get(prefix + key);
if (clazz == null) {
clazz = newInstance(doFindFactoryProperties(key), prefix);
if (clazz != null) {
classMap.put(prefix + key, clazz);
}
}
return clazz;
}
private Object newInstance(String key, String propertyPrefix) throws IllegalAccessException,
InstantiationException, IOException, ClassNotFoundException {
Class<?> clazz = findClass(key, propertyPrefix);
return clazz.newInstance();
}
private <T> T newInstance(String key, Injector injector, Class<T> expectedType) throws IOException,
ClassNotFoundException {
return newInstance(key, injector, null, expectedType);
}
private <T> T newInstance(String key, Injector injector, String propertyPrefix, Class<T> expectedType)
throws IOException, ClassNotFoundException {
Class<?> type = findClass(key, propertyPrefix);
Object value = injector.newInstance(type);
if (expectedType.isInstance(value)) {
return expectedType.cast(value);
} else {
throw new ClassCastException("Not instanceof " + expectedType.getName() + " value: " + value);
}
}
private List<Class<?>> findClasses(String key) throws ClassNotFoundException, IOException {
return findClasses(key, null);
}
private List<Class<?>> findClasses(String key, String propertyPrefix) throws ClassNotFoundException, IOException {
// TODO change to support finding multiple classes on the classpath!
Class<?> type = findClass(key, propertyPrefix);
return CastUtils.cast(Collections.singletonList(type));
}
private Class<?> newInstance(Properties properties, String propertyPrefix) throws ClassNotFoundException, IOException {
String className = properties.getProperty(propertyPrefix + "class");
if (className == null) {
throw new IOException("Expected property is missing: " + propertyPrefix + "class");
}
Class<?> clazz = classResolver.resolveClass(className);
if (clazz == null) {
throw new ClassNotFoundException(className);
}
return clazz;
}
private Properties doFindFactoryProperties(String key) throws IOException {
String uri = path + key;
InputStream in = classResolver.loadResourceAsStream(uri);
if (in == null) {
throw new NoFactoryAvailableException(uri);
}
// lets load the file
BufferedInputStream reader = null;
try {
reader = new BufferedInputStream(in);
Properties properties = new Properties();
properties.load(reader);
return properties;
} finally {
IOHelper.close(reader, key, null);
IOHelper.close(in, key, null);
}
}
}