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 <[email protected]>
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());
+ }
+ }
+ }
+
+}