You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by lb...@apache.org on 2017/02/09 14:28:57 UTC
camel git commit: CAMEL-10812: FactoryFinder: make
DefaultFactoryFinder and OsgiFactoryFinder thread safe
Repository: camel
Updated Branches:
refs/heads/master d7947a205 -> bb224ecbc
CAMEL-10812: FactoryFinder: make DefaultFactoryFinder and OsgiFactoryFinder thread safe
Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/bb224ecb
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/bb224ecb
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/bb224ecb
Branch: refs/heads/master
Commit: bb224ecbc2ab40efe01caf77493844e6f7f5f56e
Parents: d7947a2
Author: lburgazzoli <lb...@gmail.com>
Authored: Thu Feb 9 15:28:24 2017 +0100
Committer: lburgazzoli <lb...@gmail.com>
Committed: Thu Feb 9 15:28:30 2017 +0100
----------------------------------------------------------------------
.../apache/camel/impl/DefaultFactoryFinder.java | 62 ++++++++++++++++----
.../camel/impl/DefaultFactoryFinderTest.java | 5 +-
.../camel/core/osgi/OsgiFactoryFinder.java | 27 ++++-----
3 files changed, 64 insertions(+), 30 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/camel/blob/bb224ecb/camel-core/src/main/java/org/apache/camel/impl/DefaultFactoryFinder.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/DefaultFactoryFinder.java b/camel-core/src/main/java/org/apache/camel/impl/DefaultFactoryFinder.java
index 009d7b5..7697cfb 100644
--- a/camel-core/src/main/java/org/apache/camel/impl/DefaultFactoryFinder.java
+++ b/camel-core/src/main/java/org/apache/camel/impl/DefaultFactoryFinder.java
@@ -38,7 +38,7 @@ import org.apache.camel.util.IOHelper;
*/
public class DefaultFactoryFinder implements FactoryFinder {
- protected final ConcurrentMap<String, Class<?>> classMap = new ConcurrentHashMap<String, Class<?>>();
+ private final ConcurrentMap<String, Class<?>> classMap = new ConcurrentHashMap<String, Class<?>>();
private final ClassResolver classResolver;
private final String path;
@@ -47,10 +47,12 @@ public class DefaultFactoryFinder implements FactoryFinder {
this.path = resourcePath;
}
+ @Override
public String getResourcePath() {
return path;
}
+ @Override
public Object newInstance(String key) throws NoFactoryAvailableException {
try {
return newInstance(key, null);
@@ -59,6 +61,7 @@ public class DefaultFactoryFinder implements FactoryFinder {
}
}
+ @Override
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());
@@ -66,23 +69,20 @@ public class DefaultFactoryFinder implements FactoryFinder {
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 {
- String prefix = propertyPrefix != null ? propertyPrefix : "";
+ final String prefix = propertyPrefix != null ? propertyPrefix : "";
+ final String classKey = prefix + key;
- Class<?> clazz = classMap.get(prefix + key);
- if (clazz == null) {
- clazz = newInstance(doFindFactoryProperties(key), prefix);
- if (clazz != null) {
- classMap.put(prefix + key, clazz);
- }
- }
- return clazz;
+ return addToClassMap(classKey, () -> newInstance(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);
@@ -152,4 +152,46 @@ public class DefaultFactoryFinder implements FactoryFinder {
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, (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);
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/camel/blob/bb224ecb/camel-core/src/test/java/org/apache/camel/impl/DefaultFactoryFinderTest.java
----------------------------------------------------------------------
diff --git a/camel-core/src/test/java/org/apache/camel/impl/DefaultFactoryFinderTest.java b/camel-core/src/test/java/org/apache/camel/impl/DefaultFactoryFinderTest.java
index 1d95049..2d36c77 100644
--- a/camel-core/src/test/java/org/apache/camel/impl/DefaultFactoryFinderTest.java
+++ b/camel-core/src/test/java/org/apache/camel/impl/DefaultFactoryFinderTest.java
@@ -19,8 +19,6 @@ package org.apache.camel.impl;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.URL;
-import java.util.Arrays;
-import java.util.Collections;
import java.util.List;
import org.apache.camel.NoFactoryAvailableException;
@@ -35,7 +33,6 @@ import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.hamcrest.Matchers.matchesPattern;
import static org.hamcrest.core.IsCollectionContaining.hasItem;
-import static org.hamcrest.core.IsCollectionContaining.hasItems;
import static org.hamcrest.core.IsInstanceOf.instanceOf;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
@@ -158,7 +155,7 @@ public class DefaultFactoryFinderTest {
@Test
public void shouldFindSingleClassFromClassMap() throws ClassNotFoundException, IOException {
final DefaultFactoryFinder factoryFinder = new DefaultFactoryFinder(null, null);
- factoryFinder.classMap.putIfAbsent("prefixkey", TestImplA.class);
+ factoryFinder.addToClassMap("prefixkey", () -> TestImplA.class);
final Class<?> clazz = factoryFinder.findClass("key", "prefix");
http://git-wip-us.apache.org/repos/asf/camel/blob/bb224ecb/components/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiFactoryFinder.java
----------------------------------------------------------------------
diff --git a/components/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiFactoryFinder.java b/components/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiFactoryFinder.java
index b12cf71..d28f332 100644
--- a/components/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiFactoryFinder.java
+++ b/components/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiFactoryFinder.java
@@ -45,12 +45,10 @@ public class OsgiFactoryFinder extends DefaultFactoryFinder {
@Override
public Class<?> findClass(String key, String propertyPrefix, Class<?> checkClass) throws ClassNotFoundException, IOException {
- if (propertyPrefix == null) {
- propertyPrefix = "";
- }
+ final String prefix = propertyPrefix != null ? propertyPrefix : "";
+ final String classKey = propertyPrefix + key;
- Class<?> clazz = classMap.get(propertyPrefix + key);
- if (clazz == null) {
+ return addToClassMap(classKey, () -> {
BundleEntry entry = getResource(key, checkClass);
if (entry != null) {
URL url = entry.url;
@@ -61,22 +59,19 @@ public class OsgiFactoryFinder extends DefaultFactoryFinder {
reader = IOHelper.buffered(in);
Properties properties = new Properties();
properties.load(reader);
- String className = properties.getProperty(propertyPrefix + "class");
+ String className = properties.getProperty(prefix + "class");
if (className == null) {
- throw new IOException("Expected property is missing: " + propertyPrefix + "class");
+ throw new IOException("Expected property is missing: " + prefix + "class");
}
- clazz = entry.bundle.loadClass(className);
- classMap.put(propertyPrefix + key, clazz);
+ return entry.bundle.loadClass(className);
} finally {
IOHelper.close(reader, key, null);
IOHelper.close(in, key, null);
}
} else {
- throw new NoFactoryAvailableException(propertyPrefix + key);
- }
- }
-
- return clazz;
+ throw new NoFactoryAvailableException(classKey);
+ }
+ });
}
@Override
@@ -101,7 +96,7 @@ public class OsgiFactoryFinder extends DefaultFactoryFinder {
URL url;
for (Bundle bundle : bundles) {
url = bundle.getEntry(getResourcePath() + name);
- if (url != null && checkCompat(bundle, clazz)) {
+ if (url != null && checkCompatibility(bundle, clazz)) {
entry = new BundleEntry();
entry.url = url;
entry.bundle = bundle;
@@ -112,7 +107,7 @@ public class OsgiFactoryFinder extends DefaultFactoryFinder {
return entry;
}
- private boolean checkCompat(Bundle bundle, Class<?> clazz) {
+ private boolean checkCompatibility(Bundle bundle, Class<?> clazz) {
if (clazz == null) {
return true;
}