org.apache.camel.impl.DefaultFactoryFinder Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of camel-core Show documentation
Show all versions of camel-core Show documentation
The Core Camel Java DSL based router
/**
* 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 java.util.concurrent.ConcurrentMap;
import java.util.function.Function;
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 {
private final ConcurrentMap> classMap = new ConcurrentHashMap<>();
private final ClassResolver classResolver;
private final String path;
public DefaultFactoryFinder(ClassResolver classResolver, String resourcePath) {
this.classResolver = classResolver;
this.path = resourcePath;
}
@Override
public String getResourcePath() {
return path;
}
@Override
public Object newInstance(String key) throws NoFactoryAvailableException {
try {
return newInstance(key, null);
} catch (Exception e) {
throw new NoFactoryAvailableException(key, e);
}
}
@Override
public List newInstances(String key, Injector injector, Class type) throws ClassNotFoundException, IOException {
List> list = CastUtils.cast(findClasses(key));
List answer = new ArrayList<>(list.size());
answer.add(newInstance(key, injector, type));
return answer;
}
@Override
public Class findClass(String key) throws ClassNotFoundException, IOException {
return findClass(key, null);
}
@Override
public Class findClass(String key, String propertyPrefix) throws ClassNotFoundException, IOException {
final String prefix = propertyPrefix != null ? propertyPrefix : "";
final String classKey = prefix + key;
return addToClassMap(classKey, new ClassSupplier() {
@Override
public Class get() throws ClassNotFoundException, IOException {
return DefaultFactoryFinder.this.newInstance(DefaultFactoryFinder.this.doFindFactoryProperties(key), prefix);
}
});
}
@Override
public Class findClass(String key, String propertyPrefix, Class clazz) throws ClassNotFoundException, IOException {
// Just ignore clazz which is only useful for OSGiFactoryFinder
return findClass(key, propertyPrefix);
}
private Object newInstance(String key, String propertyPrefix) throws IllegalAccessException,
InstantiationException, IOException, ClassNotFoundException {
Class clazz = findClass(key, propertyPrefix);
return clazz.newInstance();
}
private T newInstance(String key, Injector injector, Class expectedType) throws IOException,
ClassNotFoundException {
return newInstance(key, injector, null, expectedType);
}
private T newInstance(String key, Injector injector, String propertyPrefix, Class 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> findClasses(String key) throws ClassNotFoundException, IOException {
return findClasses(key, null);
}
private List> findClasses(String key, String propertyPrefix) throws ClassNotFoundException, IOException {
Class type = findClass(key, propertyPrefix);
return 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 = IOHelper.buffered(in);
Properties properties = new Properties();
properties.load(reader);
return properties;
} finally {
IOHelper.close(reader, key, null);
IOHelper.close(in, key, null);
}
}
/*
* This is a wrapper function to deal with exceptions in lambdas: the exception
* is wrapped by a runtime exception (WrappedRuntimeException) which we catch
* later on with the only purpose to re-throw the original exception.
*/
protected Class addToClassMap(String key, ClassSupplier mappingFunction) throws ClassNotFoundException, IOException {
try {
return classMap.computeIfAbsent(key, new Function>() {
@Override
public Class apply(String classKey) {
try {
return mappingFunction.get();
} catch (ClassNotFoundException e) {
throw new WrappedRuntimeException(e);
} catch (NoFactoryAvailableException e) {
throw new WrappedRuntimeException(e);
} catch (IOException e) {
throw new WrappedRuntimeException(e);
}
}
});
} catch (WrappedRuntimeException e) {
if (e.getCause() instanceof ClassNotFoundException) {
throw (ClassNotFoundException)e.getCause();
} else if (e.getCause() instanceof NoFactoryAvailableException) {
throw (NoFactoryAvailableException)e.getCause();
} else if (e.getCause() instanceof IOException) {
throw (IOException)e.getCause();
} else {
throw new RuntimeException(e.getCause());
}
}
}
@FunctionalInterface
protected interface ClassSupplier {
Class get() throws ClassNotFoundException, IOException;
}
private final class WrappedRuntimeException extends RuntimeException {
WrappedRuntimeException(Exception e) {
super(e);
}
}
}