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 610d5365740 CAMEL-18151: camel-jbang - Export command for spring boot 610d5365740 is described below commit 610d53657407fe51d72b985868280a4fc017edff Author: Claus Ibsen <claus.ib...@gmail.com> AuthorDate: Tue May 31 10:52:33 2022 +0200 CAMEL-18151: camel-jbang - Export command for spring boot --- .../modules/ROOT/pages/camel-jbang.adoc | 53 +--- .../dsl/jbang/core/commands/CamelJBangMain.java | 4 +- .../core/commands/{Create.java => Export.java} | 18 +- .../dsl/jbang/core/commands/ExportSpringBoot.java | 322 +++++++++++++++++++++ .../camel/dsl/jbang/core/commands/Project.java | 165 ----------- .../apache/camel/dsl/jbang/core/commands/Run.java | 21 +- .../jbang/core/generator/CamelJbangGenerator.java | 33 --- .../dsl/jbang/core/generator/PomDependency.java | 74 ----- .../dsl/jbang/core/generator/PomProperty.java | 43 --- .../dsl/jbang/core/generator/QuarkusGenerator.java | 64 ---- .../core/templates/VelocityTemplateParser.java | 115 -------- .../src/main/resources/generator/quarkus-pom.ftl | 259 ----------------- .../main/resources/templates/spring-boot-main.tmpl | 13 + .../main/resources/templates/spring-boot-pom.tmpl | 84 ++++++ .../main/CommandLineDependencyDownloader.java | 3 +- .../main/DependencyDownloaderClassResolver.java | 3 +- .../DependencyDownloaderComponentResolver.java | 3 +- .../DependencyDownloaderDataFormatResolver.java | 3 +- .../camel/main/DependencyDownloaderKamelet.java | 3 +- .../main/DependencyDownloaderLanguageResolver.java | 3 +- ...ependencyDownloaderPropertyBindingListener.java | 3 +- .../main/DependencyDownloaderRoutesLoader.java | 3 +- .../camel/main/DependencyDownloaderStrategy.java | 2 +- .../org/apache/camel/main/DownloadListener.java | 8 + .../org/apache/camel/main/DownloaderHelper.java | 7 +- 25 files changed, 487 insertions(+), 822 deletions(-) diff --git a/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc b/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc index a44a2e42b4f..654a3bee8bf 100644 --- a/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc +++ b/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc @@ -538,59 +538,30 @@ It is better practice specifying configurations in external files such as `appli You can _export_ your Camel JBang application to a traditional Java based project such as Spring Boot or Quarkus. -=== Create Quarkus Project +You may want to do this after you have built a prototype using Camel JBang, and are in need +of a traditional Java based project with more need for Java coding, or wanting to use the powerful +runtimes of Spring Boot or Quarkus. -NOTE: New implementation on the way +=== Exporting to Camel Spring Boot -The `create project` command can be used to generate a Maven project. After running the integration with the `run` command `create project` will generate a Maven Quarkus project with some required dependencies that can be used as a starting point for complex integrations. +The command `export spring-boot` will export your current Camel JBang file(s) to a Maven based +Spring Boot project with files organized in `src/main/` folder structure. -To execute this feature run: +For example to export to Spring Boot using the Maven groupId _com.foo_ and the artifactId _acme_ +and with version _1.0-SNAPSHOT_ you simply execute: [source,bash] ---- -jbang camel@apache/camel create project integration.java integration.yaml integration.xml +camel export spring-boot --gav=com.foo:acme:1.0-SNAPSHOT ---- -This command generates a folder named CamelJBang that contains the Quarkus project, in order to execute it the following command can be run: +NOTE: This will export to the _current_ directory, meaning that files are moved into the needed folder structure. -[source,bash] ----- -cd CamelJBang -mvn compile quarkus:dev ----- - -The table below lists all the command line options configurable on the `create project` command: - -|=== -|Option |Description - -|name -|The name of the Camel application (artifactId and folder) - -|group-id -|The group ID of the maven project - -|directory -|Directory where the project will be created - -|quarkus-dependency -|Comma separated list of camel-quarkus dependencies - -|quarkus-bom-version -|Override quarkus bom version in pom.xml - -|=== - -==== Examples - -[source,bash] ----- -jbang camel@apache/camel create project TimerRoute.java --quarkusDependencies=camel-quarkus-timer,camel-quarkus-log,camel-quarkus-yaml-dsl,camel-quarkus-http --name=TimerRouteProject ----- +To export to another directly (copies the files) you execute: [source,bash] ---- -jbang camel@apache/camel create project KafkaRoute.java --quarkusDependencies=camel-quarkus-kafka,camel-quarkus-log --name=KafkaRouteProject +camel export spring-boot --gav=com.foo:acme:1.0-SNAPSHOT --dir=../myproject ---- == Troubleshooting diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CamelJBangMain.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CamelJBangMain.java index 5d4b3b13ac0..84976957b85 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CamelJBangMain.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CamelJBangMain.java @@ -45,6 +45,8 @@ public class CamelJBangMain implements Callable<Integer> { .addSubcommand("build", new CommandLine(new Build(main)) .addSubcommand("manifests", new CommandLine(new Manifest(main))) .addSubcommand("image", new CommandLine(new Image(main)))) + .addSubcommand("export", new CommandLine(new Export(main)) + .addSubcommand("spring-boot", new CommandLine(new ExportSpringBoot(main)))) .addSubcommand("deploy", new CommandLine(new Deploy(main))) .addSubcommand("undeploy", new CommandLine(new Undeploy(main))); /* // TODO: do not show commands that are deprecated and to be either removed or reworked @@ -53,8 +55,6 @@ public class CamelJBangMain implements Callable<Integer> { .addSubcommand("components", new SearchComponents()) .addSubcommand("languages", new SearchLanguages()) .addSubcommand("others", new SearchOthers())) - .addSubcommand("create", new CommandLine(new Create()) - .addSubcommand("project", new Project())); */ commandLine.getCommandSpec().versionProvider(() -> { diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Create.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Export.java similarity index 72% rename from dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Create.java rename to dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Export.java index b0d4ce4787d..28d42a4c237 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Create.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Export.java @@ -16,24 +16,20 @@ */ package org.apache.camel.dsl.jbang.core.commands; -import java.util.concurrent.Callable; - import picocli.CommandLine; import picocli.CommandLine.Command; -import picocli.CommandLine.Option; -@Command(name = "create", description = "Creates Maven Project (use --help)") -@Deprecated -class Create implements Callable<Integer> { - //CHECKSTYLE:OFF - @Option(names = { "-h", "--help" }, usageHelp = true, description = "Display the help and sub-commands") - private boolean helpRequested = false; - //CHECKSTYLE:ON +@Command(name = "export", + description = "Export to other runtimes such as Spring Boot or Quarkus (use --help to see sub commands)") +class Export extends CamelCommand { + + public Export(CamelJBangMain main) { + super(main); + } @Override public Integer call() throws Exception { new CommandLine(this).execute("--help"); - return 0; } } diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportSpringBoot.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportSpringBoot.java new file mode 100644 index 00000000000..48e82859d81 --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportSpringBoot.java @@ -0,0 +1,322 @@ +/* + * 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.jbang.core.commands; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; +import java.util.stream.Collectors; + +import org.apache.camel.catalog.CamelCatalog; +import org.apache.camel.catalog.DefaultCamelCatalog; +import org.apache.camel.main.MavenGav; +import org.apache.camel.util.FileUtil; +import org.apache.camel.util.IOHelper; +import org.apache.camel.util.OrderedProperties; +import org.apache.camel.util.StringHelper; +import picocli.CommandLine; + +@CommandLine.Command(name = "spring-boot", description = "Export as Spring Boot project") +class ExportSpringBoot extends CamelCommand { + + private static final String BUILD_DIR = ".camel-jbang/work"; + + private static final String[] SETTINGS_PROP_SOURCE_KEYS = new String[] { + "camel.main.routesIncludePattern", + "camel.component.properties.location", + "camel.component.kamelet.location", + "camel.jbang.classpathFiles" + }; + + @CommandLine.Option(names = { "--gav" }, description = "The Maven group:artifact:version", required = true) + private String gav; + + @CommandLine.Option(names = { "--main-classname" }, + description = "The class name of the Camel Spring Boot application class", + defaultValue = "CamelApplication") + private String mainClassname; + + @CommandLine.Option(names = { "--java-version" }, description = "Java version (11 or 17)", + defaultValue = "11") + private String javaVersion; + + @CommandLine.Option(names = { "--spring-boot-version" }, description = "Spring Boot version", + defaultValue = "2.6.8") + private String springBootVersion; + + @CommandLine.Option(names = { "-dir", "--directory" }, description = "Directory where the project will be exported", + defaultValue = ".") + private String exportDir; + + @CommandLine.Option(names = { "--fresh" }, description = "Make sure we use fresh (i.e. non-cached) resources") + private boolean fresh; + + public ExportSpringBoot(CamelJBangMain main) { + super(main); + } + + @Override + public Integer call() throws Exception { + String[] ids = gav.split(":"); + if (ids.length != 3) { + System.out.println("--gav must be in syntax: groupId:artifactId:version"); + return 1; + } + + File profile = new File(getProfile() + ".properties"); + + // the settings file has information what to export + File settings = new File(Run.WORK_DIR + "/" + Run.RUN_SETTINGS_FILE); + if (fresh || !settings.exists()) { + // allow to automatic build + System.out.println("Generating fresh run data"); + int silent = runSilently(); + if (silent != 0) { + return silent; + } + } else { + System.out.println("Reusing existing run data"); + } + + System.out.println("Exporting as Spring Boot project to: " + exportDir); + + // use a temporary work dir + File buildDir = new File(BUILD_DIR); + FileUtil.removeDir(buildDir); + buildDir.mkdirs(); + + // copy source files + String packageName = ids[0] + "." + ids[1]; + File srcJavaDir = new File(BUILD_DIR, "src/main/java/" + packageName.replace('.', '/')); + srcJavaDir.mkdirs(); + File srcResourcesDir = new File(BUILD_DIR, "src/main/resources"); + srcResourcesDir.mkdirs(); + copySourceFiles(settings, srcJavaDir, srcResourcesDir, packageName); + // copy from settings to profile + copySettingsAndProfile(settings, profile, srcResourcesDir); + // create main class + createMainClassSource(srcJavaDir, packageName, mainClassname); + // gather dependencies + Set<String> deps = resolveDependencies(settings); + // create pom + createPom(new File(BUILD_DIR, "pom.xml"), deps); + + // move work dir to the export dir + if (!exportDir.equals(".")) { + // create the dir and copy over all files from work dir + File target = new File(exportDir); + target.mkdirs(); + Files.move(new File(BUILD_DIR).toPath(), target.toPath(), StandardCopyOption.ATOMIC_MOVE); + } + // TODO: If output is same folder (eg dot) then files should be moved instead of copy (or we delete all and move from work dir) + + return 0; + } + + private void createPom(File pom, Set<String> deps) throws Exception { + String[] ids = gav.split(":"); + + InputStream is = ExportSpringBoot.class.getClassLoader().getResourceAsStream("templates/spring-boot-pom.tmpl"); + String context = IOHelper.loadText(is); + IOHelper.close(is); + + CamelCatalog catalog = new DefaultCamelCatalog(); + String camelVersion = catalog.getCatalogVersion(); + + context = context.replaceFirst("\\{\\{ \\.GroupId }}", ids[0]); + context = context.replaceFirst("\\{\\{ \\.ArtifactId }}", ids[1]); + context = context.replaceFirst("\\{\\{ \\.Version }}", ids[2]); + context = context.replaceAll("\\{\\{ \\.SpringBootVersion }}", springBootVersion); + context = context.replaceFirst("\\{\\{ \\.JavaVersion }}", javaVersion); + context = context.replaceFirst("\\{\\{ \\.CamelVersion }}", camelVersion); + + StringBuilder sb = new StringBuilder(); + for (String dep : deps) { + MavenGav gav = MavenGav.parseGav(null, dep); + String gid = gav.getGroupId(); + String aid = gav.getArtifactId(); + String v = gav.getVersion(); + // transform to camel-spring-boot starter GAV + if ("org.apache.camel".equals(gid)) { + gid = "org.apache.camel.springboot"; + aid = aid + "-starter"; + v = null; + } + sb.append(" <dependency>\n"); + sb.append(" <groupId>").append(gid).append("</groupId>\n"); + sb.append(" <artifactId>").append(aid).append("</artifactId>\n"); + if (v != null) { + sb.append(" <version>").append(v).append("</version>\n"); + } + sb.append(" </dependency>\n"); + } + context = context.replaceFirst("\\{\\{ \\.CamelDependencies }}", sb.toString()); + + IOHelper.writeText(context, new FileOutputStream(pom, false)); + } + + private Set<String> resolveDependencies(File settings) throws Exception { + Set<String> answer = new TreeSet<>(); + List<String> lines = Files.readAllLines(settings.toPath()); + for (String line : lines) { + if (line.startsWith("dependency=")) { + String v = StringHelper.after(line, "dependency="); + // skip core-languages and java-joor as we let spring boot compile + boolean skip = v == null || v.contains("org.apache.camel:camel-core-languages") + || v.contains("org.apache.camel:camel-java-joor-dsl"); + if (!skip) { + answer.add(v); + } + } + } + return answer; + } + + private void createMainClassSource(File srcJavaDir, String packageName, String mainClassname) throws Exception { + InputStream is = ExportSpringBoot.class.getClassLoader().getResourceAsStream("templates/spring-boot-main.tmpl"); + String context = IOHelper.loadText(is); + IOHelper.close(is); + + context = context.replaceFirst("\\{\\{ \\.PackageName }}", packageName); + context = context.replaceAll("\\{\\{ \\.MainClassname }}", mainClassname); + IOHelper.writeText(context, new FileOutputStream(srcJavaDir + "/" + mainClassname + ".java", false)); + } + + private Integer runSilently() throws Exception { + Run run = new Run(getMain()); + Integer code = run.runSilent(); + return code; + } + + private void copySourceFiles(File settings, File srcJavaDir, File srcResourcesDir, String packageName) throws Exception { + // read the settings file and find the files to copy + OrderedProperties prop = new OrderedProperties(); + prop.load(new FileInputStream(settings)); + + for (String k : SETTINGS_PROP_SOURCE_KEYS) { + String files = prop.getProperty(k); + if (files != null) { + for (String f : files.split(",")) { + String scheme = getScheme(f); + if (scheme != null) { + f = f.substring(scheme.length() + 1); + } + String ext = FileUtil.onlyExt(f, true); + boolean java = "java".equals(ext); + File target = java ? srcJavaDir : srcResourcesDir; + File source = new File(f); + File out = new File(target, source.getName()); + safeCopy(source, out, true); + if (java) { + // need to append package name in java source file + List<String> lines = Files.readAllLines(out.toPath()); + lines.add(0, ""); + lines.add(0, "package " + packageName + ";"); + FileOutputStream fos = new FileOutputStream(out); + for (String line : lines) { + if (line.startsWith("public class") + && (line.contains("RouteBuilder") || line.contains("EndpointRouteBuilder"))) { + fos.write("import org.springframework.stereotype.Component;\n\n" + .getBytes(StandardCharsets.UTF_8)); + fos.write("@Component\n".getBytes(StandardCharsets.UTF_8)); + } + fos.write(line.getBytes(StandardCharsets.UTF_8)); + fos.write("\n".getBytes(StandardCharsets.UTF_8)); + } + IOHelper.close(fos); + } + } + } + } + } + + private void copySettingsAndProfile(File settings, File profile, File targetDir) throws Exception { + OrderedProperties prop = new OrderedProperties(); + prop.load(new FileInputStream(settings)); + OrderedProperties prop2 = new OrderedProperties(); + if (profile.exists()) { + prop2.load(new FileInputStream(profile)); + } + + for (Map.Entry<Object, Object> entry : prop.entrySet()) { + String key = entry.getKey().toString(); + boolean skip = "camel.main.routesCompileDirectory".equals(key) || "camel.main.routesReloadEnabled".equals(key); + if (!skip && key.startsWith("camel.main")) { + prop2.put(entry.getKey(), entry.getValue()); + } + } + + // camel.main.x should be renamed to camel.springboot.x + OrderedProperties prop3 = new OrderedProperties(); + for (Map.Entry<Object, Object> entry : prop2.entrySet()) { + String key = entry.getKey().toString(); + if (key.startsWith("camel.main.")) { + key = "camel.springboot." + key.substring(11); + } + prop3.put(key, entry.getValue()); + } + + FileOutputStream fos = new FileOutputStream(new File(targetDir, profile.getName()), false); + for (Map.Entry<Object, Object> entry : prop3.entrySet()) { + String k = entry.getKey().toString(); + String v = entry.getValue().toString(); + // files are now loaded in classpath + v = v.replaceAll("file:", "classpath:"); + if ("camel.springboot.routesIncludePattern".equals(k)) { + // camel.main.routesIncludePattern should remove all .java as we use spring boot to load them + v = Arrays.stream(v.split(",")) + .filter(n -> !n.endsWith(".java")) + .collect(Collectors.joining(",")); + } + String line = k + "=" + v; + fos.write(line.getBytes(StandardCharsets.UTF_8)); + fos.write("\n".getBytes(StandardCharsets.UTF_8)); + } + IOHelper.close(fos); + } + + private static void safeCopy(File source, File target, boolean override) throws Exception { + if (!source.exists()) { + return; + } + + if (!target.exists()) { + Files.copy(source.toPath(), target.toPath()); + } else if (override) { + Files.copy(source.toPath(), target.toPath(), + StandardCopyOption.REPLACE_EXISTING); + } + } + + private static String getScheme(String name) { + int pos = name.indexOf(":"); + if (pos != -1) { + return name.substring(0, pos); + } + return null; + } + +} diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Project.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Project.java deleted file mode 100644 index 6d041040ee1..00000000000 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Project.java +++ /dev/null @@ -1,165 +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.dsl.jbang.core.commands; - -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.io.Writer; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; -import java.util.concurrent.Callable; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Stream; - -import freemarker.template.Configuration; -import freemarker.template.Template; -import freemarker.template.TemplateException; -import freemarker.template.TemplateExceptionHandler; -import org.apache.camel.dsl.jbang.core.generator.CamelJbangGenerator; -import org.apache.camel.dsl.jbang.core.generator.QuarkusGenerator; -import picocli.CommandLine; - -@CommandLine.Command(name = "create-project", description = "Creates Camel-Quarkus project") -@Deprecated -public class Project implements Callable<Integer> { - - private static final String PACKAGE_REGEX = "package\\s+([a-zA_Z_][\\.\\w]*);"; - private static final Pattern PACKAGE_PATTERN = Pattern.compile(PACKAGE_REGEX); - @CommandLine.Parameters(description = "The Camel file(s) to include in the created project", arity = "1") - private String[] files; - @CommandLine.Option(names = { "-h", "--help" }, usageHelp = true, description = "Display the help and sub-commands") - private boolean helpRequested; - @CommandLine.Option(names = { "-n", "--name" }, description = "The name of the Camel application", - defaultValue = "CamelJBang") - private String name; - @CommandLine.Option(names = { "-g", "--group-id" }, description = "The group ID of the maven project", - defaultValue = "org.apache.camel.jbang") - private String groupId; - @CommandLine.Option(names = { "-d", "--directory" }, description = "Directory where the project will be created", - defaultValue = ".") - private String baseDirectory; - @CommandLine.Option(names = "--quarkus-dependency", description = "Comma separated list of camel-quarkus dependencies", - defaultValue = "camel-quarkus-timer,camel-quarkus-log,camel-quarkus-yaml-dsl,camel-quarkus-kamelet,org.apache.camel.kamelets:camel-kamelets-catalog:0.6.0") - private String quarkusDependencies; - @CommandLine.Option(names = "--quarkus-bom-version", description = "Override quarkus bom version in pom.xml", - defaultValue = "2.6.0.Final") - private String quarkusBomVersion; - - private CamelJbangGenerator generator; - private Path resourcesFolder = Paths.get("src", "main", "resources"); - private Path sourcesFolder = Paths.get("src", "main", "java"); - private Path routesFolder = resourcesFolder.resolve("routes"); - - @Override - public Integer call() throws Exception { - generator = new QuarkusGenerator(Arrays.asList(quarkusDependencies.split(",")), quarkusBomVersion); - - File baseDir = new File(baseDirectory); - createDirectory(baseDir); - - Path projectPath = Paths.get(baseDirectory, name); - File projectDir = projectPath.toFile(); - createDirectory(projectDir); - - System.out.println(name + " project will be generated in " + projectDir.getAbsolutePath()); - - createProjectStructure(projectPath); - - for (String file : files) { - if (!file.endsWith(".java")) { - Files.copy(Paths.get(file), projectPath.resolve(routesFolder).resolve(Paths.get(file).getFileName())); - } else { - String packageName; - try (Stream<String> stream = Files.lines(Paths.get(file)) - .map(this::getPackage) - .filter(Objects::nonNull)) { - packageName = stream - .findFirst() - .orElse(""); - } - try { - Path packageDirectory - = projectPath.resolve(sourcesFolder).resolve(packageName.replace(".", File.separator)); - if (!packageDirectory.toFile().exists()) { - createDirectory(packageDirectory.toFile()); - } - - Files.copy(Paths.get(file), - packageDirectory.resolve(Paths.get(file).getFileName())); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - } - - return 0; - } - - private void createProjectStructure(Path projectPath) throws IOException { - Path javaSourcesPath = projectPath.resolve(sourcesFolder); - createDirectory(javaSourcesPath.toFile()); - Path resourcesPath = projectPath.resolve(resourcesFolder); - createDirectory(resourcesPath.toFile()); - Path routes = projectPath.resolve(routesFolder); - createDirectory(routes.toFile()); - - // Create application.properties - Files.write(projectPath.resolve(generator.getPropertyFileLocation()), - generator.getPropertyFileContent(name).getBytes()); - - // Create pom.xml - Map root = new HashMap<String, Object>(); - root.put("name", name); - root.put("groupId", groupId); - root.put("pomProperties", generator.getPomProperties()); - root.put("pomDependencies", generator.getPomDependencies()); - - Configuration cfg = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS); - cfg.setClassForTemplateLoading(this.getClass(), "/generator"); - cfg.setTemplateExceptionHandler(TemplateExceptionHandler.IGNORE_HANDLER); - - Template template = cfg.getTemplate(generator.getTemplate()); - - try (Writer fileWriter = new FileWriter(projectPath.resolve("pom.xml").toFile())) { - template.process(root, fileWriter); - } catch (TemplateException e) { - throw new RuntimeException(e); - } - } - - private String getPackage(String fileContent) { - Matcher matcher = PACKAGE_PATTERN.matcher(fileContent); - if (matcher.find()) { - return matcher.group(1); - } - - return null; - } - - private void createDirectory(File directory) { - if (!directory.exists()) { - directory.mkdirs(); - } - } -} 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 d0166dc8457..6c144f5ca51 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 @@ -51,6 +51,7 @@ import org.apache.camel.CamelContext; import org.apache.camel.dsl.jbang.core.common.RuntimeUtil; import org.apache.camel.generator.openapi.RestDslGenerator; import org.apache.camel.impl.lw.LightweightCamelContext; +import org.apache.camel.main.DownloadListener; import org.apache.camel.main.KameletMain; import org.apache.camel.support.ResourceHelper; import org.apache.camel.util.FileUtil; @@ -307,11 +308,20 @@ class Run extends CamelCommand { final KameletMain main = createMainInstance(); final Set<String> downloaded = new HashSet<>(); - main.setDownloadListener((groupId, artifactId, version) -> { - String line = "mvn:" + groupId + ":" + artifactId + ":" + version; - if (!downloaded.contains(line)) { - writeSettings("dependency", line); - downloaded.add(line); + main.setDownloadListener(new DownloadListener() { + @Override + public void onDownloadDependency(String groupId, String artifactId, String version) { + String line = "mvn:" + groupId + ":" + artifactId + ":" + version; + if (!downloaded.contains(line)) { + writeSettings("dependency", line); + downloaded.add(line); + } + } + + @Override + public void onAlreadyDownloadedDependency(String groupId, String artifactId, String version) { + // we want to register everything + onDownloadDependency(groupId, artifactId, version); } }); main.setAppName("Apache Camel (JBang)"); @@ -524,6 +534,7 @@ class Run extends CamelCommand { } else { loc = locations.toString(); } + // TODO: remove duplicates in loc main.addInitialProperty("camel.component.properties.location", loc); writeSettings("camel.component.properties.location", loc); } diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/generator/CamelJbangGenerator.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/generator/CamelJbangGenerator.java deleted file mode 100644 index a7709e4d119..00000000000 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/generator/CamelJbangGenerator.java +++ /dev/null @@ -1,33 +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.dsl.jbang.core.generator; - -import java.nio.file.Path; -import java.util.List; - -public interface CamelJbangGenerator { - - Path getPropertyFileLocation(); - - String getPropertyFileContent(String name); - - List<PomProperty> getPomProperties(); - - String getTemplate(); - - List<PomDependency> getPomDependencies(); -} diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/generator/PomDependency.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/generator/PomDependency.java deleted file mode 100644 index 33dcf9f0557..00000000000 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/generator/PomDependency.java +++ /dev/null @@ -1,74 +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.dsl.jbang.core.generator; - -public class PomDependency { - private String groupId; - private String artifactId; - private String version; - - public PomDependency(String artifactId) { - this.artifactId = artifactId; - this.groupId = "org.apache.camel.quarkus"; - } - - public PomDependency(String groupId, String artifactId) { - this.groupId = groupId; - this.artifactId = artifactId; - } - - public PomDependency(String groupId, String artifactId, String version) { - this.groupId = groupId; - this.artifactId = artifactId; - this.version = version; - } - - public static PomDependency of(String dependency) { - String[] gav = dependency.split(":"); - if (gav.length == 3) { - return new PomDependency(gav[0], gav[1], gav[2]); - } else if (gav.length == 2) { - return new PomDependency(gav[0], gav[1]); - } else { - return new PomDependency(dependency); - } - } - - public String getVersion() { - return version; - } - - public void setVersion(String version) { - this.version = version; - } - - public String getGroupId() { - return groupId; - } - - public void setGroupId(String groupId) { - this.groupId = groupId; - } - - public String getArtifactId() { - return artifactId; - } - - public void setArtifactId(String artifactId) { - this.artifactId = artifactId; - } -} diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/generator/PomProperty.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/generator/PomProperty.java deleted file mode 100644 index 295549bf687..00000000000 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/generator/PomProperty.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 - * - * 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.jbang.core.generator; - -public class PomProperty { - private String key; - private String value; - - public PomProperty(String key, String value) { - this.key = key; - this.value = value; - } - - public String getKey() { - return key; - } - - public void setKey(String key) { - this.key = key; - } - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } -} diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/generator/QuarkusGenerator.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/generator/QuarkusGenerator.java deleted file mode 100644 index a139d416785..00000000000 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/generator/QuarkusGenerator.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.dsl.jbang.core.generator; - -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.List; -import java.util.stream.Collectors; - -public class QuarkusGenerator implements CamelJbangGenerator { - - private final List<String> dependencies; - private final String bomVersion; - - public QuarkusGenerator(List<String> dependencies, String bomVersion) { - this.dependencies = dependencies; - this.bomVersion = bomVersion; - } - - @Override - public Path getPropertyFileLocation() { - return Paths.get("src", "main", "resources", "application.properties"); - } - - @Override - public String getPropertyFileContent(String name) { - StringBuilder sb = new StringBuilder(); - sb.append("quarkus.banner.enabled = false\n"); - sb.append("quarkus.log.file.enable = true\n"); - sb.append("camel.context.name = ").append(name).append("\n"); - sb.append("camel.main.routes-include-pattern = classpath:routes/*"); - return sb.toString(); - } - - @Override - public List<PomProperty> getPomProperties() { - return List.of(new PomProperty("quarkus.platform.version", bomVersion)); - } - - public String getTemplate() { - return "quarkus-pom.ftl"; - } - - @Override - public List<PomDependency> getPomDependencies() { - return dependencies.stream() - .map(PomDependency::of) - .collect(Collectors.toList()); - } -} diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/templates/VelocityTemplateParser.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/templates/VelocityTemplateParser.java deleted file mode 100644 index 094351a73f4..00000000000 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/templates/VelocityTemplateParser.java +++ /dev/null @@ -1,115 +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.dsl.jbang.core.templates; - -import java.io.File; -import java.io.FileReader; -import java.io.IOException; -import java.io.Writer; -import java.util.Properties; - -import org.apache.camel.CamelException; -import org.apache.camel.dsl.jbang.core.api.TemplateParser; -import org.apache.camel.dsl.jbang.core.common.exceptions.ResourceAlreadyExists; -import org.apache.camel.util.ObjectHelper; -import org.apache.velocity.Template; -import org.apache.velocity.VelocityContext; -import org.apache.velocity.app.Velocity; -import org.apache.velocity.exception.MethodInvocationException; -import org.apache.velocity.exception.ParseErrorException; -import org.apache.velocity.exception.ResourceNotFoundException; -import org.apache.velocity.runtime.RuntimeConstants; - -public class VelocityTemplateParser implements TemplateParser { - private final Properties properties = new Properties(); - - public VelocityTemplateParser(File templateDir, String propertiesFile) throws IOException { - this(templateDir, new File(propertiesFile)); - } - - public VelocityTemplateParser(File templateDir, File propertiesFile) throws IOException { - initializeTemplateEngine(templateDir); - - try (FileReader propertiesReader = new FileReader(propertiesFile)) { - properties.load(propertiesReader); - } - } - - private void initializeTemplateEngine(File templateDir) { - Properties props = new Properties(); - - props.setProperty(RuntimeConstants.RESOURCE_LOADER, "file"); - - props.put("resource.loader.file.path", templateDir.getAbsolutePath()); - - Velocity.init(props); - } - - private void overridePropertyList(VelocityContext context, Properties properties, String requiredKameletProperties) { - String requiredPropertyList = properties.getProperty(requiredKameletProperties); - - if (ObjectHelper.isNotEmpty(requiredPropertyList)) { - context.put(requiredKameletProperties, requiredPropertyList.split(",")); - } - } - - @Override - public void parse(String templateFileName, Writer writer) throws CamelException { - VelocityContext context = new VelocityContext(); - - try { - loadTemplateProperties(context); - } catch (IOException e) { - throw new CamelException("Unable to load the template properties", e); - } - - try { - Template template = Velocity.getTemplate(templateFileName); - - template.merge(context, writer); - } catch (ResourceNotFoundException rnfe) { - throw new CamelException("Could not find the template to parse", rnfe); - } catch (ParseErrorException pee) { - throw new CamelException("Failed parsing the template", pee); - } catch (MethodInvocationException mie) { - throw new CamelException("Method call within the templated has failed", mie); - } catch (Exception e) { - throw new CamelException("Unspecified error while loading, parsing or processing the template", e); - } - } - - private void loadTemplateProperties(VelocityContext context) throws IOException { - properties.forEach((k, v) -> context.put(k.toString(), v)); - - overridePropertyList(context, properties, "kameletProperties"); - overridePropertyList(context, properties, "requiredKameletProperties"); - overridePropertyList(context, properties, "kameletBeans"); - overridePropertyList(context, properties, "fromParameters"); - overridePropertyList(context, properties, "toParameters"); - } - - public File getOutputFile(File outputDir) throws ResourceAlreadyExists { - String outputFileName = properties.getProperty("kameletMetadataName") + ".kamelet.yaml"; - - File outputFile = new File(outputDir, outputFileName); - if (outputFile.exists()) { - throw new ResourceAlreadyExists(outputFile); - } - - return outputFile; - } -} diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/resources/generator/quarkus-pom.ftl b/dsl/camel-jbang/camel-jbang-core/src/main/resources/generator/quarkus-pom.ftl deleted file mode 100644 index 6242c8d90d5..00000000000 --- a/dsl/camel-jbang/camel-jbang-core/src/main/resources/generator/quarkus-pom.ftl +++ /dev/null @@ -1,259 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - <modelVersion>4.0.0</modelVersion> - - <artifactId>${name}</artifactId> - <groupId>${groupId}</groupId> - <version>1.0.0-SNAPSHOT</version> - - <name>${name}</name> - - <properties> - <#list pomProperties as property> - <${property.key}>${property.value}</${property.key}> - </#list> - <camel-quarkus.platform.version>${r"${quarkus.platform.version}"}</camel-quarkus.platform.version> - - <quarkus.platform.group-id>io.quarkus.platform</quarkus.platform.group-id> - <quarkus.platform.artifact-id>quarkus-bom</quarkus.platform.artifact-id> - <camel-quarkus.platform.group-id>${r"${quarkus.platform.group-id}"}</camel-quarkus.platform.group-id> - <camel-quarkus.platform.artifact-id>quarkus-camel-bom</camel-quarkus.platform.artifact-id> - - <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> - <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> - <maven.compiler.target>11</maven.compiler.target> - <maven.compiler.source>11</maven.compiler.source> - <maven.compiler.testTarget>${r"${maven.compiler.target}"}</maven.compiler.testTarget> - <maven.compiler.testSource>${r"${maven.compiler.source}"}</maven.compiler.testSource> - - <formatter-maven-plugin.version>2.17.1</formatter-maven-plugin.version> - <impsort-maven-plugin.version>1.3.2</impsort-maven-plugin.version> - <maven-compiler-plugin.version>3.8.0</maven-compiler-plugin.version> - <maven-jar-plugin.version>3.2.0</maven-jar-plugin.version> - <maven-resources-plugin.version>3.1.0</maven-resources-plugin.version> - <maven-surefire-plugin.version>2.22.2</maven-surefire-plugin.version> - <mycila-license.version>3.0</mycila-license.version> - </properties> - - <dependencyManagement> - <dependencies> - <!-- Import BOM --> - <dependency> - <groupId>${r"${quarkus.platform.group-id}"}</groupId> - <artifactId>${r"${quarkus.platform.artifact-id}"}</artifactId> - <version>${r"${quarkus.platform.version}"}</version> - <type>pom</type> - <scope>import</scope> - </dependency> - <dependency> - <groupId>${r"${camel-quarkus.platform.group-id}"}</groupId> - <artifactId>${r"${camel-quarkus.platform.artifact-id}"}</artifactId> - <version>${r"${camel-quarkus.platform.version}"}</version> - <type>pom</type> - <scope>import</scope> - </dependency> - </dependencies> - </dependencyManagement> - - <dependencies> - <#list pomDependencies as dependency> - <dependency> - <groupId>${dependency.groupId}</groupId> - <artifactId>${dependency.artifactId}</artifactId> - <#if dependency.version??> - <version>${dependency.version}</version> - </#if> - </dependency> - </#list> - - <!-- Test --> - <dependency> - <groupId>io.quarkus</groupId> - <artifactId>quarkus-junit5</artifactId> - <scope>test</scope> - </dependency> - <dependency> - <groupId>org.awaitility</groupId> - <artifactId>awaitility</artifactId> - <scope>test</scope> - </dependency> - </dependencies> - - <build> - <pluginManagement> - <plugins> - - <plugin> - <groupId>net.revelc.code.formatter</groupId> - <artifactId>formatter-maven-plugin</artifactId> - <version>${r"${formatter-maven-plugin.version}"}</version> - </plugin> - - <plugin> - <groupId>net.revelc.code</groupId> - <artifactId>impsort-maven-plugin</artifactId> - <version>${r"${impsort-maven-plugin.version}"}</version> - <configuration> - <groups>java.,javax.,org.w3c.,org.xml.,junit.</groups> - <removeUnused>true</removeUnused> - <staticAfter>true</staticAfter> - <staticGroups>java.,javax.,org.w3c.,org.xml.,junit.</staticGroups> - </configuration> - </plugin> - - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-compiler-plugin</artifactId> - <version>${r"${maven-compiler-plugin.version}"}</version> - <configuration> - <showDeprecation>true</showDeprecation> - <showWarnings>true</showWarnings> - <compilerArgs> - <arg>-Xlint:unchecked</arg> - </compilerArgs> - </configuration> - </plugin> - - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-surefire-plugin</artifactId> - <version>${r"${maven-surefire-plugin.version}"}</version> - <configuration> - <failIfNoTests>false</failIfNoTests> - <systemProperties> - <java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager> - </systemProperties> - </configuration> - </plugin> - - <plugin> - <groupId>${r"${quarkus.platform.group-id}"}</groupId> - <artifactId>quarkus-maven-plugin</artifactId> - <version>${r"${quarkus.platform.version}"}</version> - </plugin> - - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-failsafe-plugin</artifactId> - <version>${r"${maven-surefire-plugin.version}"}</version> - </plugin> - - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-jar-plugin</artifactId> - <version>${r"${maven-jar-plugin.version}"}</version> - </plugin> - - <plugin> - <groupId>com.mycila</groupId> - <artifactId>license-maven-plugin</artifactId> - <version>${r"${mycila-license.version}"}</version> - <configuration> - <failIfUnknown>true</failIfUnknown> - <header>${r"${maven.multiModuleProjectDirectory}"}/header.txt</header> - <excludes> - <exclude>**/*.adoc</exclude> - <exclude>**/*.txt</exclude> - <exclude>**/LICENSE.txt</exclude> - <exclude>**/LICENSE</exclude> - <exclude>**/NOTICE.txt</exclude> - <exclude>**/NOTICE</exclude> - <exclude>**/README</exclude> - <exclude>**/pom.xml.versionsBackup</exclude> - </excludes> - <mapping> - <java>SLASHSTAR_STYLE</java> - <properties>CAMEL_PROPERTIES_STYLE</properties> - <kt>SLASHSTAR_STYLE</kt> - </mapping> - <headerDefinitions> - <headerDefinition>${r"${maven.multiModuleProjectDirectory}"}/license-properties-headerdefinition.xml</headerDefinition> - </headerDefinitions> - </configuration> - </plugin> - </plugins> - </pluginManagement> - - <plugins> - <plugin> - <groupId>${r"${quarkus.platform.group-id}"}</groupId> - <artifactId>quarkus-maven-plugin</artifactId> - <executions> - <execution> - <id>build</id> - <goals> - <goal>build</goal> - </goals> - </execution> - </executions> - <configuration> - <workingDir>${r"${project.basedir}"}</workingDir> - </configuration> - </plugin> - - <plugin> - <groupId>net.revelc.code.formatter</groupId> - <artifactId>formatter-maven-plugin</artifactId> - <executions> - <execution> - <id>format</id> - <goals> - <goal>format</goal> - </goals> - <phase>process-sources</phase> - </execution> - </executions> - </plugin> - - <plugin> - <groupId>net.revelc.code</groupId> - <artifactId>impsort-maven-plugin</artifactId> - <executions> - <execution> - <id>sort-imports</id> - <goals> - <goal>sort</goal> - </goals> - <phase>process-sources</phase> - </execution> - </executions> - </plugin> - </plugins> - </build> - - <profiles> - <profile> - <id>native</id> - <activation> - <property> - <name>native</name> - </property> - </activation> - <properties> - <quarkus.package.type>native</quarkus.package.type> - </properties> - <build> - <plugins> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-failsafe-plugin</artifactId> - <executions> - <execution> - <goals> - <goal>integration-test</goal> - <goal>verify</goal> - </goals> - <configuration> - <systemPropertyVariables> - <quarkus.package.type>${r"${quarkus.package.type}"}</quarkus.package.type> - </systemPropertyVariables> - </configuration> - </execution> - </executions> - </plugin> - </plugins> - </build> - </profile> - </profiles> - -</project> \ No newline at end of file diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/spring-boot-main.tmpl b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/spring-boot-main.tmpl new file mode 100644 index 00000000000..a793b4296ca --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/spring-boot-main.tmpl @@ -0,0 +1,13 @@ +package {{ .PackageName }}; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class {{ .MainClassname }} { + + public static void main(String[] args) { + SpringApplication.run({{ .MainClassname }}.class, args); + } + +} diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/spring-boot-pom.tmpl b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/spring-boot-pom.tmpl new file mode 100644 index 00000000000..3ba005dfac6 --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/spring-boot-pom.tmpl @@ -0,0 +1,84 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-parent</artifactId> + <version>{{ .SpringBootVersion }}</version> + <relativePath/> <!-- lookup parent from repository --> + </parent> + + <groupId>{{ .GroupId }}</groupId> + <artifactId>{{ .ArtifactId }}</artifactId> + <version>{{ .Version }}</version> + + <properties> + <java.version>{{ .JavaVersion }}</java.version> + </properties> + + <dependencyManagement> + <dependencies> + <!-- Spring Boot BOM --> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-dependencies</artifactId> + <version>{{ .SpringBootVersion }}</version> + <type>pom</type> + <scope>import</scope> + </dependency> + <!-- Camel BOM --> + <dependency> + <groupId>org.apache.camel.springboot</groupId> + <artifactId>camel-spring-boot-bom</artifactId> + <version>{{ .CamelVersion }}</version> + <type>pom</type> + <scope>import</scope> + </dependency> + </dependencies> + </dependencyManagement> + + <dependencies> + + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-web</artifactId> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-actuator</artifactId> + </dependency> + + <dependency> + <groupId>org.apache.camel.springboot</groupId> + <artifactId>camel-spring-boot-engine-starter</artifactId> + </dependency> + <dependency> + <groupId>org.apache.camel.springboot</groupId> + <artifactId>camel-dsl-modeline-starter</artifactId> + </dependency> +{{ .CamelDependencies }} + + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-test</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-test-spring-junit5</artifactId> + <scope>test</scope> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-maven-plugin</artifactId> + </plugin> + </plugins> + </build> + +</project> diff --git a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/CommandLineDependencyDownloader.java b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/CommandLineDependencyDownloader.java index f6f4b82cbce..bb598455bf6 100644 --- a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/CommandLineDependencyDownloader.java +++ b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/CommandLineDependencyDownloader.java @@ -70,7 +70,8 @@ public class CommandLineDependencyDownloader extends ServiceSupport implements C private boolean isValidGav(String gav) { MavenGav mg = MavenGav.parseGav(camelContext, gav); - boolean exists = DownloaderHelper.alreadyOnClasspath(camelContext, mg.getArtifactId(), mg.getVersion()); + boolean exists + = DownloaderHelper.alreadyOnClasspath(camelContext, mg.getGroupId(), mg.getArtifactId(), mg.getVersion()); // valid if not already on classpath return !exists; } diff --git a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/DependencyDownloaderClassResolver.java b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/DependencyDownloaderClassResolver.java index 2f73a8e00ef..d638fe88fb5 100644 --- a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/DependencyDownloaderClassResolver.java +++ b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/DependencyDownloaderClassResolver.java @@ -42,7 +42,8 @@ final class DependencyDownloaderClassResolver extends DefaultClassResolver { // okay maybe the class is from a known GAV that we can download first and then load the class MavenGav gav = knownDependenciesResolver.mavenGavForClass(name); if (gav != null) { - if (!DownloaderHelper.alreadyOnClasspath(getCamelContext(), gav.getArtifactId(), gav.getVersion())) { + if (!DownloaderHelper.alreadyOnClasspath(getCamelContext(), gav.getGroupId(), gav.getArtifactId(), + gav.getVersion())) { DownloaderHelper.downloadDependency(getCamelContext(), gav.getGroupId(), gav.getArtifactId(), gav.getVersion()); } diff --git a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/DependencyDownloaderComponentResolver.java b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/DependencyDownloaderComponentResolver.java index db1ef258690..a4cff33c85b 100644 --- a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/DependencyDownloaderComponentResolver.java +++ b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/DependencyDownloaderComponentResolver.java @@ -54,7 +54,8 @@ final class DependencyDownloaderComponentResolver extends DefaultComponentResolv @Override public Component resolveComponent(String name, CamelContext context) { ComponentModel model = catalog.componentModel(name); - if (model != null && !DownloaderHelper.alreadyOnClasspath(camelContext, model.getArtifactId(), model.getVersion())) { + if (model != null && !DownloaderHelper.alreadyOnClasspath(camelContext, model.getGroupId(), model.getArtifactId(), + model.getVersion())) { DownloaderHelper.downloadDependency(camelContext, model.getGroupId(), model.getArtifactId(), model.getVersion()); } diff --git a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/DependencyDownloaderDataFormatResolver.java b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/DependencyDownloaderDataFormatResolver.java index d520a253390..af118d7579e 100644 --- a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/DependencyDownloaderDataFormatResolver.java +++ b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/DependencyDownloaderDataFormatResolver.java @@ -49,7 +49,8 @@ final class DependencyDownloaderDataFormatResolver extends DefaultDataFormatReso @Override public DataFormat createDataFormat(String name, CamelContext context) { DataFormatModel model = catalog.dataFormatModel(name); - if (model != null && !DownloaderHelper.alreadyOnClasspath(camelContext, model.getArtifactId(), model.getVersion())) { + if (model != null && !DownloaderHelper.alreadyOnClasspath(camelContext, model.getGroupId(), model.getArtifactId(), + model.getVersion())) { DownloaderHelper.downloadDependency(camelContext, model.getGroupId(), model.getArtifactId(), model.getVersion()); } return super.createDataFormat(name, context); diff --git a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/DependencyDownloaderKamelet.java b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/DependencyDownloaderKamelet.java index 8bf283d4d39..caae629d72a 100644 --- a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/DependencyDownloaderKamelet.java +++ b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/DependencyDownloaderKamelet.java @@ -181,7 +181,8 @@ final class DependencyDownloaderKamelet extends ServiceSupport implements CamelC } MavenGav mg = MavenGav.parseGav(camelContext, gav); - boolean exists = DownloaderHelper.alreadyOnClasspath(camelContext, mg.getArtifactId(), mg.getVersion()); + boolean exists + = DownloaderHelper.alreadyOnClasspath(camelContext, mg.getGroupId(), mg.getArtifactId(), mg.getVersion()); // valid if not already on classpath return !exists; } diff --git a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/DependencyDownloaderLanguageResolver.java b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/DependencyDownloaderLanguageResolver.java index 38de22c433f..40975edd412 100644 --- a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/DependencyDownloaderLanguageResolver.java +++ b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/DependencyDownloaderLanguageResolver.java @@ -49,7 +49,8 @@ final class DependencyDownloaderLanguageResolver extends DefaultLanguageResolver @Override public Language resolveLanguage(String name, CamelContext context) { LanguageModel model = catalog.languageModel(name); - if (model != null && !DownloaderHelper.alreadyOnClasspath(camelContext, model.getArtifactId(), model.getVersion())) { + if (model != null && !DownloaderHelper.alreadyOnClasspath(camelContext, model.getGroupId(), model.getArtifactId(), + model.getVersion())) { DownloaderHelper.downloadDependency(camelContext, model.getGroupId(), model.getArtifactId(), model.getVersion()); } diff --git a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/DependencyDownloaderPropertyBindingListener.java b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/DependencyDownloaderPropertyBindingListener.java index 974b85a1ea9..4054071bd00 100644 --- a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/DependencyDownloaderPropertyBindingListener.java +++ b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/DependencyDownloaderPropertyBindingListener.java @@ -36,7 +36,8 @@ class DependencyDownloaderPropertyBindingListener implements PropertyBindingList String s = (String) value; MavenGav gav = knownDependenciesResolver.mavenGavForClass(s); if (gav != null) { - if (!DownloaderHelper.alreadyOnClasspath(camelContext, gav.getArtifactId(), gav.getVersion())) { + if (!DownloaderHelper.alreadyOnClasspath(camelContext, gav.getGroupId(), gav.getArtifactId(), + gav.getVersion())) { DownloaderHelper.downloadDependency(camelContext, gav.getGroupId(), gav.getArtifactId(), gav.getVersion()); } diff --git a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/DependencyDownloaderRoutesLoader.java b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/DependencyDownloaderRoutesLoader.java index 6b62fed3a9b..d45fcdb93a2 100644 --- a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/DependencyDownloaderRoutesLoader.java +++ b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/DependencyDownloaderRoutesLoader.java @@ -75,7 +75,8 @@ public class DependencyDownloaderRoutesLoader extends MainRoutesLoader { } private void downloadLoader(String artifactId) { - if (!DownloaderHelper.alreadyOnClasspath(getCamelContext(), artifactId, getCamelContext().getVersion())) { + if (!DownloaderHelper.alreadyOnClasspath(getCamelContext(), "org.apache.camel", artifactId, + getCamelContext().getVersion())) { DownloaderHelper.downloadDependency(getCamelContext(), "org.apache.camel", artifactId, getCamelContext().getVersion()); } diff --git a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/DependencyDownloaderStrategy.java b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/DependencyDownloaderStrategy.java index 44fc10f59ff..6287fb78577 100644 --- a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/DependencyDownloaderStrategy.java +++ b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/DependencyDownloaderStrategy.java @@ -30,7 +30,7 @@ class DependencyDownloaderStrategy implements DependencyStrategy { @Override public void onDependency(String dependency) { MavenGav gav = MavenGav.parseGav(camelContext, dependency); - if (!DownloaderHelper.alreadyOnClasspath(camelContext, gav.getArtifactId(), gav.getVersion())) { + if (!DownloaderHelper.alreadyOnClasspath(camelContext, gav.getGroupId(), gav.getArtifactId(), gav.getVersion())) { DownloaderHelper.downloadDependency(camelContext, gav.getGroupId(), gav.getArtifactId(), gav.getVersion()); } diff --git a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/DownloadListener.java b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/DownloadListener.java index f0281710677..78c60967738 100644 --- a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/DownloadListener.java +++ b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/DownloadListener.java @@ -21,6 +21,14 @@ package org.apache.camel.main; */ public interface DownloadListener { + /** + * Downloads a new dependency + */ void onDownloadDependency(String groupId, String artifactId, String version); + /** + * Uses an existing already downloaded dependency + */ + void onAlreadyDownloadedDependency(String groupId, String artifactId, String version); + } diff --git a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/DownloaderHelper.java b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/DownloaderHelper.java index 8db2dea2938..62ef40adeb6 100644 --- a/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/DownloaderHelper.java +++ b/dsl/camel-kamelet-main/src/main/java/org/apache/camel/main/DownloaderHelper.java @@ -76,7 +76,7 @@ public final class DownloaderHelper { }, gav); } - public static boolean alreadyOnClasspath(CamelContext camelContext, String artifactId, String version) { + public static boolean alreadyOnClasspath(CamelContext camelContext, String groupId, String artifactId, String version) { // if no artifact then regard this as okay if (artifactId == null) { return true; @@ -94,6 +94,11 @@ public final class DownloaderHelper { for (URL u : ucl.getURLs()) { String s = u.toString(); if (s.contains(target)) { + // trigger listener + DownloadListener listener = camelContext.getExtension(DownloadListener.class); + if (listener != null) { + listener.onAlreadyDownloadedDependency(groupId, artifactId, version); + } // already on classpath return true; }