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 2cf92c29193 Run gav (#10991) 2cf92c29193 is described below commit 2cf92c291932f5dc69f40b2e5036562b2ec6e3ee Author: Claus Ibsen <claus.ib...@gmail.com> AuthorDate: Fri Aug 4 06:33:35 2023 +0200 Run gav (#10991) CAMEL-19710: camel-jbang - Run should compile java to default package if project has GAV --- .../camel/dsl/support/DefaultSourceLoader.java | 60 +++++++++++++++++++++ .../dsl/support/RouteBuilderLoaderSupport.java | 37 +++---------- .../org/apache/camel/dsl/support/SourceLoader.java | 41 ++++++++++++++ .../apache/camel/dsl/jbang/core/commands/Run.java | 8 +++ .../java/org/apache/camel/main/KameletMain.java | 15 ++++++ .../main/download/PackageNameSourceLoader.java | 63 ++++++++++++++++++++++ 6 files changed, 194 insertions(+), 30 deletions(-) diff --git a/dsl/camel-dsl-support/src/main/java/org/apache/camel/dsl/support/DefaultSourceLoader.java b/dsl/camel-dsl-support/src/main/java/org/apache/camel/dsl/support/DefaultSourceLoader.java new file mode 100644 index 00000000000..f588b449801 --- /dev/null +++ b/dsl/camel-dsl-support/src/main/java/org/apache/camel/dsl/support/DefaultSourceLoader.java @@ -0,0 +1,60 @@ +/* + * 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.dsl.support; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; + +import org.apache.camel.spi.Resource; +import org.apache.camel.util.IOHelper; + +/** + * Default {@link SourceLoader}. + */ +public class DefaultSourceLoader implements SourceLoader { + + @Override + public String loadResource(Resource resource) throws IOException { + InputStream in = resource.getInputStream(); + + StringBuilder builder = new StringBuilder(); + InputStreamReader isr = new InputStreamReader(in); + boolean first = true; + try { + BufferedReader reader = IOHelper.buffered(isr); + while (true) { + String line = reader.readLine(); + if (line != null) { + // we need to skip first line if it starts with a special script marker for camel-jbang in pipe mode + if (first && line.startsWith("///usr/bin/env jbang") && line.contains("camel@apache/camel pipe")) { + line = ""; // use an empty line so line numbers still matches + } + builder.append(line); + builder.append("\n"); + first = false; + } else { + break; + } + } + return builder.toString(); + } finally { + IOHelper.close(isr, in); + } + } +} diff --git a/dsl/camel-dsl-support/src/main/java/org/apache/camel/dsl/support/RouteBuilderLoaderSupport.java b/dsl/camel-dsl-support/src/main/java/org/apache/camel/dsl/support/RouteBuilderLoaderSupport.java index 0f714d15590..6ea89eebc72 100644 --- a/dsl/camel-dsl-support/src/main/java/org/apache/camel/dsl/support/RouteBuilderLoaderSupport.java +++ b/dsl/camel-dsl-support/src/main/java/org/apache/camel/dsl/support/RouteBuilderLoaderSupport.java @@ -16,11 +16,9 @@ */ package org.apache.camel.dsl.support; -import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; -import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; @@ -37,7 +35,6 @@ import org.apache.camel.spi.Resource; import org.apache.camel.spi.RoutesBuilderLoader; import org.apache.camel.spi.StartupStepRecorder; import org.apache.camel.support.RoutesBuilderLoaderSupport; -import org.apache.camel.util.IOHelper; /** * Base class for {@link RoutesBuilderLoader} implementations. @@ -46,6 +43,7 @@ public abstract class RouteBuilderLoaderSupport extends RoutesBuilderLoaderSuppo private final String extension; private final List<CompilePostProcessor> compilePostProcessors = new ArrayList<>(); private StartupStepRecorder recorder; + private SourceLoader sourceLoader = new DefaultSourceLoader(); protected RouteBuilderLoaderSupport(String extension) { this.extension = extension; @@ -93,6 +91,11 @@ public abstract class RouteBuilderLoaderSupport extends RoutesBuilderLoaderSuppo addCompilePostProcessor(pre); } } + // discover a special source loader to be used + SourceLoader sl = getCamelContext().getRegistry().findSingleByType(SourceLoader.class); + if (sl != null) { + this.sourceLoader = sl; + } } } @@ -129,7 +132,7 @@ public abstract class RouteBuilderLoaderSupport extends RoutesBuilderLoaderSuppo */ protected InputStream resourceInputStream(Resource resource) throws IOException { // load into memory as we need to skip a specific first-line if present - String data = loadResource(resource.getInputStream()); + String data = sourceLoader.loadResource(resource); if (data.trim().isEmpty()) { throw new IOException("Resource is empty: " + resource.getLocation()); } @@ -144,30 +147,4 @@ public abstract class RouteBuilderLoaderSupport extends RoutesBuilderLoaderSuppo */ protected abstract RouteBuilder doLoadRouteBuilder(Resource resource) throws Exception; - private static String loadResource(InputStream in) throws IOException { - StringBuilder builder = new StringBuilder(); - InputStreamReader isr = new InputStreamReader(in); - boolean first = true; - try { - BufferedReader reader = IOHelper.buffered(isr); - while (true) { - String line = reader.readLine(); - if (line != null) { - // we need to skip first line if it starts with a special script marker for camel-jbang in pipe mode - if (first && line.startsWith("///usr/bin/env jbang") && line.contains("camel@apache/camel pipe")) { - line = ""; // use an empty line so line numbers still matches - } - builder.append(line); - builder.append("\n"); - first = false; - } else { - break; - } - } - return builder.toString(); - } finally { - IOHelper.close(isr, in); - } - } - } diff --git a/dsl/camel-dsl-support/src/main/java/org/apache/camel/dsl/support/SourceLoader.java b/dsl/camel-dsl-support/src/main/java/org/apache/camel/dsl/support/SourceLoader.java new file mode 100644 index 00000000000..29e003c5d9f --- /dev/null +++ b/dsl/camel-dsl-support/src/main/java/org/apache/camel/dsl/support/SourceLoader.java @@ -0,0 +1,41 @@ +/* + * 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.dsl.support; + +import java.io.IOException; + +import org.apache.camel.spi.Resource; + +/** + * Loader for loading the source code from {@link Resource}. + * + * Custom {@link SourceLoader} implementations can be plugged into the {@link org.apache.camel.CamelContext} by adding + * to the {@link org.apache.camel.spi.Registry}. + */ +public interface SourceLoader { + + /** + * Loads the source from the given resource + * + * @param resource the resource + * @return the source code (such as java, xml, groovy, yaml) + * + * @throws IOException is thrown if error loading the source + */ + String loadResource(Resource resource) throws IOException; + +} diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java index 309fc9efe3d..e8f0ca92555 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java @@ -141,6 +141,9 @@ public class Run extends CamelCommand { description = "Additional maven repositories for download on-demand (Use commas to separate multiple repositories)") String repos; + @Option(names = { "--gav" }, description = "The Maven group:artifact:version (used during exporting)") + String gav; + @Option(names = { "--maven-settings" }, description = "Optional location of maven setting.xml file to configure servers, repositories, mirrors and proxies." + @@ -376,6 +379,10 @@ public class Run extends CamelCommand { if (modeline) { writeSetting(main, profileProperties, "camel.main.modeline", "true"); } + + if (gav != null) { + writeSetting(main, profileProperties, "camel.jbang.gav", gav); + } writeSetting(main, profileProperties, "camel.jbang.open-api", openapi); writeSetting(main, profileProperties, "camel.jbang.repos", repos); writeSetting(main, profileProperties, "camel.jbang.health", health ? "true" : "false"); @@ -678,6 +685,7 @@ public class Run extends CamelCommand { download = "true".equals(answer.getProperty("camel.jbang.download", download ? "true" : "false")); background = "true".equals(answer.getProperty("camel.jbang.background", background ? "true" : "false")); camelVersion = answer.getProperty("camel.jbang.camel-version", camelVersion); + gav = answer.getProperty("camel.jbang.gav", gav); } return answer; } 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 14d2f4cc50b..a6c4580f7d9 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 @@ -36,6 +36,7 @@ import org.apache.camel.CamelContext; import org.apache.camel.ManagementStatisticsLevel; import org.apache.camel.ProducerTemplate; import org.apache.camel.RuntimeCamelException; +import org.apache.camel.dsl.support.SourceLoader; import org.apache.camel.impl.DefaultCamelContext; import org.apache.camel.main.download.AutoConfigureDownloadListener; import org.apache.camel.main.download.BasePackageScanDownloadListener; @@ -59,6 +60,7 @@ import org.apache.camel.main.download.KameletMainInjector; import org.apache.camel.main.download.KnownDependenciesResolver; import org.apache.camel.main.download.KnownReposResolver; import org.apache.camel.main.download.MavenDependencyDownloader; +import org.apache.camel.main.download.PackageNameSourceLoader; import org.apache.camel.main.download.TypeConverterLoaderDownloadListener; import org.apache.camel.main.injection.AnnotationDependencyInjection; import org.apache.camel.main.util.ExtraFilesClassLoader; @@ -79,6 +81,7 @@ import org.apache.camel.support.DefaultContextReloadStrategy; import org.apache.camel.support.PluginHelper; import org.apache.camel.support.RouteOnDemandReloadStrategy; import org.apache.camel.support.service.ServiceHelper; +import org.apache.camel.tooling.maven.MavenGav; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.CannotLoadBeanClassException; import org.springframework.beans.factory.SmartFactoryBean; @@ -463,6 +466,18 @@ public class KameletMain extends MainCommandLineSupport { answer.setStartupStepRecorder(recorder); } + // special for source compilation to a specific package based on Maven GAV + String gav = getInitialProperties().getProperty("camel.jbang.gav"); + if (gav != null) { + MavenGav g = MavenGav.parseGav(gav); + if (g.getGroupId() != null && g.getArtifactId() != null) { + // plugin a custom source loader with package name based on GAV + String defaultPackageName = g.getGroupId().replace('-', '.') + "." + g.getArtifactId().replace('-', '.'); + SourceLoader sl = new PackageNameSourceLoader(defaultPackageName); + answer.getRegistry().bind("PackageNameSourceLoader", sl); + } + } + try { // dependencies from CLI Object dependencies = getInitialProperties().get("camel.jbang.dependencies"); diff --git a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/PackageNameSourceLoader.java b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/PackageNameSourceLoader.java new file mode 100644 index 00000000000..915dd6f9cb8 --- /dev/null +++ b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/download/PackageNameSourceLoader.java @@ -0,0 +1,63 @@ +/* + * 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.IOException; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.camel.dsl.support.DefaultSourceLoader; +import org.apache.camel.spi.Resource; + +/** + * {@link org.apache.camel.dsl.support.SourceLoader} that can enrich the source with a package name if the code does not + * have anyone. + */ +public class PackageNameSourceLoader extends DefaultSourceLoader { + + private static final Pattern PACKAGE_PATTERN = Pattern.compile( + "^\\s*package\\s+([a-zA-Z][.\\w]*)\\s*;.*$", Pattern.MULTILINE); + + private final String packageName; + + public PackageNameSourceLoader(String packageName) { + this.packageName = packageName; + } + + @Override + public String loadResource(Resource resource) throws IOException { + String code = super.loadResource(resource); + + // for java source then insert package name in top of file if none exists + String loc = resource.getLocation(); + if (loc != null && loc.endsWith(".java")) { + String pn = determineClassName(code); + if (pn == null) { + // insert default package name in top + // (avoid new-lines so source code lines does not get changed) + code = "package " + packageName + "; " + code; + } + } + return code; + } + + private static String determineClassName(String content) { + Matcher matcher = PACKAGE_PATTERN.matcher(content); + return matcher.find() ? matcher.group(1) : null; + } + +}