CAMEL-10060: Added fat-jar aware package scan class resolver
Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/cbe8c326 Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/cbe8c326 Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/cbe8c326 Branch: refs/heads/camel-2.17.x Commit: cbe8c3268058b54b855b5490cedc5ab4b61cd5db Parents: 33048a8 Author: Nicola Ferraro <[email protected]> Authored: Thu Jun 16 23:37:22 2016 +0200 Committer: Claus Ibsen <[email protected]> Committed: Tue Jun 21 08:44:48 2016 +0200 ---------------------------------------------------------------------- .../impl/DefaultPackageScanClassResolver.java | 2 +- .../spring/boot/CamelAutoConfiguration.java | 2 + .../boot/FatJarPackageScanClassResolver.java | 83 ++++++++++++++++++++ 3 files changed, 86 insertions(+), 1 deletion(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/cbe8c326/camel-core/src/main/java/org/apache/camel/impl/DefaultPackageScanClassResolver.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/impl/DefaultPackageScanClassResolver.java b/camel-core/src/main/java/org/apache/camel/impl/DefaultPackageScanClassResolver.java index aba0330..6390e27 100644 --- a/camel-core/src/main/java/org/apache/camel/impl/DefaultPackageScanClassResolver.java +++ b/camel-core/src/main/java/org/apache/camel/impl/DefaultPackageScanClassResolver.java @@ -417,7 +417,7 @@ public class DefaultPackageScanClassResolver extends ServiceSupport implements P * @param urlPath the url of the jar file to be examined for classes * @return all the .class entries from the JAR */ - private List<String> doLoadJarClassEntries(InputStream stream, String urlPath) { + protected List<String> doLoadJarClassEntries(InputStream stream, String urlPath) { List<String> entries = new ArrayList<String>(); JarInputStream jarStream = null; http://git-wip-us.apache.org/repos/asf/camel/blob/cbe8c326/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelAutoConfiguration.java ---------------------------------------------------------------------- diff --git a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelAutoConfiguration.java b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelAutoConfiguration.java index 771ff27..1385968 100644 --- a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelAutoConfiguration.java +++ b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelAutoConfiguration.java @@ -76,6 +76,8 @@ public class CamelAutoConfiguration { camelContext.getManagementStrategy().getManagementAgent().setCreateConnector(config.isJmxCreateConnector()); } + camelContext.setPackageScanClassResolver(new FatJarPackageScanClassResolver()); + return camelContext; } http://git-wip-us.apache.org/repos/asf/camel/blob/cbe8c326/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/FatJarPackageScanClassResolver.java ---------------------------------------------------------------------- diff --git a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/FatJarPackageScanClassResolver.java b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/FatJarPackageScanClassResolver.java new file mode 100644 index 0000000..e435b7a --- /dev/null +++ b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/FatJarPackageScanClassResolver.java @@ -0,0 +1,83 @@ +/** + * 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.spring.boot; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.jar.JarEntry; +import java.util.jar.JarInputStream; + +import org.apache.camel.impl.DefaultPackageScanClassResolver; +import org.apache.camel.util.IOHelper; + +/** + * An implementation of the {@code org.apache.camel.spi.PackageScanClassResolver} that is able to + * scan spring-boot fat jars to find classes contained also in nested jars. + */ +public class FatJarPackageScanClassResolver extends DefaultPackageScanClassResolver { + + /** + * Loads all the class entries from the main JAR and all nested jars. + * + * @param stream the inputstream of the jar file to be examined for classes + * @param urlPath the url of the jar file to be examined for classes + * @return all the .class entries from the main JAR and all nested jars + */ + @Override + protected List<String> doLoadJarClassEntries(InputStream stream, String urlPath) { + return doLoadJarClassEntries(stream, urlPath, true, true); + } + + protected List<String> doLoadJarClassEntries(InputStream stream, String urlPath, boolean inspectNestedJars, boolean closeStream) { + List<String> entries = new ArrayList<String>(); + + JarInputStream jarStream = null; + try { + jarStream = new JarInputStream(stream); + + JarEntry entry; + while ((entry = jarStream.getNextJarEntry()) != null) { + String name = entry.getName(); + + if (name != null) { + name = name.trim(); + if (!entry.isDirectory() && name.endsWith(".class")) { + entries.add(name); + } else if (inspectNestedJars && !entry.isDirectory() && name.startsWith("lib/") && name.endsWith(".jar")) { + String nestedUrl = urlPath + "!/" + name; + log.trace("Inspecting nested jar: {}", nestedUrl); + + List<String> nestedEntries = doLoadJarClassEntries(jarStream, nestedUrl, false, false); + entries.addAll(nestedEntries); + } + } + } + } catch (IOException ioe) { + log.warn("Cannot search jar file '" + urlPath + " due to an IOException: " + ioe.getMessage(), ioe); + } finally { + if (closeStream) { + // stream is left open when scanning nested jars, otherwise the fat jar stream gets closed + IOHelper.close(jarStream, urlPath, log); + } + } + + return entries; + } + +}
