This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/camel.git
commit f4a16bcc530634cd78520421d970cc65e713ac8b Author: Claus Ibsen <claus.ib...@gmail.com> AuthorDate: Mon Jun 17 09:58:34 2019 +0200 CAMEL-13647: Allow to do autowrire by classpath. Quick and dirty prototype. --- .../apache/camel/support/MyBarImplementation.java | 43 ----- .../org/apache/camel/support/MyBarInterface.java | 29 --- ...ropertyBindingSupportAutowireClasspathTest.java | 64 ------- .../camel/support/PropertyBindingSupport.java | 202 --------------------- 4 files changed, 338 deletions(-) diff --git a/core/camel-core/src/test/java/org/apache/camel/support/MyBarImplementation.java b/core/camel-core/src/test/java/org/apache/camel/support/MyBarImplementation.java deleted file mode 100644 index 2a91dec..0000000 --- a/core/camel-core/src/test/java/org/apache/camel/support/MyBarImplementation.java +++ /dev/null @@ -1,43 +0,0 @@ -/** - * 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 - * <p> - * http://www.apache.org/licenses/LICENSE-2.0 - * <p> - * 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.support; - -public class MyBarImplementation implements MyBarInterface { - - private String name; - private String city; - - @Override - public String getName() { - return name; - } - - @Override - public void setName(String name) { - this.name = name; - } - - @Override - public String getCity() { - return city; - } - - @Override - public void setCity(String city) { - this.city = city; - } -} diff --git a/core/camel-core/src/test/java/org/apache/camel/support/MyBarInterface.java b/core/camel-core/src/test/java/org/apache/camel/support/MyBarInterface.java deleted file mode 100644 index 5813eaa..0000000 --- a/core/camel-core/src/test/java/org/apache/camel/support/MyBarInterface.java +++ /dev/null @@ -1,29 +0,0 @@ -/** - * 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 - * <p> - * http://www.apache.org/licenses/LICENSE-2.0 - * <p> - * 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.support; - -public interface MyBarInterface { - - void setName(String name); - - String getName(); - - void setCity(String city); - - String getCity(); - -} diff --git a/core/camel-core/src/test/java/org/apache/camel/support/PropertyBindingSupportAutowireClasspathTest.java b/core/camel-core/src/test/java/org/apache/camel/support/PropertyBindingSupportAutowireClasspathTest.java deleted file mode 100644 index d803585..0000000 --- a/core/camel-core/src/test/java/org/apache/camel/support/PropertyBindingSupportAutowireClasspathTest.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * 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.support; - -import org.apache.camel.ContextTestSupport; -import org.junit.Test; - -/** - * Unit test for PropertyBindingSupport - */ -public class PropertyBindingSupportAutowireClasspathTest extends ContextTestSupport { - - @Test - public void testAutowireProperties() throws Exception { - Foo foo = new Foo(); - - PropertyBindingSupport.bindProperty(context, foo, "name", "James"); - PropertyBindingSupport.autowireInterfacePropertiesFromClasspath(context, foo); - PropertyBindingSupport.bindProperty(context, foo, "my-bar.name", "Thirsty Bear"); - PropertyBindingSupport.bindProperty(context, foo, "my-bar.city", "San Francisco"); - - assertEquals("James", foo.getName()); - assertEquals("Thirsty Bear", foo.getMyBar().getName()); - assertEquals("San Francisco", foo.getMyBar().getCity()); - } - - public static class Foo { - private String name; - private MyBarInterface myBar; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public MyBarInterface getMyBar() { - return myBar; - } - - public void setMyBar(MyBarInterface myBar) { - this.myBar = myBar; - } - } - - -} - diff --git a/core/camel-support/src/main/java/org/apache/camel/support/PropertyBindingSupport.java b/core/camel-support/src/main/java/org/apache/camel/support/PropertyBindingSupport.java index a4367d0..94a425e 100644 --- a/core/camel-support/src/main/java/org/apache/camel/support/PropertyBindingSupport.java +++ b/core/camel-support/src/main/java/org/apache/camel/support/PropertyBindingSupport.java @@ -16,8 +16,6 @@ */ package org.apache.camel.support; -import java.io.File; -import java.io.IOException; import java.lang.reflect.Method; import java.util.HashSet; import java.util.Iterator; @@ -25,13 +23,9 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; -import java.util.TreeSet; -import java.util.jar.JarFile; import org.apache.camel.CamelContext; -import org.apache.camel.ExtendedCamelContext; import org.apache.camel.PropertyBindingException; -import org.apache.camel.spi.PackageScanClassResolver; import static org.apache.camel.support.IntrospectionSupport.findSetterMethods; import static org.apache.camel.util.ObjectHelper.isNotEmpty; @@ -277,133 +271,6 @@ public final class PropertyBindingSupport { } /** - * This will discover all the properties on the target which are interfaces, and automatic attempt to bind the properties that are null by - * doing classpath scanning to find if there is a just only one class that implements the interface, and then attempt to create a new instance - * of this class. This is used for convention over configuration to automatic configure resources such as DataSource, Amazon Logins and - * so on. - * - * @param camelContext the camel context - * @param target the target object - * @return true if one ore more properties was auto wired - */ - @Deprecated - public static boolean autowireInterfacePropertiesFromClasspath(CamelContext camelContext, Object target) { - return autowireInterfacePropertiesFromClasspath(camelContext, target, false, false, null); - } - - /** - * This will discover all the properties on the target which are interfaces, and automatic attempt to bind the properties that are null by - * doing classpath scanning to find if there is a just only one class that implements the interface, and then attempt to create a new instance - * of this class. This is used for convention over configuration to automatic configure resources such as DataSource, Amazon Logins and - * so on. - * - * @param camelContext the camel context - * @param target the target object - * @param bindNullOnly whether to only autowire if the property has no default value or has not been configured explicit - * @param deepNesting whether to attempt to walk as deep down the object graph by creating new empty objects on the way if needed (Camel can only create - * new empty objects if they have a default no-arg constructor, also mind that this may lead to creating many empty objects, even - * if they will not have any objects autowired from the registry, so use this with caution) - * @param callback optional callback when a property was auto wired - * @return true if one ore more properties was auto wired - */ - @Deprecated - public static boolean autowireInterfacePropertiesFromClasspath(CamelContext camelContext, Object target, - boolean bindNullOnly, boolean deepNesting, OnAutowiring callback) { - try { - if (target != null) { - Set<Object> parents = new HashSet<>(); - return doAutowireInterfacePropertiesFromClasspath(camelContext, target, parents, bindNullOnly, deepNesting, callback); - } - } catch (Exception e) { - throw new PropertyBindingException(target, e); - } - - return false; - } - - @Deprecated - private static boolean doAutowireInterfacePropertiesFromClasspath(CamelContext camelContext, Object target, Set<Object> parents, - boolean bindNullOnly, boolean deepNesting, OnAutowiring callback) throws Exception { - - Map<String, Object> properties = new LinkedHashMap<>(); - IntrospectionSupport.getProperties(target, properties, null); - - boolean hit = false; - - for (Map.Entry<String, Object> entry : properties.entrySet()) { - String key = entry.getKey(); - Object value = entry.getValue(); - Class<?> type = getGetterType(target, key); - - boolean skip = parents.contains(value) || value instanceof CamelContext; - if (skip) { - // we have already covered this as parent of parents so dont walk down this as we want to avoid - // circular dependencies when walking the OGNL graph, also we dont want to walk down CamelContext - continue; - } - - if (isComplexUserType(type) && isInterface(type)) { - // if the property has not been set and its a complex type (not simple or string etc) - if (!bindNullOnly || value == null) { - // do classpath scanning (TODO: do this only once) - Set<String> packageNames = findAllPackageNames(null); - if (!packageNames.isEmpty()) { - String[] packages = packageNames.toArray(new String[packageNames.size()]); - - PackageScanClassResolver resolver = camelContext.adapt(ExtendedCamelContext.class).getPackageScanClassResolver(); - Set<Class<?>> classes = resolver.findByFilter( - c -> !c.isInterface() && type.isAssignableFrom(c), - packages); - - if (classes.size() == 1) { - Class<?> clazz = classes.iterator().next(); - try { - value = camelContext.getInjector().newInstance(clazz); - } catch (Throwable e) { - // ignore - } - if (value != null) { - hit |= IntrospectionSupport.setProperty(camelContext, target, key, value); - if (hit && callback != null) { - callback.onAutowire(target, key, type, value); - } - } - } - } - } - - // attempt to create new instances to walk down the tree if its null (deepNesting option) - if (value == null && deepNesting) { - // okay is there a setter so we can create a new instance and set it automatic - Method method = findBestSetterMethod(target.getClass(), key, true, true); - if (method != null) { - Class<?> parameterType = method.getParameterTypes()[0]; - if (parameterType != null && org.apache.camel.util.ObjectHelper.hasDefaultPublicNoArgConstructor(parameterType)) { - Object instance = camelContext.getInjector().newInstance(parameterType); - if (instance != null) { - org.apache.camel.support.ObjectHelper.invokeMethod(method, target, instance); - target = instance; - // remember this as parent and also autowire nested properties - // do not walk down if it point to our-selves (circular reference) - parents.add(target); - value = instance; - hit |= doAutowireInterfacePropertiesFromClasspath(camelContext, value, parents, bindNullOnly, deepNesting, callback); - } - } - } - } else if (value != null) { - // remember this as parent and also autowire nested properties - // do not walk down if it point to our-selves (circular reference) - parents.add(target); - hit |= doAutowireInterfacePropertiesFromClasspath(camelContext, value, parents, bindNullOnly, deepNesting, callback); - } - } - } - - return hit; - } - - /** * Binds the properties to the target object, and removes the property that was bound from properties. * * @param camelContext the camel context @@ -773,74 +640,5 @@ public final class PropertyBindingSupport { return parameter != null && parameter.trim().startsWith("#"); } - // TODO: move this to some util class - @Deprecated - public static Set<String> findAllPackageNames(ClassLoader loader) throws IOException { - Set<String> answer = new TreeSet<>(); - - // get all JARs on classpath - String cp = System.getProperty("java.class.path"); - String[] parts = cp.split(":"); - for (String p : parts) { - if (p.endsWith(".jar")) { - JarFile jar = new JarFile(p); - jar.stream().forEach(e -> { - if (e.isDirectory()) { - String name = e.getName(); - name = name.replace('/', '.'); - name = name.replace('\\', '.'); - if (name.endsWith(".")) { - name = name.substring(0, name.length() - 1); - } - if (validName(name)) { - answer.add(name); - } - } - }); - } else { - // its a directory such as target, then traverse and find all directory - gatherAllDirectories(new File(p), "", answer); - } - } - - return answer; - } - - @Deprecated - public static boolean validName(String name) { - boolean invalid = name.startsWith("META-INF") || name.startsWith("java") || name.startsWith("jdk") || name.startsWith("netscape") - || name.startsWith("resources") || name.startsWith("toolbarButtonGraphics") - || name.startsWith("oracle") || name.startsWith("sun") || name.startsWith("com.sun") || name.startsWith("com.oracle"); - return !invalid; - } - - @Deprecated - public static boolean validPackageForClassloader(String packageName, ClassLoader loader) throws IOException { - return loader.getResources(packageName) != null; - } - - @Deprecated - public static void gatherAllDirectories(File path, String root, Set<String> dirs) { - if (path == null) { - return; - } - File[] paths = path.listFiles(f -> f.isDirectory()); - if (paths != null) { - for (File dir : paths) { - String name = root + (root.isEmpty() ? "" : ".") + dir.getName(); - name = name.replace('/', '.'); - name = name.replace('\\', '.'); - if (name.endsWith(".")) { - name = name.substring(0, name.length() - 1); - } - - if (validName(name)) { - dirs.add(name); - String subRoot = root + (root.isEmpty() ? "" : ".") + dir.getName(); - gatherAllDirectories(dir, subRoot, dirs); - } - } - } - } }