You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2022/10/20 08:26:44 UTC
[camel] branch main updated: CAMEL-18624: camel-jbang - Should load custom type converters when adding new JARs
This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push:
new 8bdf3833361 CAMEL-18624: camel-jbang - Should load custom type converters when adding new JARs
8bdf3833361 is described below
commit 8bdf383336129c9cc3df8d691bea12c78fac181d
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Thu Oct 20 10:26:02 2022 +0200
CAMEL-18624: camel-jbang - Should load custom type converters when adding new JARs
---
.../java/org/apache/camel/main/KameletMain.java | 8 +-
.../main/download/ArtifactDownloadListener.java | 34 +++++++
.../camel/main/download/DependencyDownloader.java | 5 +
.../main/download/MavenDependencyDownloader.java | 11 +++
.../TypeConverterLoaderDownloadListener.java | 105 +++++++++++++++++++++
5 files changed, 162 insertions(+), 1 deletion(-)
diff --git a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/KameletMain.java b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/KameletMain.java
index 0a20be32185..204ea84733b 100644
--- a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/KameletMain.java
+++ b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/KameletMain.java
@@ -43,6 +43,7 @@ import org.apache.camel.main.download.DownloadListener;
import org.apache.camel.main.download.KameletMainInjector;
import org.apache.camel.main.download.KnownDependenciesResolver;
import org.apache.camel.main.download.MavenDependencyDownloader;
+import org.apache.camel.main.download.TypeConverterLoaderDownloadListener;
import org.apache.camel.main.http.VertxHttpServer;
import org.apache.camel.main.injection.AnnotationDependencyInjection;
import org.apache.camel.main.util.ExtraFilesClassLoader;
@@ -299,9 +300,13 @@ public class KameletMain extends MainCommandLineSupport {
DefaultCamelContext answer = new DefaultCamelContext(false);
answer.setLogJvmUptime(true);
if (download) {
- answer.setApplicationContextClassLoader(createApplicationContextClassLoader());
+ ClassLoader dynamicCL = createApplicationContextClassLoader();
+ answer.setApplicationContextClassLoader(dynamicCL);
+ answer.getPackageScanClassResolver().addClassLoader(dynamicCL);
+ answer.getPackageScanResourceResolver().addClassLoader(dynamicCL);
MavenDependencyDownloader downloader = new MavenDependencyDownloader();
+ downloader.setClassLoader(dynamicCL);
downloader.setCamelContext(answer);
downloader.setRepos(repos);
downloader.setFresh(fresh);
@@ -311,6 +316,7 @@ public class KameletMain extends MainCommandLineSupport {
downloader.addDownloadListener(downloadListener);
}
downloader.addDownloadListener(new AutoConfigureDownloadListener());
+ downloader.addArtifactDownloadListener(new TypeConverterLoaderDownloadListener());
// register as extension
try {
diff --git a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/ArtifactDownloadListener.java b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/ArtifactDownloadListener.java
new file mode 100644
index 00000000000..619bccbc0b2
--- /dev/null
+++ b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/ArtifactDownloadListener.java
@@ -0,0 +1,34 @@
+/*
+ * 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.main.download;
+
+import java.io.File;
+
+/**
+ * Listener for downloading a maven file (can be downloaded from a local cache)
+ */
+@FunctionalInterface
+public interface ArtifactDownloadListener {
+
+ /**
+ * After the artifact has been downloaded
+ *
+ * @param file the downloaded artifact as a file
+ */
+ void onDownloadedFile(File file);
+
+}
diff --git a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/DependencyDownloader.java b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/DependencyDownloader.java
index a7cc346329c..9296d653da2 100644
--- a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/DependencyDownloader.java
+++ b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/DependencyDownloader.java
@@ -39,6 +39,11 @@ public interface DependencyDownloader extends CamelContextAware, StaticService {
*/
void addDownloadListener(DownloadListener downloadListener);
+ /**
+ * Adds a listener to capture download activity
+ */
+ void addArtifactDownloadListener(ArtifactDownloadListener downloadListener);
+
String getRepos();
/**
diff --git a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/MavenDependencyDownloader.java b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/MavenDependencyDownloader.java
index c60c2b95793..53b48ffba5a 100644
--- a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/MavenDependencyDownloader.java
+++ b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/MavenDependencyDownloader.java
@@ -220,6 +220,7 @@ public class MavenDependencyDownloader extends ServiceSupport implements Depende
private ClassLoader classLoader;
private CamelContext camelContext;
private final Set<DownloadListener> downloadListeners = new LinkedHashSet<>();
+ private final Set<ArtifactDownloadListener> artifactDownloadListeners = new LinkedHashSet<>();
// repository URLs set from "camel.jbang.repos" property or --repos option.
private String repos;
@@ -258,6 +259,12 @@ public class MavenDependencyDownloader extends ServiceSupport implements Depende
downloadListeners.add(downloadListener);
}
+ @Override
+ public void addArtifactDownloadListener(ArtifactDownloadListener downloadListener) {
+ CamelContextAware.trySetCamelContext(downloadListener, getCamelContext());
+ artifactDownloadListeners.add(downloadListener);
+ }
+
@Override
public String getRepos() {
return repos;
@@ -367,6 +374,10 @@ public class MavenDependencyDownloader extends ServiceSupport implements Depende
DependencyDownloaderClassLoader ddc = (DependencyDownloaderClassLoader) classLoader;
ddc.addFile(file);
}
+ // trigger listener after downloaded and added to classloader
+ for (ArtifactDownloadListener listener : artifactDownloadListeners) {
+ listener.onDownloadedFile(file);
+ }
LOG.trace("Added classpath: {}", a.getGav());
}
}
diff --git a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/TypeConverterLoaderDownloadListener.java b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/TypeConverterLoaderDownloadListener.java
new file mode 100644
index 00000000000..a713f562fc4
--- /dev/null
+++ b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/TypeConverterLoaderDownloadListener.java
@@ -0,0 +1,105 @@
+/*
+ * 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.main.download;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.CamelContextAware;
+import org.apache.camel.impl.converter.BaseTypeConverterRegistry;
+import org.apache.camel.spi.TypeConverterLoader;
+import org.apache.camel.util.IOHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class TypeConverterLoaderDownloadListener implements ArtifactDownloadListener, CamelContextAware {
+
+ private static final Logger LOG = LoggerFactory.getLogger(TypeConverterLoaderDownloadListener.class);
+
+ private CamelContext camelContext;
+
+ @Override
+ public CamelContext getCamelContext() {
+ return camelContext;
+ }
+
+ @Override
+ public void setCamelContext(CamelContext camelContext) {
+ this.camelContext = camelContext;
+ }
+
+ @Override
+ public void onDownloadedFile(File file) {
+ try {
+ loadTypeConverters(file);
+ } catch (Exception e) {
+ // ignore
+ }
+ }
+
+ protected void loadTypeConverters(File file) throws Exception {
+ // use isolated classloader to load the service file as we only want to check this file
+ // (and not what is already in the existing classloader)
+ DependencyDownloaderClassLoader cl = new DependencyDownloaderClassLoader(null);
+ cl.addFile(file);
+
+ // load names for custom type converters from the downloaded JAR
+ Collection<String> loaders = new ArrayList<>();
+ findTypeConverterLoaderClasses(loaders,
+ cl.getResourceAsStream(BaseTypeConverterRegistry.META_INF_SERVICES_TYPE_CONVERTER_LOADER));
+ findTypeConverterLoaderClasses(loaders,
+ cl.getResourceAsStream(BaseTypeConverterRegistry.META_INF_SERVICES_FALLBACK_TYPE_CONVERTER));
+ loadTypeConverters(loaders);
+ }
+
+ protected void findTypeConverterLoaderClasses(Collection<String> loaders, InputStream is) throws IOException {
+ if (is != null) {
+ BufferedReader reader = IOHelper.buffered(new InputStreamReader(is, StandardCharsets.UTF_8));
+ String line;
+ do {
+ line = reader.readLine();
+ if (line != null && !line.startsWith("#") && !line.isEmpty()) {
+ loaders.add(line);
+ }
+ } while (line != null);
+ IOHelper.close(reader);
+ }
+ }
+
+ protected void loadTypeConverters(Collection<String> loaders) throws ClassNotFoundException {
+ for (String name : loaders) {
+ LOG.debug("Resolving TypeConverterLoader: {}", name);
+ Class<?> clazz = getCamelContext().getClassResolver().resolveMandatoryClass(name);
+ Object obj = getCamelContext().getInjector().newInstance(clazz, false);
+ CamelContextAware.trySetCamelContext(obj, getCamelContext());
+ if (obj instanceof TypeConverterLoader) {
+ TypeConverterLoader loader = (TypeConverterLoader) obj;
+ CamelContextAware.trySetCamelContext(loader, getCamelContext());
+ LOG.debug("TypeConverterLoader: {} loading converters", name);
+ loader.load(getCamelContext().getTypeConverterRegistry());
+ }
+ }
+ }
+
+}