From c8a5ccc2e119eae1b6d6e1cd501317d6eede32e5 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Mon, 23 Mar 2026 16:15:11 +0100 Subject: [PATCH 1/4] CAMEL-21208: Replace manual string-based code generation with FreeMarker templates in camel-jbang - Add FreeMarker 2.3.34 dependency to camel-jbang-core - Create TemplateHelper utility using square bracket syntax ([=var], [#if]...[/#if]) to avoid conflicts with ${...} (Maven) and <...> (XML) in generated content - Convert all 23 .tmpl template files to .ftl FreeMarker templates - Refactor Export*, Run, and Init commands to use TemplateHelper instead of manual StringBuilder/replaceAll/replaceFirst code generation - Extract shared helpers (buildRepositoryList, buildDependencyList, formatBuildProperties, mavenGavComparator) into ExportBaseCommand - Maintain backward compatibility for catalog-provided templates in ExportSpringBoot - Remove 4 unreferenced templates (main-docker-*.tmpl, main-jkube-pom.tmpl) - Keep deprecated bind templates (.tmpl) used by TemplateProvider Co-Authored-By: Claude Opus 4.6 --- dsl/camel-jbang/camel-jbang-core/pom.xml | 7 + .../camel/dsl/jbang/core/commands/Export.java | 111 ++----- .../core/commands/ExportBaseCommand.java | 195 +++++++++---- .../jbang/core/commands/ExportCamelMain.java | 179 +++--------- .../jbang/core/commands/ExportQuarkus.java | 102 +++---- .../jbang/core/commands/ExportSpringBoot.java | 164 ++++++++--- .../camel/dsl/jbang/core/commands/Init.java | 12 +- .../camel/dsl/jbang/core/commands/Run.java | 40 ++- .../dsl/jbang/core/common/TemplateHelper.java | 76 +++++ .../{Dockerfile21.tmpl => Dockerfile21.ftl} | 27 +- .../{Dockerfile25.tmpl => Dockerfile25.ftl} | 26 +- .../main/resources/templates/code-java.ftl | 38 +++ .../main/resources/templates/code-java.tmpl | 20 -- .../resources/templates/init-pipe.yaml.ftl | 35 +++ .../resources/templates/init-pipe.yaml.tmpl | 17 -- .../resources/templates/integration.yaml.ftl | 32 +++ .../resources/templates/integration.yaml.tmpl | 14 - .../src/main/resources/templates/java.ftl | 30 ++ .../src/main/resources/templates/java.tmpl | 12 - .../templates/kamelet-action.yaml.ftl | 45 +++ .../templates/kamelet-action.yaml.tmpl | 27 -- .../resources/templates/kamelet-sink.yaml.ftl | 51 ++++ .../templates/kamelet-sink.yaml.tmpl | 33 --- ...urce.yaml.tmpl => kamelet-source.yaml.ftl} | 20 +- .../templates/main-docker-from-auth-pom.tmpl | 4 - .../resources/templates/main-docker-pom.tmpl | 21 -- .../templates/main-docker-to-auth-pom.tmpl | 4 - .../resources/templates/main-jkube-pom.tmpl | 24 -- ...netes-pom.tmpl => main-kubernetes-pom.ftl} | 99 ++++++- .../src/main/resources/templates/main-pom.ftl | 272 ++++++++++++++++++ .../main/resources/templates/main-pom.tmpl | 137 --------- .../src/main/resources/templates/main.ftl | 31 ++ .../src/main/resources/templates/main.tmpl | 12 - ...es-pom.tmpl => quarkus-kubernetes-pom.ftl} | 97 ++++++- .../{quarkus-pom.tmpl => quarkus-pom.ftl} | 99 ++++++- .../main/resources/templates/readme.md.ftl | 49 ++++ .../main/resources/templates/readme.md.tmpl | 31 -- ...me.native.md.tmpl => readme.native.md.ftl} | 30 +- .../resources/templates/rest-dsl.yaml.ftl | 23 ++ .../resources/templates/rest-dsl.yaml.tmpl | 5 - ...sion.tmpl => run-custom-camel-version.ftl} | 28 +- ...om.tmpl => spring-boot-kubernetes-pom.ftl} | 95 +++++- .../resources/templates/spring-boot-main.ftl | 31 ++ .../resources/templates/spring-boot-main.tmpl | 13 - ...ring-boot-pom.tmpl => spring-boot-pom.ftl} | 97 ++++++- .../src/main/resources/templates/xml.ftl | 34 +++ .../src/main/resources/templates/xml.tmpl | 16 -- .../src/main/resources/templates/yaml.ftl | 27 ++ .../src/main/resources/templates/yaml.tmpl | 9 - .../commands/kubernetes/KubernetesExport.java | 6 +- 50 files changed, 1730 insertions(+), 877 deletions(-) create mode 100644 dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/TemplateHelper.java rename dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/{Dockerfile21.tmpl => Dockerfile21.ftl} (84%) rename dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/{Dockerfile25.tmpl => Dockerfile25.ftl} (52%) create mode 100644 dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/code-java.ftl delete mode 100644 dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/code-java.tmpl create mode 100644 dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/init-pipe.yaml.ftl delete mode 100644 dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/init-pipe.yaml.tmpl create mode 100644 dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/integration.yaml.ftl delete mode 100644 dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/integration.yaml.tmpl create mode 100644 dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/java.ftl delete mode 100644 dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/java.tmpl create mode 100644 dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/kamelet-action.yaml.ftl delete mode 100644 dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/kamelet-action.yaml.tmpl create mode 100644 dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/kamelet-sink.yaml.ftl delete mode 100644 dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/kamelet-sink.yaml.tmpl rename dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/{kamelet-source.yaml.tmpl => kamelet-source.yaml.ftl} (50%) delete mode 100644 dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/main-docker-from-auth-pom.tmpl delete mode 100644 dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/main-docker-pom.tmpl delete mode 100644 dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/main-docker-to-auth-pom.tmpl delete mode 100644 dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/main-jkube-pom.tmpl rename dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/{main-kubernetes-pom.tmpl => main-kubernetes-pom.ftl} (72%) create mode 100644 dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/main-pom.ftl delete mode 100644 dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/main-pom.tmpl create mode 100644 dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/main.ftl delete mode 100644 dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/main.tmpl rename dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/{quarkus-kubernetes-pom.tmpl => quarkus-kubernetes-pom.ftl} (79%) rename dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/{quarkus-pom.tmpl => quarkus-pom.ftl} (70%) create mode 100644 dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/readme.md.ftl delete mode 100644 dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/readme.md.tmpl rename dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/{readme.native.md.tmpl => readme.native.md.ftl} (54%) create mode 100644 dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/rest-dsl.yaml.ftl delete mode 100644 dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/rest-dsl.yaml.tmpl rename dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/{run-custom-camel-version.tmpl => run-custom-camel-version.ftl} (56%) rename dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/{spring-boot-kubernetes-pom.tmpl => spring-boot-kubernetes-pom.ftl} (75%) create mode 100644 dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/spring-boot-main.ftl delete mode 100644 dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/spring-boot-main.tmpl rename dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/{spring-boot-pom.tmpl => spring-boot-pom.ftl} (61%) create mode 100644 dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/xml.ftl delete mode 100644 dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/xml.tmpl create mode 100644 dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/yaml.ftl delete mode 100644 dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/yaml.tmpl diff --git a/dsl/camel-jbang/camel-jbang-core/pom.xml b/dsl/camel-jbang/camel-jbang-core/pom.xml index 31dccd48d50da..f94519188011f 100644 --- a/dsl/camel-jbang/camel-jbang-core/pom.xml +++ b/dsl/camel-jbang/camel-jbang-core/pom.xml @@ -152,6 +152,13 @@ plexus-xml + + + org.freemarker + freemarker + ${freemarker-version} + + org.apache.camel diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Export.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Export.java index 113a611879077..941a0a9bf3a93 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Export.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Export.java @@ -17,13 +17,14 @@ package org.apache.camel.dsl.jbang.core.commands; import java.io.FileNotFoundException; -import java.io.InputStream; +import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.text.SimpleDateFormat; -import java.util.Comparator; import java.util.Date; +import java.util.HashMap; +import java.util.Map; import java.util.Properties; import org.apache.camel.dsl.jbang.core.common.CamelJBangConstants; @@ -31,10 +32,9 @@ import org.apache.camel.dsl.jbang.core.common.RuntimeType; import org.apache.camel.dsl.jbang.core.common.RuntimeUtil; import org.apache.camel.dsl.jbang.core.common.SourceScheme; -import org.apache.camel.tooling.maven.MavenGav; +import org.apache.camel.dsl.jbang.core.common.TemplateHelper; import org.apache.camel.util.CamelCaseOrderedProperties; import org.apache.camel.util.FileUtil; -import org.apache.camel.util.IOHelper; import picocli.CommandLine.Command; import static org.apache.camel.dsl.jbang.core.common.CamelJBangConstants.CAMEL_SPRING_BOOT_VERSION; @@ -300,72 +300,6 @@ protected String getVersion() { return "1.0-SNAPSHOT"; } - public Comparator mavenGavComparator() { - return new Comparator() { - @Override - public int compare(MavenGav o1, MavenGav o2) { - int r1 = rankGroupId(o1); - int r2 = rankGroupId(o2); - - if (r1 > r2) { - return -1; - } else if (r2 > r1) { - return 1; - } else { - return o1.toString().compareTo(o2.toString()); - } - } - - int rankGroupId(MavenGav o1) { - String g1 = o1.getGroupId(); - if (g1 == null) { - return 0; - } - - switch (g1) { - case "org.springframework.boot" -> { - return 30; - } - case "io.quarkus" -> { - return 30; - } - case "org.apache.camel.quarkus" -> { - String a1 = o1.getArtifactId(); - // main/core/engine first - if ("camel-quarkus-core".equals(a1)) { - return 21; - } - return 20; - } - case "org.apache.camel.springboot" -> { - String a1 = o1.getArtifactId(); - // main/core/engine first - if ("camel-spring-boot-starter".equals(a1)) { - return 21; - } else if ("camel-spring-boot-engine-starter".equals(a1)) { - return 22; - } - return 20; - } - case "org.apache.camel" -> { - String a1 = o1.getArtifactId(); - // main/core/engine first - if ("camel-main".equals(a1)) { - return 11; - } - return 10; - } - case "org.apache.camel.kamelets" -> { - return 5; - } - default -> { - return 0; - } - } - } - }; - } - // Maven reproducible builds: https://maven.apache.org/guides/mini/guide-reproducible-builds.html protected String getBuildMavenProjectDate() { // 2024-09-23T10:00:00Z @@ -378,33 +312,36 @@ protected void copyDockerFiles(String buildDir) throws Exception { Path docker = Path.of(buildDir).resolve("src/main/docker"); Files.createDirectories(docker); String[] ids = gav.split(":"); - String templateName = "templates/Dockerfile" + javaVersion + ".tmpl"; - InputStream is = ExportCamelMain.class.getClassLoader().getResourceAsStream(templateName); - if (is == null) { + + String ftlName = "Dockerfile" + javaVersion + ".ftl"; + String context; + try { + Map model = new HashMap<>(); + model.put("ArtifactId", ids[1]); + model.put("Version", ids[2]); + model.put("AppJar", ids[1] + "-" + ids[2] + ".jar"); + context = TemplateHelper.processTemplate(ftlName, model); + } catch (IOException e) { // fallback to JDK 21 template printer().printf("No Dockerfile template for Java %s, falling back to Java 21 template%n", javaVersion); - is = ExportCamelMain.class.getClassLoader().getResourceAsStream("templates/Dockerfile21.tmpl"); + Map model = new HashMap<>(); + model.put("ArtifactId", ids[1]); + model.put("Version", ids[2]); + model.put("AppJar", ids[1] + "-" + ids[2] + ".jar"); + context = TemplateHelper.processTemplate("Dockerfile21.ftl", model); } - String context = IOHelper.loadText(is); - IOHelper.close(is); - - String appJar = ids[1] + "-" + ids[2] + ".jar"; - context = context.replaceAll("\\{\\{ \\.ArtifactId }}", ids[1]); - context = context.replaceAll("\\{\\{ \\.Version }}", ids[2]); - context = context.replaceAll("\\{\\{ \\.AppJar }}", appJar); Files.writeString(docker.resolve("Dockerfile"), context); } // Copy the readme.md into the same Maven project root directory. protected void copyReadme(String buildDir, String appJar) throws Exception { String[] ids = gav.split(":"); - InputStream is = ExportCamelMain.class.getClassLoader().getResourceAsStream("templates/readme.md.tmpl"); - String context = IOHelper.loadText(is); - IOHelper.close(is); + Map model = new HashMap<>(); + model.put("ArtifactId", ids[1]); + model.put("Version", ids[2]); + model.put("AppRuntimeJar", appJar); - context = context.replaceAll("\\{\\{ \\.ArtifactId }}", ids[1]); - context = context.replaceAll("\\{\\{ \\.Version }}", ids[2]); - context = context.replaceAll("\\{\\{ \\.AppRuntimeJar }}", appJar); + String context = TemplateHelper.processTemplate("readme.md.ftl", model); Files.writeString(Path.of(buildDir).resolve("readme.md"), context); } } diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportBaseCommand.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportBaseCommand.java index 24ccf486aa70c..a7ac10ad363a6 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportBaseCommand.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportBaseCommand.java @@ -406,46 +406,144 @@ private static String humanReadableSize(long bytes) { } } - protected static String mavenRepositoriesAsPomXml(String repos) { - StringBuilder sb = new StringBuilder(); - int i = 1; - sb.append(" \n"); - if (!repos.isEmpty()) { + /** + * Builds a list of repository data maps from a comma-separated repos string, for use with FreeMarker templates. + */ + protected static List> buildRepositoryList(String repos) { + List> result = new ArrayList<>(); + if (repos != null && !repos.isEmpty()) { + int i = 1; for (String repo : repos.split(",")) { - sb.append(" \n"); - sb.append(" custom").append(i++).append("\n"); - sb.append(" ").append(repo).append("\n"); - if (repo.contains("snapshots")) { - sb.append(" \n"); - sb.append(" false\n"); - sb.append(" \n"); - sb.append(" \n"); - sb.append(" true\n"); - sb.append(" \n"); - } - sb.append(" \n"); + Map r = new HashMap<>(); + r.put("id", "custom" + i++); + r.put("url", repo); + r.put("isSnapshot", repo.contains("snapshots")); + result.add(r); } } - sb.append(" \n"); - sb.append(" \n"); - if (!repos.isEmpty()) { - for (String repo : repos.split(",")) { - sb.append(" \n"); - sb.append(" custom").append(i++).append("\n"); - sb.append(" ").append(repo).append("\n"); - if (repo.contains("snapshots")) { - sb.append(" \n"); - sb.append(" false\n"); - sb.append(" \n"); - sb.append(" \n"); - sb.append(" true\n"); - sb.append(" \n"); + return result; + } + + /** + * Builds a list of dependency data maps from the deps set, for use with FreeMarker templates. + */ + protected List> buildDependencyList(Set deps) { + List gavs = new ArrayList<>(); + for (String dep : deps) { + MavenGav gav = parseMavenGav(dep); + String gid = gav.getGroupId(); + if ("org.apache.camel".equals(gid)) { + // uses BOM so version should not be included + gav.setVersion(null); + } + gavs.add(gav); + } + + // sort artifacts + gavs.sort(mavenGavComparator()); + + List> result = new ArrayList<>(); + for (MavenGav gav : gavs) { + Map dep = new HashMap<>(); + dep.put("groupId", gav.getGroupId()); + dep.put("artifactId", gav.getArtifactId()); + dep.put("version", gav.getVersion()); + dep.put("scope", gav.getScope()); + dep.put("isLib", "lib".equals(gav.getPackaging())); + dep.put("isKameletsUtils", "camel-kamelets-utils".equals(gav.getArtifactId())); + result.add(dep); + } + return result; + } + + public Comparator mavenGavComparator() { + return new Comparator() { + @Override + public int compare(MavenGav o1, MavenGav o2) { + int r1 = rankGroupId(o1); + int r2 = rankGroupId(o2); + + if (r1 > r2) { + return -1; + } else if (r2 > r1) { + return 1; + } else { + return o1.toString().compareTo(o2.toString()); } - sb.append(" \n"); + } + + int rankGroupId(MavenGav o1) { + String g1 = o1.getGroupId(); + if (g1 == null) { + return 0; + } + + switch (g1) { + case "org.springframework.boot" -> { + return 30; + } + case "io.quarkus" -> { + return 30; + } + case "org.apache.camel.quarkus" -> { + String a1 = o1.getArtifactId(); + // main/core/engine first + if ("camel-quarkus-core".equals(a1)) { + return 21; + } + return 20; + } + case "org.apache.camel.springboot" -> { + String a1 = o1.getArtifactId(); + // main/core/engine first + if ("camel-spring-boot-starter".equals(a1)) { + return 21; + } else if ("camel-spring-boot-engine-starter".equals(a1)) { + return 22; + } + return 20; + } + case "org.apache.camel" -> { + String a1 = o1.getArtifactId(); + // main/core/engine first + if ("camel-main".equals(a1)) { + return 11; + } + return 10; + } + case "org.apache.camel.kamelets" -> { + return 5; + } + default -> { + return 0; + } + } + } + }; + } + + /** + * Formats build properties as XML property lines for inclusion in POM templates. + */ + protected String formatBuildProperties() { + Properties properties = mapBuildProperties(); + + if (!skipPlugins) { + Set exporters = PluginHelper.getActivePlugins(getMain(), repositories).values() + .stream() + .map(Plugin::getExporter) + .filter(Optional::isPresent) + .map(Optional::get) + .collect(Collectors.toSet()); + + for (PluginExporter exporter : exporters) { + exporter.getBuildProperties().forEach(properties::putIfAbsent); } } - sb.append(" \n"); - return sb.toString(); + + return properties.entrySet().stream() + .map(item -> String.format(" <%s>%s", item.getKey(), item.getValue(), item.getKey())) + .collect(Collectors.joining(System.lineSeparator())); } protected abstract Integer export() throws Exception; @@ -487,30 +585,15 @@ protected void addDependencies(String... deps) { dependencies.addAll(Arrays.asList(depsArray)); } + /** + * @deprecated Use {@link #formatBuildProperties()} instead for FreeMarker templates. + */ + @Deprecated protected String replaceBuildProperties(String context) { - Properties properties = mapBuildProperties(); - - if (!skipPlugins) { - Set exporters = PluginHelper.getActivePlugins(getMain(), repositories).values() - .stream() - .map(Plugin::getExporter) - .filter(Optional::isPresent) - .map(Optional::get) - .collect(Collectors.toSet()); - - for (PluginExporter exporter : exporters) { - exporter.getBuildProperties().forEach(properties::putIfAbsent); - } - } - - String mavenProperties = properties.entrySet().stream() - .map(item -> { - return String.format(" <%s>%s", item.getKey(), item.getValue(), item.getKey()); - }) - .collect(Collectors.joining(System.lineSeparator())); - + String mavenProperties = formatBuildProperties(); if (!mavenProperties.isEmpty()) { - context = context.replaceFirst(Pattern.quote("{{ .BuildProperties }}"), Matcher.quoteReplacement(mavenProperties)); + context = context.replaceFirst(Pattern.quote("{{ .BuildProperties }}"), + Matcher.quoteReplacement(mavenProperties)); } else { context = context.replaceFirst(Pattern.quote("{{ .BuildProperties }}"), ""); } diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportCamelMain.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportCamelMain.java index 1ac673b32302f..b538dbfca85c1 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportCamelMain.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportCamelMain.java @@ -22,7 +22,9 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Properties; import java.util.Set; @@ -31,10 +33,9 @@ import org.apache.camel.dsl.jbang.core.common.CommandLineHelper; import org.apache.camel.dsl.jbang.core.common.PathUtils; import org.apache.camel.dsl.jbang.core.common.RuntimeUtil; +import org.apache.camel.dsl.jbang.core.common.TemplateHelper; import org.apache.camel.dsl.jbang.core.common.VersionHelper; -import org.apache.camel.tooling.maven.MavenGav; import org.apache.camel.util.CamelCaseOrderedProperties; -import org.apache.camel.util.IOHelper; import org.apache.camel.util.ObjectHelper; import static org.apache.camel.dsl.jbang.core.commands.ExportHelper.exportPackageName; @@ -45,7 +46,7 @@ class ExportCamelMain extends Export { public ExportCamelMain(CamelJBangMain main) { super(main); - pomTemplateName = "main-pom.tmpl"; + pomTemplateName = "main-pom.ftl"; } @Override @@ -184,10 +185,6 @@ public Integer export() throws Exception { private void createMavenPom(Path settings, Path profile, Path pom, Set deps, String packageName) throws Exception { String[] ids = gav.split(":"); - InputStream is = ExportCamelMain.class.getClassLoader().getResourceAsStream("templates/" + pomTemplateName); - String context = IOHelper.loadText(is); - IOHelper.close(is); - CamelCatalog catalog = new DefaultCamelCatalog(); if (ObjectHelper.isEmpty(camelVersion)) { camelVersion = catalog.getLoadedVersion(); @@ -196,97 +193,45 @@ private void createMavenPom(Path settings, Path profile, Path pom, Set d camelVersion = VersionHelper.extractCamelVersion(); } - context = context.replaceAll("\\{\\{ \\.GroupId }}", ids[0]); - context = context.replaceAll("\\{\\{ \\.ArtifactId }}", ids[1]); - context = context.replaceAll("\\{\\{ \\.Version }}", ids[2]); - context = context.replaceAll("\\{\\{ \\.JavaVersion }}", javaVersion); - context = context.replaceAll("\\{\\{ \\.CamelVersion }}", camelVersion); - if (packageName != null) { - context = context.replaceAll("\\{\\{ \\.MainClassname }}", packageName + "." + mainClassname); - } else { - context = context.replaceAll("\\{\\{ \\.MainClassname }}", mainClassname); - } - context = context.replaceFirst("\\{\\{ \\.ProjectBuildOutputTimestamp }}", this.getBuildMavenProjectDate()); - Properties prop = new CamelCaseOrderedProperties(); RuntimeUtil.loadProperties(prop, settings); String repos = getMavenRepositories(settings, prop, camelVersion); - context = replaceBuildProperties(context); - - if (repos == null || repos.isEmpty()) { - context = context.replaceFirst("\\{\\{ \\.MavenRepositories }}", ""); + // build the template data model + Map model = new HashMap<>(); + model.put("GroupId", ids[0]); + model.put("ArtifactId", ids[1]); + model.put("Version", ids[2]); + model.put("JavaVersion", javaVersion); + model.put("CamelVersion", camelVersion); + if (packageName != null) { + model.put("MainClassname", packageName + "." + mainClassname); } else { - String s = mavenRepositoriesAsPomXml(repos); - context = context.replaceFirst("\\{\\{ \\.MavenRepositories }}", s); - } - - List gavs = new ArrayList<>(); - for (String dep : deps) { - MavenGav gav = parseMavenGav(dep); - String gid = gav.getGroupId(); - if ("org.apache.camel".equals(gid)) { - // uses BOM so version should not be included - gav.setVersion(null); - } - gavs.add(gav); - } - - // sort artifacts - gavs.sort(mavenGavComparator()); - - StringBuilder sb = new StringBuilder(); - for (MavenGav gav : gavs) { - sb.append(" \n"); - sb.append(" ").append(gav.getGroupId()).append("\n"); - sb.append(" ").append(gav.getArtifactId()).append("\n"); - if (gav.getVersion() != null) { - sb.append(" ").append(gav.getVersion()).append("\n"); - } - if (gav.getScope() != null) { - sb.append(" ").append(gav.getScope()).append("\n"); - } - // special for lib JARs - if ("lib".equals(gav.getPackaging())) { - sb.append(" system\n"); - sb.append(" \\$\\{project.basedir}/lib/").append(gav.getArtifactId()).append("-") - .append(gav.getVersion()).append(".jar\n"); - } - if ("camel-kamelets-utils".equals(gav.getArtifactId())) { - // special for camel-kamelets-utils - sb.append(" \n"); - sb.append(" \n"); - sb.append(" org.apache.camel\n"); - sb.append(" *\n"); - sb.append(" \n"); - sb.append(" \n"); - } - sb.append(" \n"); + model.put("MainClassname", mainClassname); } + model.put("ProjectBuildOutputTimestamp", this.getBuildMavenProjectDate()); + model.put("BuildProperties", formatBuildProperties()); + model.put("Repositories", buildRepositoryList(repos)); + model.put("Dependencies", buildDependencyList(deps)); - context = context.replaceFirst("\\{\\{ \\.CamelDependencies }}", sb.toString()); - - // include docker/kubernetes with jib/jkube - context = enrichMavenPomJib(context, settings, profile); + // kubernetes/docker properties + enrichKubernetesModel(model, settings, profile); + String context = TemplateHelper.processTemplate(pomTemplateName, model); Files.writeString(pom, context); } - protected String enrichMavenPomJib(String context, Path settings, Path profile) throws Exception { - StringBuilder sb1 = new StringBuilder(); - StringBuilder sb2 = new StringBuilder(); - + private void enrichKubernetesModel(Map model, Path settings, Path profile) throws Exception { // is kubernetes included? Properties prop = new CamelCaseOrderedProperties(); if (Files.exists(profile)) { RuntimeUtil.loadProperties(prop, profile); } - // include additional build properties boolean jib = prop.stringPropertyNames().stream().anyMatch(s -> s.startsWith("jib.")); boolean jkube = prop.stringPropertyNames().stream().anyMatch(s -> s.startsWith("jkube.")); - // jib is used for docker and kubernetes, jkube is only used for kubernetes + + List> kubernetesProperties = new ArrayList<>(); if (jib || jkube) { - // include all jib/jkube/label properties String fromImage = null; for (String key : prop.stringPropertyNames()) { String value = prop.getProperty(key); @@ -295,62 +240,33 @@ protected String enrichMavenPomJib(String context, Path settings, Path profile) } boolean accept = key.startsWith("jkube.") || key.startsWith("jib.") || key.startsWith("label."); if (accept) { - sb1.append(String.format(" <%s>%s%n", key, value, key)); + kubernetesProperties.add(Map.of("key", key, "value", value)); } } - // from image is mandatory so use a default image if none provided if (fromImage == null) { fromImage = "mirror.gcr.io/library/eclipse-temurin:" + javaVersion + "-jre"; - sb1.append(String.format(" <%s>%s%n", "jib.from.image", fromImage, "jib.from.image")); + kubernetesProperties.add(Map.of("key", "jib.from.image", "value", fromImage)); } + } + model.put("KubernetesProperties", kubernetesProperties); - InputStream is = ExportCamelMain.class.getClassLoader().getResourceAsStream("templates/main-docker-pom.tmpl"); - String context2 = IOHelper.loadText(is); - IOHelper.close(is); - - context2 = context2.replaceFirst("\\{\\{ \\.JibMavenPluginVersion }}", - jibMavenPluginVersion(settings, prop)); - - // image from/to auth - String auth = ""; - if (prop.stringPropertyNames().stream().anyMatch(s -> s.startsWith("jib.from.auth."))) { - is = ExportCamelMain.class.getClassLoader().getResourceAsStream("templates/main-docker-from-auth-pom.tmpl"); - auth = IOHelper.loadText(is); - IOHelper.close(is); - } - context2 = context2.replace("{{ .JibFromImageAuth }}", auth); - auth = ""; - if (prop.stringPropertyNames().stream().anyMatch(s -> s.startsWith("jib.to.auth."))) { - is = ExportCamelMain.class.getClassLoader().getResourceAsStream("templates/main-docker-to-auth-pom.tmpl"); - auth = IOHelper.loadText(is); - IOHelper.close(is); - } - context2 = context2.replace("{{ .JibToImageAuth }}", auth); - // http port setting + model.put("hasJib", jib || jkube); + model.put("hasJkube", jkube); + if (jib || jkube) { + model.put("JibMavenPluginVersion", jibMavenPluginVersion(settings, prop)); + model.put("hasJibFromAuth", + prop.stringPropertyNames().stream().anyMatch(s -> s.startsWith("jib.from.auth."))); + model.put("hasJibToAuth", + prop.stringPropertyNames().stream().anyMatch(s -> s.startsWith("jib.to.auth."))); int port = httpServerPort(settings); if (port == -1) { port = 8080; } - context2 = context2.replaceFirst("\\{\\{ \\.Port }}", String.valueOf(port)); - sb2.append(context2); - // jkube is only used for kubernetes - if (jkube) { - is = ExportCamelMain.class.getClassLoader().getResourceAsStream("templates/main-jkube-pom.tmpl"); - String context3 = IOHelper.loadText(is); - IOHelper.close(is); - context3 = context3.replaceFirst("\\{\\{ \\.JkubeMavenPluginVersion }}", - jkubeMavenPluginVersion(settings, prop)); - sb2.append(context3); - } + model.put("Port", String.valueOf(port)); + } + if (jkube) { + model.put("JkubeMavenPluginVersion", jkubeMavenPluginVersion(settings, prop)); } - - // remove empty lines - String s1 = sb1.toString().replaceAll("(\\r?\\n){2,}", "\n"); - String s2 = sb2.toString().replaceAll("(\\r?\\n){2,}", "\n"); - - context = context.replace("{{ .CamelKubernetesProperties }}", s1); - context = context.replace("{{ .CamelKubernetesPlugins }}", s2); - return context; } @Override @@ -392,18 +308,15 @@ protected Set resolveDependencies(Path settings, Path profile) throws Ex } private void createMainClassSource(Path srcJavaDir, String packageName, String mainClassname) throws Exception { - InputStream is = ExportCamelMain.class.getClassLoader().getResourceAsStream("templates/main.tmpl"); - String context = IOHelper.loadText(is); - IOHelper.close(is); - + Map model = new HashMap<>(); if (packageName != null) { - context = context.replaceFirst("\\{\\{ \\.PackageName }}", "package " + packageName + ";"); - } else { - context = context.replaceFirst("\\{\\{ \\.PackageName }}", ""); + model.put("PackageName", "package " + packageName + ";"); } - context = context.replaceAll("\\{\\{ \\.MainClassname }}", mainClassname); + model.put("MainClassname", mainClassname); + + String content = TemplateHelper.processTemplate("main.ftl", model); Path outputFile = srcJavaDir.resolve(mainClassname + ".java"); - Files.writeString(outputFile, context); + Files.writeString(outputFile, content); } @Override diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportQuarkus.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportQuarkus.java index 9b58bf18dad8f..bf476d6e72bc8 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportQuarkus.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportQuarkus.java @@ -35,12 +35,12 @@ import org.apache.camel.dsl.jbang.core.common.CommandLineHelper; import org.apache.camel.dsl.jbang.core.common.PathUtils; import org.apache.camel.dsl.jbang.core.common.RuntimeUtil; +import org.apache.camel.dsl.jbang.core.common.TemplateHelper; import org.apache.camel.dsl.jbang.core.common.VersionHelper; import org.apache.camel.tooling.maven.MavenGav; import org.apache.camel.tooling.model.ArtifactModel; import org.apache.camel.util.CamelCaseOrderedProperties; import org.apache.camel.util.FileUtil; -import org.apache.camel.util.IOHelper; import org.apache.camel.util.StringHelper; import static org.apache.camel.dsl.jbang.core.commands.ExportHelper.exportPackageName; @@ -50,7 +50,7 @@ class ExportQuarkus extends Export { public ExportQuarkus(CamelJBangMain main) { super(main); - pomTemplateName = "quarkus-pom.tmpl"; + pomTemplateName = "quarkus-pom.ftl"; } @Override @@ -313,23 +313,18 @@ protected void copyDockerFiles(String buildDir) throws Exception { @Override protected void copyReadme(String buildDir, String appJar) throws Exception { String[] ids = gav.split(":"); - InputStream is = ExportCamelMain.class.getClassLoader().getResourceAsStream("templates/readme.native.md.tmpl"); - String context = IOHelper.loadText(is); - IOHelper.close(is); + Map model = new HashMap<>(); + model.put("ArtifactId", ids[1]); + model.put("Version", ids[2]); + model.put("AppRuntimeJar", appJar); - context = context.replaceAll("\\{\\{ \\.ArtifactId }}", ids[1]); - context = context.replaceAll("\\{\\{ \\.Version }}", ids[2]); - context = context.replaceAll("\\{\\{ \\.AppRuntimeJar }}", appJar); + String context = TemplateHelper.processTemplate("readme.native.md.ftl", model); Files.writeString(Path.of(buildDir).resolve("readme.md"), context); } private void createMavenPom(Path settings, Path pom, Set deps) throws Exception { String[] ids = gav.split(":"); - InputStream is = ExportQuarkus.class.getClassLoader().getResourceAsStream("templates/" + pomTemplateName); - String context = IOHelper.loadText(is); - IOHelper.close(is); - Properties prop = new CamelCaseOrderedProperties(); RuntimeUtil.loadProperties(prop, settings); // quarkus controls the camel version @@ -345,27 +340,30 @@ private void createMavenPom(Path settings, Path pom, Set deps) throws Ex mp = "9876"; } - context = context.replaceAll("\\{\\{ \\.GroupId }}", ids[0]); - context = context.replaceAll("\\{\\{ \\.ArtifactId }}", ids[1]); - context = context.replaceAll("\\{\\{ \\.Version }}", ids[2]); - context = context.replaceAll("\\{\\{ \\.QuarkusGroupId }}", quarkusGroupId); - context = context.replaceAll("\\{\\{ \\.QuarkusArtifactId }}", quarkusArtifactId); - context = context.replaceAll("\\{\\{ \\.QuarkusVersion }}", quarkusVersion); - context = context.replaceAll("\\{\\{ \\.QuarkusPackageType }}", quarkusPackageType); - context = context.replaceAll("\\{\\{ \\.QuarkusManagementPort }}", mp); - context = context.replaceAll("\\{\\{ \\.JavaVersion }}", javaVersion); - context = context.replaceAll("\\{\\{ \\.CamelVersion }}", camelVersion); - context = context.replaceAll("\\{\\{ \\.ProjectBuildOutputTimestamp }}", this.getBuildMavenProjectDate()); - - context = replaceBuildProperties(context); - - if (repos == null || repos.isEmpty()) { - context = context.replaceFirst("\\{\\{ \\.MavenRepositories }}", ""); - } else { - String s = mavenRepositoriesAsPomXml(repos); - context = context.replaceFirst("\\{\\{ \\.MavenRepositories }}", s); - } + // Build template data model + List> depList = buildQuarkusDependencyList(deps, catalog); + + Map model = new HashMap<>(); + model.put("GroupId", ids[0]); + model.put("ArtifactId", ids[1]); + model.put("Version", ids[2]); + model.put("QuarkusGroupId", quarkusGroupId); + model.put("QuarkusArtifactId", quarkusArtifactId); + model.put("QuarkusVersion", quarkusVersion); + model.put("QuarkusPackageType", quarkusPackageType); + model.put("QuarkusManagementPort", mp); + model.put("JavaVersion", javaVersion); + model.put("CamelVersion", camelVersion); + model.put("ProjectBuildOutputTimestamp", this.getBuildMavenProjectDate()); + model.put("BuildProperties", formatBuildProperties()); + model.put("Repositories", buildRepositoryList(repos)); + model.put("Dependencies", depList); + + String context = TemplateHelper.processTemplate(pomTemplateName, model); + Files.writeString(pom, context); + } + private List> buildQuarkusDependencyList(Set deps, CamelCatalog catalog) { List gavs = new ArrayList<>(); for (String dep : deps) { MavenGav gav = parseMavenGav(dep); @@ -394,41 +392,23 @@ private void createMavenPom(Path settings, Path pom, Set deps) throws Ex // sort artifacts gavs.sort(mavenGavComparator()); - StringBuilder sb = new StringBuilder(); + List> result = new ArrayList<>(); for (MavenGav gav : gavs) { - //Special case, quarkus-pom.tmpl already have them included. + // Special case, quarkus-pom.ftl already has them included. if ("camel-quarkus-core".equals(gav.getArtifactId()) || "camel-quarkus-microprofile-health".equals(gav.getArtifactId())) { continue; } - sb.append(" \n"); - sb.append(" ").append(gav.getGroupId()).append("\n"); - sb.append(" ").append(gav.getArtifactId()).append("\n"); - if (gav.getVersion() != null) { - sb.append(" ").append(gav.getVersion()).append("\n"); - } - if (gav.getScope() != null) { - sb.append(" ").append(gav.getScope()).append("\n"); - } - if ("lib".equals(gav.getPackaging())) { - // special for lib JARs - sb.append(" system\n"); - sb.append(" \\$\\{project.basedir}/lib/").append(gav.getArtifactId()).append("-") - .append(gav.getVersion()).append(".jar\n"); - } else if ("camel-kamelets-utils".equals(gav.getArtifactId())) { - // special for camel-kamelets-utils - sb.append(" \n"); - sb.append(" \n"); - sb.append(" org.apache.camel\n"); - sb.append(" *\n"); - sb.append(" \n"); - sb.append(" \n"); - } - sb.append(" \n"); + Map dep = new HashMap<>(); + dep.put("groupId", gav.getGroupId()); + dep.put("artifactId", gav.getArtifactId()); + dep.put("version", gav.getVersion()); + dep.put("scope", gav.getScope()); + dep.put("isLib", "lib".equals(gav.getPackaging())); + dep.put("isKameletsUtils", "camel-kamelets-utils".equals(gav.getArtifactId())); + result.add(dep); } - context = context.replaceFirst("\\{\\{ \\.CamelDependencies }}", sb.toString()); - - Files.writeString(pom, context); + return result; } @Override 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 index 405dc7b48c07b..7312187937590 100644 --- 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 @@ -17,7 +17,6 @@ package org.apache.camel.dsl.jbang.core.commands; import java.io.File; -import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.charset.StandardCharsets; @@ -25,7 +24,9 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Properties; import java.util.Set; @@ -35,6 +36,7 @@ import org.apache.camel.dsl.jbang.core.common.CommandLineHelper; import org.apache.camel.dsl.jbang.core.common.PathUtils; import org.apache.camel.dsl.jbang.core.common.RuntimeUtil; +import org.apache.camel.dsl.jbang.core.common.TemplateHelper; import org.apache.camel.dsl.jbang.core.common.VersionHelper; import org.apache.camel.tooling.maven.MavenGav; import org.apache.camel.tooling.model.ArtifactModel; @@ -48,7 +50,7 @@ class ExportSpringBoot extends Export { public ExportSpringBoot(CamelJBangMain main) { super(main); - pomTemplateName = "spring-boot-pom.tmpl"; + pomTemplateName = "spring-boot-pom.ftl"; } @Override @@ -190,16 +192,83 @@ private void createMavenPom(Path settings, Path profile, Path pom, Set d camelVersion = VersionHelper.extractCamelVersion(); } - // First try to load a specialized template from the catalog, if the catalog does not provide it - // fallback to the template defined in camel-jbang-core - String context; - InputStream template = catalog.loadResource("camel-jbang", pomTemplateName); - if (template != null) { - context = IOHelper.loadText(template); - } else { - context = readResourceTemplate("templates/" + pomTemplateName); + // Check if catalog provides a custom template (backward compatibility) + InputStream catalogTemplate = catalog.loadResource("camel-jbang", pomTemplateName); + if (catalogTemplate != null) { + // Catalog provides a custom template - use legacy regex-based processing + String context = IOHelper.loadText(catalogTemplate); + IOHelper.close(catalogTemplate); + context = processLegacyPomTemplate(context, ids, repos, deps, catalog); + IOHelper.writeText(context, Files.newOutputStream(pom)); + return; + } + + // Build template data model + List> depList = buildSpringBootDependencyList(deps, catalog); + + Map model = new HashMap<>(); + model.put("GroupId", ids[0]); + model.put("ArtifactId", ids[1]); + model.put("Version", ids[2]); + model.put("SpringBootVersion", springBootVersion); + model.put("JavaVersion", javaVersion); + model.put("CamelVersion", camelVersion); + model.put("CamelSpringBootVersion", + Objects.requireNonNullElseGet(camelSpringBootVersion, () -> camelVersion)); + model.put("ProjectBuildOutputTimestamp", this.getBuildMavenProjectDate()); + model.put("BuildProperties", formatBuildProperties()); + model.put("Repositories", buildRepositoryList(repos)); + model.put("Dependencies", depList); + + String context = TemplateHelper.processTemplate(pomTemplateName, model); + IOHelper.writeText(context, Files.newOutputStream(pom)); + } + + private List> buildSpringBootDependencyList(Set deps, CamelCatalog catalog) { + List gavs = new ArrayList<>(); + for (String dep : deps) { + MavenGav gav = parseMavenGav(dep); + String gid = gav.getGroupId(); + String aid = gav.getArtifactId(); + + // transform to camel-spring-boot starter GAV + if ("org.apache.camel".equals(gid)) { + ArtifactModel am = catalog.modelFromMavenGAV("org.apache.camel.springboot", aid + "-starter", null); + if (am != null) { + gav.setGroupId(am.getGroupId()); + gav.setArtifactId(am.getArtifactId()); + gav.setVersion(null); + } else { + gav.setVersion(camelVersion); + } + } + if ("org.springframework.boot".equals(gid)) { + gav.setVersion(null); + } + gavs.add(gav); + } + + gavs.sort(mavenGavComparator()); + + List> result = new ArrayList<>(); + for (MavenGav gav : gavs) { + Map dep = new HashMap<>(); + dep.put("groupId", gav.getGroupId()); + dep.put("artifactId", gav.getArtifactId()); + dep.put("version", gav.getVersion()); + dep.put("scope", gav.getScope()); + dep.put("isLib", "lib".equals(gav.getPackaging())); + dep.put("isKameletsUtils", "camel-kamelets-utils".equals(gav.getArtifactId())); + result.add(dep); } + return result; + } + /** + * Legacy processing for catalog-provided templates that use {{ .Name }} syntax. + */ + private String processLegacyPomTemplate( + String context, String[] ids, String repos, Set deps, CamelCatalog catalog) { context = context.replaceAll("\\{\\{ \\.GroupId }}", ids[0]); context = context.replaceAll("\\{\\{ \\.ArtifactId }}", ids[1]); context = context.replaceAll("\\{\\{ \\.Version }}", ids[2]); @@ -209,13 +278,12 @@ private void createMavenPom(Path settings, Path profile, Path pom, Set d context = context.replaceAll("\\{\\{ \\.CamelSpringBootVersion }}", Objects.requireNonNullElseGet(camelSpringBootVersion, () -> camelVersion)); context = context.replaceFirst("\\{\\{ \\.ProjectBuildOutputTimestamp }}", this.getBuildMavenProjectDate()); - context = replaceBuildProperties(context); if (repos == null || repos.isEmpty()) { context = context.replaceFirst("\\{\\{ \\.MavenRepositories }}", ""); } else { - String s = mavenRepositoriesAsPomXml(repos); + String s = legacyMavenRepositoriesAsPomXml(repos); context = context.replaceFirst("\\{\\{ \\.MavenRepositories }}", s); } @@ -224,28 +292,21 @@ private void createMavenPom(Path settings, Path profile, Path pom, Set d MavenGav gav = parseMavenGav(dep); String gid = gav.getGroupId(); String aid = gav.getArtifactId(); - - // transform to camel-spring-boot starter GAV if ("org.apache.camel".equals(gid)) { ArtifactModel am = catalog.modelFromMavenGAV("org.apache.camel.springboot", aid + "-starter", null); if (am != null) { - // use spring-boot starter gav.setGroupId(am.getGroupId()); gav.setArtifactId(am.getArtifactId()); - gav.setVersion(null); // uses BOM so version should not be included + gav.setVersion(null); } else { - // there is no spring boot starter so use plain camel gav.setVersion(camelVersion); } } - // use spring-boot version from BOM if ("org.springframework.boot".equals(gid)) { - gav.setVersion(null); // uses BOM so version should not be included + gav.setVersion(null); } gavs.add(gav); } - - // sort artifacts gavs.sort(mavenGavComparator()); StringBuilder sb = new StringBuilder(); @@ -260,12 +321,10 @@ private void createMavenPom(Path settings, Path profile, Path pom, Set d sb.append(" ").append(gav.getScope()).append("\n"); } if ("lib".equals(gav.getPackaging())) { - // special for lib JARs sb.append(" system\n"); sb.append(" \\$\\{project.basedir}/lib/").append(gav.getArtifactId()).append("-") .append(gav.getVersion()).append(".jar\n"); } else if ("camel-kamelets-utils".equals(gav.getArtifactId())) { - // special for camel-kamelets-utils sb.append(" \n"); sb.append(" \n"); sb.append(" org.apache.camel\n"); @@ -276,8 +335,48 @@ private void createMavenPom(Path settings, Path profile, Path pom, Set d sb.append(" \n"); } context = context.replaceFirst("\\{\\{ \\.CamelDependencies }}", sb.toString()); + return context; + } - IOHelper.writeText(context, Files.newOutputStream(pom)); + /** + * Legacy method for backward compatibility with catalog-provided templates. + */ + private static String legacyMavenRepositoriesAsPomXml(String repos) { + StringBuilder sb = new StringBuilder(); + int i = 1; + sb.append(" \n"); + for (String repo : repos.split(",")) { + sb.append(" \n"); + sb.append(" custom").append(i++).append("\n"); + sb.append(" ").append(repo).append("\n"); + if (repo.contains("snapshots")) { + sb.append(" \n"); + sb.append(" false\n"); + sb.append(" \n"); + sb.append(" \n"); + sb.append(" true\n"); + sb.append(" \n"); + } + sb.append(" \n"); + } + sb.append(" \n"); + sb.append(" \n"); + for (String repo : repos.split(",")) { + sb.append(" \n"); + sb.append(" custom").append(i++).append("\n"); + sb.append(" ").append(repo).append("\n"); + if (repo.contains("snapshots")) { + sb.append(" \n"); + sb.append(" false\n"); + sb.append(" \n"); + sb.append(" \n"); + sb.append(" true\n"); + sb.append(" \n"); + } + sb.append(" \n"); + } + sb.append(" \n"); + return sb.toString(); } @Override @@ -301,12 +400,12 @@ protected Set resolveDependencies(Path settings, Path profile) throws Ex } private void createMainClassSource(Path srcJavaDir, String packageName, String mainClassname) throws Exception { - String context = readResourceTemplate("templates/spring-boot-main.tmpl"); + Map model = new HashMap<>(); + model.put("PackageName", packageName); + model.put("MainClassname", mainClassname); - context = context.replaceFirst("\\{\\{ \\.PackageName }}", packageName); - context = context.replaceAll("\\{\\{ \\.MainClassname }}", mainClassname); - IOHelper.writeText(context, - Files.newOutputStream(srcJavaDir.resolve(mainClassname + ".java"))); + String content = TemplateHelper.processTemplate("spring-boot-main.ftl", model); + IOHelper.writeText(content, Files.newOutputStream(srcJavaDir.resolve(mainClassname + ".java"))); } @Override @@ -335,11 +434,4 @@ protected String applicationPropertyLine(String key, String value) { return super.applicationPropertyLine(key, value); } - private String readResourceTemplate(String name) throws IOException { - InputStream is = ExportSpringBoot.class.getClassLoader().getResourceAsStream(name); - String text = IOHelper.loadText(is); - IOHelper.close(is); - return text; - } - } diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Init.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Init.java index 6d965cd2dd894..a0f65cf76e467 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Init.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Init.java @@ -154,6 +154,10 @@ private int execute() throws Exception { } if (is == null) { + is = Init.class.getClassLoader().getResourceAsStream("templates/" + ext + ".ftl"); + } + if (is == null) { + // fallback to old .tmpl format is = Init.class.getClassLoader().getResourceAsStream("templates/" + ext + ".tmpl"); } if (is == null) { @@ -166,6 +170,8 @@ private int execute() throws Exception { } String content = IOHelper.loadText(is); IOHelper.close(is); + // Strip FreeMarker license header comment (appears as literal text in .ftl files) + content = content.replaceFirst("(?s)\\A<#--.*?-->\\s*", ""); if (!directory.equals(".")) { if (cleanDirectory) { @@ -179,7 +185,8 @@ private int execute() throws Exception { if (!targetPath.isAbsolute()) { targetPath = Paths.get(directory, file); } - content = content.replaceFirst("\\{\\{ \\.Name }}", name); + content = content.replace("{{ .Name }}", name); + content = content.replace("[=Name]", name); if (fromKamelet != null) { content = content.replaceFirst("\\s\\sname:\\s" + fromKamelet, " name: " + name); content = content.replaceFirst("camel.apache.org/provider: \"Apache Software Foundation\"", @@ -201,7 +208,8 @@ private int execute() throws Exception { } if ("java".equals(ext)) { String packageDeclaration = computeJavaPackageDeclaration(targetPath); - content = content.replaceFirst("\\{\\{ \\.PackageDeclaration }}", packageDeclaration); + content = content.replace("{{ .PackageDeclaration }}", packageDeclaration); + content = content.replace("[=PackageDeclaration]", packageDeclaration); } // in case of using relative paths in the file name Path parentPath = targetPath.getParent(); 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 1c23567cc89e5..2b7fb76be4532 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 @@ -60,6 +60,7 @@ import org.apache.camel.dsl.jbang.core.common.Source; import org.apache.camel.dsl.jbang.core.common.SourceHelper; import org.apache.camel.dsl.jbang.core.common.SourceScheme; +import org.apache.camel.dsl.jbang.core.common.TemplateHelper; import org.apache.camel.dsl.jbang.core.common.VersionHelper; import org.apache.camel.main.KameletMain; import org.apache.camel.main.download.DownloadListener; @@ -1622,16 +1623,9 @@ protected int runDebug(KameletMain main) throws Exception { } protected int runCustomCamelVersion(KameletMain main) throws Exception { - InputStream is = Run.class.getClassLoader().getResourceAsStream("templates/run-custom-camel-version.tmpl"); - String content = IOHelper.loadText(is); - IOHelper.close(is); - - content = content.replaceFirst("\\{\\{ \\.JavaVersion }}", "21"); - if (repositories != null) { - content = content.replaceFirst("\\{\\{ \\.MavenRepositories }}", "//REPOS " + repositories); - } else { - content = content.replaceFirst("\\{\\{ \\.MavenRepositories }}", ""); - } + Map model = new HashMap<>(); + model.put("JavaVersion", "21"); + model.put("MavenRepositories", repositories != null ? "//REPOS " + repositories : ""); // use custom distribution of camel StringBuilder sb = new StringBuilder(); @@ -1645,18 +1639,20 @@ protected int runCustomCamelVersion(KameletMain main) throws Exception { if (VersionHelper.isGE(camelVersion, "3.19.0")) { sb.append(String.format("//DEPS org.apache.camel:camel-cli-connector:%s%n", camelVersion)); } - content = content.replaceFirst("\\{\\{ \\.CamelDependencies }}", sb.toString()); + model.put("CamelDependencies", sb.toString()); // use apache distribution of camel-jbang/github-resolver String v = camelVersion.substring(0, camelVersion.lastIndexOf('.')); sb = new StringBuilder(); sb.append(String.format("//DEPS org.apache.camel:camel-jbang-core:%s%n", v)); sb.append(String.format("//DEPS org.apache.camel:camel-resourceresolver-github:%s%n", v)); - content = content.replaceFirst("\\{\\{ \\.CamelJBangDependencies }}", sb.toString()); + model.put("CamelJBangDependencies", sb.toString()); sb = new StringBuilder(); sb.append(String.format("//DEPS org.apache.camel.kamelets:camel-kamelets:%s%n", kameletsVersion)); - content = content.replaceFirst("\\{\\{ \\.CamelKameletsDependencies }}", sb.toString()); + model.put("CamelKameletsDependencies", sb.toString()); + + String content = TemplateHelper.processTemplate("run-custom-camel-version.ftl", model); String fn = CommandLineHelper.CAMEL_JBANG_WORK_DIR + "/CustomCamelJBang.java"; Files.writeString(Paths.get(fn), content); @@ -1723,9 +1719,6 @@ protected int runKameletMain(KameletMain main) throws Exception { private String loadFromCode(String code, String name, boolean file) throws IOException { String fn = CommandLineHelper.CAMEL_JBANG_WORK_DIR + "/" + name + ".java"; - InputStream is = Run.class.getClassLoader().getResourceAsStream("templates/code-java.tmpl"); - String content = IOHelper.loadText(is); - IOHelper.close(is); if (!file) { // need to replace single quote as double quotes (from input string) code = code.replace("'", "\""); @@ -1735,8 +1728,10 @@ private String loadFromCode(String code, String name, boolean file) throws IOExc if (!code.endsWith(";")) { code = code + ";"; } - content = StringHelper.replaceFirst(content, "{{ .Name }}", name); - content = StringHelper.replaceFirst(content, "{{ .Code }}", code); + Map model = new HashMap<>(); + model.put("Name", name); + model.put("Code", code); + String content = TemplateHelper.processTemplate("code-java.ftl", model); Files.writeString(Paths.get(fn), content); return "file:" + fn; } @@ -1918,11 +1913,10 @@ private void generateOpenApi() throws Exception { throw new FileNotFoundException("Cannot find file: " + filePath); } - try (InputStream is = Run.class.getClassLoader().getResourceAsStream("templates/rest-dsl.yaml.tmpl")) { - String content = IOHelper.loadText(is); - String onlyName = filePath.toString(); - content = content.replaceFirst("\\{\\{ \\.Spec }}", onlyName); - + { + Map model = new HashMap<>(); + model.put("Spec", filePath.toString()); + String content = TemplateHelper.processTemplate("rest-dsl.yaml.ftl", model); Files.writeString(Paths.get(OPENAPI_GENERATED_FILE), content); // we need to include the spec on the classpath diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/TemplateHelper.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/TemplateHelper.java new file mode 100644 index 0000000000000..c7b176712fd0e --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/TemplateHelper.java @@ -0,0 +1,76 @@ +/* + * 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.common; + +import java.io.IOException; +import java.io.StringWriter; +import java.util.Map; +import java.util.regex.Pattern; + +import freemarker.cache.ClassTemplateLoader; +import freemarker.template.Configuration; +import freemarker.template.Template; +import freemarker.template.TemplateException; +import freemarker.template.TemplateExceptionHandler; + +/** + * Utility for processing FreeMarker templates used in code generation. + *

+ * Uses square bracket syntax for both interpolation ([=name]) and directives ([#if]...[/#if]) to avoid conflicts with + * ${...} (Maven/Camel expressions) and <...> (XML tags) in generated content. + */ +public final class TemplateHelper { + + // Matches <#-- ... --> comment blocks that appear as literal text in square bracket tag syntax mode + private static final Pattern ANGLE_BRACKET_COMMENT = Pattern.compile("\\A<#--.*?-->\\s*", Pattern.DOTALL); + + private static final Configuration CFG; + + static { + CFG = new Configuration(Configuration.VERSION_2_3_34); + CFG.setTemplateLoader(new ClassTemplateLoader(TemplateHelper.class, "/templates")); + CFG.setDefaultEncoding("UTF-8"); + CFG.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER); + CFG.setLogTemplateExceptions(false); + // Use square bracket syntax to avoid conflicts with ${...} and <...> in templates + CFG.setInterpolationSyntax(Configuration.SQUARE_BRACKET_INTERPOLATION_SYNTAX); + CFG.setTagSyntax(Configuration.SQUARE_BRACKET_TAG_SYNTAX); + } + + private TemplateHelper() { + } + + /** + * Process a FreeMarker template from classpath resources/templates/ directory. + * + * @param templateName the template file name (e.g. "main-pom.ftl") + * @param model the data model + * @return the processed template output + */ + public static String processTemplate(String templateName, Map model) throws IOException { + try { + Template template = CFG.getTemplate(templateName); + StringWriter writer = new StringWriter(); + template.process(model, writer); + // Strip any <#-- ... --> license header that appears as literal text + // (angle bracket comments are not recognized in square bracket tag syntax mode) + return ANGLE_BRACKET_COMMENT.matcher(writer.toString()).replaceFirst(""); + } catch (TemplateException e) { + throw new IOException("Failed to process template: " + templateName, e); + } + } +} diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/Dockerfile21.tmpl b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/Dockerfile21.ftl similarity index 84% rename from dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/Dockerfile21.tmpl rename to dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/Dockerfile21.ftl index 72ce5d36dd79e..9939f0bba7286 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/Dockerfile21.tmpl +++ b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/Dockerfile21.ftl @@ -1,3 +1,21 @@ +<#-- + + 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. + +--> # # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with @@ -19,8 +37,8 @@ # This Dockerfile is used in order to build a container that runs the Camel application # # ./mvnw clean package -# docker build -f src/main/docker/Dockerfile -t {{ .ArtifactId }}:{{ .Version }} . -# docker run -it {{ .ArtifactId }}:{{ .Version }} +# docker build -f src/main/docker/Dockerfile -t [=ArtifactId]:[=Version] . +# docker run -it [=ArtifactId]:[=Version] # # This image uses the `run-java.sh` script to run the application. # This scripts computes the command line to execute your Java application, and @@ -84,14 +102,13 @@ ### FROM registry.access.redhat.com/ubi9/openjdk-21:1.23 -COPY --chown=185 target/{{ .AppJar }} /deployments/ +COPY --chown=185 target/[=AppJar] /deployments/ # Uncomment to expose any given port # EXPOSE 8080 USER 185 # Uncomment to provide any Java option # ENV JAVA_OPTS="" -ENV JAVA_APP_JAR="/deployments/{{ .AppJar }}" +ENV JAVA_APP_JAR="/deployments/[=AppJar]" ENTRYPOINT [ "/opt/jboss/container/java/run/run-java.sh" ] - diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/Dockerfile25.tmpl b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/Dockerfile25.ftl similarity index 52% rename from dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/Dockerfile25.tmpl rename to dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/Dockerfile25.ftl index cc5ff1d27de75..506abc971d602 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/Dockerfile25.tmpl +++ b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/Dockerfile25.ftl @@ -1,3 +1,21 @@ +<#-- + + 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. + +--> # # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with @@ -19,8 +37,8 @@ # This Dockerfile is used in order to build a container that runs the Camel application # # ./mvnw clean package -# docker build -f src/main/docker/Dockerfile -t {{ .ArtifactId }}:{{ .Version }} . -# docker run -it {{ .ArtifactId }}:{{ .Version }} +# docker build -f src/main/docker/Dockerfile -t [=ArtifactId]:[=Version] . +# docker run -it [=ArtifactId]:[=Version] # ### FROM eclipse-temurin:25-jre-ubi9-minimal @@ -29,7 +47,7 @@ ENV LANGUAGE='en_US:en' RUN mkdir /deployments -COPY --chown=185 target/{{ .AppJar }} /deployments/ +COPY --chown=185 target/[=AppJar] /deployments/ # Uncomment to expose any given port # EXPOSE 8080 @@ -38,4 +56,4 @@ USER 185 # ENV JAVA_OPTS="" WORKDIR /deployments -ENTRYPOINT exec java $JAVA_OPTS -jar {{ .AppJar }} +ENTRYPOINT exec java $JAVA_OPTS -jar [=AppJar] diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/code-java.ftl b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/code-java.ftl new file mode 100644 index 0000000000000..27c36ddc83a93 --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/code-java.ftl @@ -0,0 +1,38 @@ +<#-- + + 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. + +--> +import java.time.*; +import java.util.*; +import java.util.concurrent.*; + +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.CamelContext; +import org.apache.camel.Exchange; +import org.apache.camel.Message; +import org.apache.camel.model.*; +import org.apache.camel.model.rest.*; +import org.apache.camel.spi.*; +import org.apache.camel.*; + +public class [=Name] extends RouteBuilder { + + @Override + public void configure() throws Exception { + [=Code] + } +} diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/code-java.tmpl b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/code-java.tmpl deleted file mode 100644 index e051a368348fc..0000000000000 --- a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/code-java.tmpl +++ /dev/null @@ -1,20 +0,0 @@ -import java.time.*; -import java.util.*; -import java.util.concurrent.*; - -import org.apache.camel.builder.RouteBuilder; -import org.apache.camel.CamelContext; -import org.apache.camel.Exchange; -import org.apache.camel.Message; -import org.apache.camel.model.*; -import org.apache.camel.model.rest.*; -import org.apache.camel.spi.*; -import org.apache.camel.*; - -public class {{ .Name }} extends RouteBuilder { - - @Override - public void configure() throws Exception { - {{ .Code }} - } -} diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/init-pipe.yaml.ftl b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/init-pipe.yaml.ftl new file mode 100644 index 0000000000000..96c7f29b1708b --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/init-pipe.yaml.ftl @@ -0,0 +1,35 @@ +<#-- + + 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. + +--> +apiVersion: camel.apache.org/v1 +kind: Pipe +metadata: + name: [=Name] +spec: + source: + ref: + kind: Kamelet + apiVersion: camel.apache.org/v1 + name: timer-source + properties: + message: Hello World + sink: + ref: + kind: Kamelet + apiVersion: camel.apache.org/v1 + name: log-sink diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/init-pipe.yaml.tmpl b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/init-pipe.yaml.tmpl deleted file mode 100644 index 9e9beffcc0764..0000000000000 --- a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/init-pipe.yaml.tmpl +++ /dev/null @@ -1,17 +0,0 @@ -apiVersion: camel.apache.org/v1 -kind: Pipe -metadata: - name: {{ .Name }} -spec: - source: - ref: - kind: Kamelet - apiVersion: camel.apache.org/v1 - name: timer-source - properties: - message: Hello World - sink: - ref: - kind: Kamelet - apiVersion: camel.apache.org/v1 - name: log-sink \ No newline at end of file diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/integration.yaml.ftl b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/integration.yaml.ftl new file mode 100644 index 0000000000000..50f8e8a2d2b4a --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/integration.yaml.ftl @@ -0,0 +1,32 @@ +<#-- + + 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. + +--> +apiVersion: camel.apache.org/v1 +kind: Integration +metadata: + name: [=Name] +spec: + flows: + - from: + uri: "timer:yaml" + parameters: + period: "1000" + steps: + - setBody: + constant: "Hello Camel from yaml" + - log: "${body}" diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/integration.yaml.tmpl b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/integration.yaml.tmpl deleted file mode 100644 index 71a6b9d3d5af9..0000000000000 --- a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/integration.yaml.tmpl +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: camel.apache.org/v1 -kind: Integration -metadata: - name: {{ .Name }} -spec: - flows: - - from: - uri: "timer:yaml" - parameters: - period: "1000" - steps: - - setBody: - constant: "Hello Camel from yaml" - - log: "${body}" diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/java.ftl b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/java.ftl new file mode 100644 index 0000000000000..a9f403628cf87 --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/java.ftl @@ -0,0 +1,30 @@ +<#-- + + 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. + +--> +[=PackageDeclaration]import org.apache.camel.builder.RouteBuilder; + +public class [=Name] extends RouteBuilder { + + @Override + public void configure() throws Exception { + from("timer:java?period=1000") + .setBody() + .simple("Hello Camel from ${routeId}") + .log("${body}"); + } +} diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/java.tmpl b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/java.tmpl deleted file mode 100644 index 1f922f1e6e79e..0000000000000 --- a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/java.tmpl +++ /dev/null @@ -1,12 +0,0 @@ -{{ .PackageDeclaration }}import org.apache.camel.builder.RouteBuilder; - -public class {{ .Name }} extends RouteBuilder { - - @Override - public void configure() throws Exception { - from("timer:java?period=1000") - .setBody() - .simple("Hello Camel from ${routeId}") - .log("${body}"); - } -} diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/kamelet-action.yaml.ftl b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/kamelet-action.yaml.ftl new file mode 100644 index 0000000000000..26355e87bccd6 --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/kamelet-action.yaml.ftl @@ -0,0 +1,45 @@ +<#-- + + 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. + +--> +apiVersion: camel.apache.org/v1 +kind: Kamelet +metadata: + name: [=Name] + labels: + camel.apache.org/kamelet.type: "action" +spec: + definition: + title: "Delay Action" + description: Delay the processing using a specific amount of time + required: + - milliseconds + properties: + milliseconds: + title: Milliseconds + description: The number of milliseconds of delay + type: integer + example: 1000 + dependencies: + - "camel:core" + - "camel:kamelet" + template: + from: + uri: "kamelet:source" + steps: + - delay: + constant: "{{milliseconds}}" diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/kamelet-action.yaml.tmpl b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/kamelet-action.yaml.tmpl deleted file mode 100644 index 243d688c3ad46..0000000000000 --- a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/kamelet-action.yaml.tmpl +++ /dev/null @@ -1,27 +0,0 @@ -apiVersion: camel.apache.org/v1 -kind: Kamelet -metadata: - name: {{ .Name }} - labels: - camel.apache.org/kamelet.type: "action" -spec: - definition: - title: "Delay Action" - description: Delay the processing using a specific amount of time - required: - - milliseconds - properties: - milliseconds: - title: Milliseconds - description: The number of milliseconds of delay - type: integer - example: 1000 - dependencies: - - "camel:core" - - "camel:kamelet" - template: - from: - uri: "kamelet:source" - steps: - - delay: - constant: "{{milliseconds}}" \ No newline at end of file diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/kamelet-sink.yaml.ftl b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/kamelet-sink.yaml.ftl new file mode 100644 index 0000000000000..24cc8df0576fd --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/kamelet-sink.yaml.ftl @@ -0,0 +1,51 @@ +<#-- + + 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. + +--> +apiVersion: camel.apache.org/v1 +kind: Kamelet +metadata: + name: [=Name] + labels: + camel.apache.org/kamelet.type: "sink" +spec: + definition: + title: "Log Sink" + description: A sink that logs all data that it receives, useful for debugging purposes. + properties: + showHeaders: + title: Show Headers + description: Show the headers received + type: boolean + default: false + showStreams: + title: Show Streams + description: Show the stream bodies (they may not be available in following steps) + type: boolean + default: false + dependencies: + - "camel:kamelet" + - "camel:log" + template: + from: + uri: "kamelet:source" + steps: + - to: + uri: "log:info" + parameters: + showHeaders: "{{?showHeaders}}" + showStreams: "{{?showStreams}}" diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/kamelet-sink.yaml.tmpl b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/kamelet-sink.yaml.tmpl deleted file mode 100644 index 8d73cf2760554..0000000000000 --- a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/kamelet-sink.yaml.tmpl +++ /dev/null @@ -1,33 +0,0 @@ -apiVersion: camel.apache.org/v1 -kind: Kamelet -metadata: - name: {{ .Name }} - labels: - camel.apache.org/kamelet.type: "sink" -spec: - definition: - title: "Log Sink" - description: A sink that logs all data that it receives, useful for debugging purposes. - properties: - showHeaders: - title: Show Headers - description: Show the headers received - type: boolean - default: false - showStreams: - title: Show Streams - description: Show the stream bodies (they may not be available in following steps) - type: boolean - default: false - dependencies: - - "camel:kamelet" - - "camel:log" - template: - from: - uri: "kamelet:source" - steps: - - to: - uri: "log:info" - parameters: - showHeaders: "{{?showHeaders}}" - showStreams: "{{?showStreams}}" \ No newline at end of file diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/kamelet-source.yaml.tmpl b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/kamelet-source.yaml.ftl similarity index 50% rename from dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/kamelet-source.yaml.tmpl rename to dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/kamelet-source.yaml.ftl index a876236d52712..d40d80a6a8271 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/kamelet-source.yaml.tmpl +++ b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/kamelet-source.yaml.ftl @@ -1,7 +1,25 @@ +<#-- + + 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. + +--> apiVersion: camel.apache.org/v1 kind: Kamelet metadata: - name: {{ .Name }} + name: [=Name] labels: camel.apache.org/kamelet.type: "source" spec: diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/main-docker-from-auth-pom.tmpl b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/main-docker-from-auth-pom.tmpl deleted file mode 100644 index 9ec06c4aa2734..0000000000000 --- a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/main-docker-from-auth-pom.tmpl +++ /dev/null @@ -1,4 +0,0 @@ - - ${jib.from.auth.username} - ${jib.from.auth.password} - diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/main-docker-pom.tmpl b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/main-docker-pom.tmpl deleted file mode 100644 index cb11e0d6d18e5..0000000000000 --- a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/main-docker-pom.tmpl +++ /dev/null @@ -1,21 +0,0 @@ - - com.google.cloud.tools - jib-maven-plugin - {{ .JibMavenPluginVersion }} - - - ${jib.from.image} -{{ .JibFromImageAuth }} - - - ${jib.to.image} -{{ .JibToImageAuth }} - - packaged - - - {{ .Port }} - - - - diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/main-docker-to-auth-pom.tmpl b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/main-docker-to-auth-pom.tmpl deleted file mode 100644 index 9bd2171ee9102..0000000000000 --- a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/main-docker-to-auth-pom.tmpl +++ /dev/null @@ -1,4 +0,0 @@ - - ${jib.to.auth.username} - ${jib.to.auth.password} - diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/main-jkube-pom.tmpl b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/main-jkube-pom.tmpl deleted file mode 100644 index e016f531a145d..0000000000000 --- a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/main-jkube-pom.tmpl +++ /dev/null @@ -1,24 +0,0 @@ - - org.eclipse.jkube - kubernetes-maven-plugin - {{ .JkubeMavenPluginVersion }} - - - - ${jib.to.image} - - - - - - - - - ${label.runtime} - camel - - - - - - \ No newline at end of file diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/main-kubernetes-pom.tmpl b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/main-kubernetes-pom.ftl similarity index 72% rename from dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/main-kubernetes-pom.tmpl rename to dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/main-kubernetes-pom.ftl index 04b2e9607e4c0..784b56ef6a163 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/main-kubernetes-pom.tmpl +++ b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/main-kubernetes-pom.ftl @@ -1,15 +1,35 @@ +<#-- + + 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. + +--> 4.0.0 - {{ .GroupId }} - {{ .ArtifactId }} - {{ .Version }} + [=GroupId] + [=ArtifactId] + [=Version] - {{ .JavaVersion }} -{{ .BuildProperties }} + [=JavaVersion] +[#if BuildProperties?has_content] +[=BuildProperties] +[/#if] @@ -18,14 +38,47 @@ org.apache.camel camel-bom - {{ .CamelVersion }} + [=CamelVersion] pom import -{{ .MavenRepositories }} +[#if Repositories?has_content] + +[#list Repositories as repo] + + [=repo.id] + [=repo.url] +[#if repo.isSnapshot] + + false + + + true + +[/#if] + +[/#list] + + +[#list Repositories as repo] + + plugin-[=repo.id] + [=repo.url] +[#if repo.isSnapshot] + + false + + + true + +[/#if] + +[/#list] + +[/#if] @@ -33,7 +86,29 @@ camel-main -{{ .CamelDependencies }} +[#list Dependencies as dep] + + [=dep.groupId] + [=dep.artifactId] +[#if dep.version??] + [=dep.version] +[/#if] +[#if dep.isLib] + system + ${project.basedir}/lib/[=dep.artifactId]-[=dep.version].jar +[#elseif dep.scope??] + [=dep.scope] +[/#if] +[#if dep.isKameletsUtils] + + + org.apache.camel + * + + +[/#if] + +[/#list] @@ -79,9 +154,9 @@ org.apache.camel camel-maven-plugin - {{ .CamelVersion }} + [=CamelVersion] - {{ .MainClassname }} + [=MainClassname] @@ -95,7 +170,7 @@ org.apache.camel camel-repackager-maven-plugin - {{ .CamelVersion }} + [=CamelVersion] repackage-executable @@ -104,7 +179,7 @@ repackage - {{ .MainClassname }} + [=MainClassname] diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/main-pom.ftl b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/main-pom.ftl new file mode 100644 index 0000000000000..22e99ebf7b798 --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/main-pom.ftl @@ -0,0 +1,272 @@ +<#-- + + 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. + +--> + + + 4.0.0 + + [=GroupId] + [=ArtifactId] + [=Version] + + + [=JavaVersion] + [=ProjectBuildOutputTimestamp] +[#if BuildProperties?has_content] +[=BuildProperties] +[/#if] +[#list KubernetesProperties as prop] + <[=prop.key]>[=prop.value] +[/#list] + + + + + + + org.apache.camel + camel-bom + [=CamelVersion] + pom + import + + + + +[#if Repositories?has_content] + +[#list Repositories as repo] + + [=repo.id] + [=repo.url] +[#if repo.isSnapshot] + + false + + + true + +[/#if] + +[/#list] + + +[#list Repositories as repo] + + plugin-[=repo.id] + [=repo.url] +[#if repo.isSnapshot] + + false + + + true + +[/#if] + +[/#list] + +[/#if] + + + + + org.apache.camel + camel-main + +[#list Dependencies as dep] + + [=dep.groupId] + [=dep.artifactId] +[#if dep.version??] + [=dep.version] +[/#if] +[#if dep.isLib] + system + ${project.basedir}/lib/[=dep.artifactId]-[=dep.version].jar +[#elseif dep.scope??] + [=dep.scope] +[/#if] +[#if dep.isKameletsUtils] + + + org.apache.camel + * + + +[/#if] + +[/#list] + + + + org.fusesource.jansi + jansi + 2.4.2 + + + org.apache.logging.log4j + log4j-api + 2.24.3 + + + org.apache.logging.log4j + log4j-slf4j2-impl + 2.24.3 + + + org.apache.logging.log4j + log4j-core + 2.24.3 + + + + org.apache.camel + camel-test-junit6 + test + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.15.0 + + ${java.version} + ${java.version} + + + + + org.apache.camel + camel-maven-plugin + [=CamelVersion] + + [=MainClassname] + + + + + prepare-fatjar + + + + + + + org.apache.camel + camel-repackager-maven-plugin + [=CamelVersion] + + + repackage-executable + package + + repackage + + + [=MainClassname] + + + + +[#if hasJib] + + com.google.cloud.tools + jib-maven-plugin + [=JibMavenPluginVersion] + + + ${jib.from.image} +[#if hasJibFromAuth] + + ${jib.from.auth.username} + ${jib.from.auth.password} + +[/#if] + + + ${jib.to.image} +[#if hasJibToAuth] + + ${jib.to.auth.username} + ${jib.to.auth.password} + +[/#if] + + packaged + + + [=Port] + + + + +[/#if] +[#if hasJkube] + + org.eclipse.jkube + kubernetes-maven-plugin + [=JkubeMavenPluginVersion] + + + + ${jib.to.image} + + + + + + + + + ${label.runtime} + camel + + + + + + +[/#if] + + + + + + camel.debug + + + camel.debug + true + + + + + org.apache.camel + camel-debug + + + + + + diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/main-pom.tmpl b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/main-pom.tmpl deleted file mode 100644 index 9c01813bd7e97..0000000000000 --- a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/main-pom.tmpl +++ /dev/null @@ -1,137 +0,0 @@ - - - 4.0.0 - - {{ .GroupId }} - {{ .ArtifactId }} - {{ .Version }} - - - {{ .JavaVersion }} - {{ .ProjectBuildOutputTimestamp }} -{{ .BuildProperties }} -{{ .CamelKubernetesProperties }} - - - - - - - org.apache.camel - camel-bom - {{ .CamelVersion }} - pom - import - - - - -{{ .MavenRepositories }} - - - - - org.apache.camel - camel-main - -{{ .CamelDependencies }} - - - - org.fusesource.jansi - jansi - 2.4.2 - - - org.apache.logging.log4j - log4j-api - 2.24.3 - - - org.apache.logging.log4j - log4j-slf4j2-impl - 2.24.3 - - - org.apache.logging.log4j - log4j-core - 2.24.3 - - - - org.apache.camel - camel-test-junit6 - test - - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.15.0 - - ${java.version} - ${java.version} - - - - - org.apache.camel - camel-maven-plugin - {{ .CamelVersion }} - - {{ .MainClassname }} - - - - - prepare-fatjar - - - - - - - org.apache.camel - camel-repackager-maven-plugin - {{ .CamelVersion }} - - - repackage-executable - package - - repackage - - - {{ .MainClassname }} - - - - -{{ .CamelKubernetesPlugins }} - - - - - - camel.debug - - - camel.debug - true - - - - - org.apache.camel - camel-debug - - - - - - diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/main.ftl b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/main.ftl new file mode 100644 index 0000000000000..7ab822afda2ab --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/main.ftl @@ -0,0 +1,31 @@ +<#-- + + 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. + +--> +[#if PackageName??][=PackageName] + +[/#if] +import org.apache.camel.main.fatjar.Main; + +public class [=MainClassname] { + + public static void main(String[] args) throws Exception { + Main main = new Main([=MainClassname].class); + main.run(args); + } + +} diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/main.tmpl b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/main.tmpl deleted file mode 100644 index edb65a0f7f13b..0000000000000 --- a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/main.tmpl +++ /dev/null @@ -1,12 +0,0 @@ -{{ .PackageName }} - -import org.apache.camel.main.fatjar.Main; - -public class {{ .MainClassname }} { - - public static void main(String[] args) throws Exception { - Main main = new Main({{ .MainClassname }}.class); - main.run(args); - } - -} diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/quarkus-kubernetes-pom.tmpl b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/quarkus-kubernetes-pom.ftl similarity index 79% rename from dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/quarkus-kubernetes-pom.tmpl rename to dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/quarkus-kubernetes-pom.ftl index 94a1547d122c6..5e239d97a8098 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/quarkus-kubernetes-pom.tmpl +++ b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/quarkus-kubernetes-pom.ftl @@ -1,24 +1,44 @@ +<#-- + + 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. + +--> 4.0.0 - {{ .GroupId }} - {{ .ArtifactId }} - {{ .Version }} + [=GroupId] + [=ArtifactId] + [=Version] - {{ .ProjectBuildOutputTimestamp }} + [=ProjectBuildOutputTimestamp] 3.15.0 false - {{ .JavaVersion }} + [=JavaVersion] UTF-8 UTF-8 - {{ .QuarkusGroupId }} - {{ .QuarkusArtifactId }} - {{ .QuarkusVersion }} -{{ .BuildProperties }} + [=QuarkusGroupId] + [=QuarkusArtifactId] + [=QuarkusVersion] +[#if BuildProperties?has_content] +[=BuildProperties] +[/#if] true 3.5.5 @@ -42,14 +62,69 @@ -{{ .MavenRepositories }} +[#if Repositories?has_content] + +[#list Repositories as repo] + + [=repo.id] + [=repo.url] +[#if repo.isSnapshot] + + false + + + true + +[/#if] + +[/#list] + + +[#list Repositories as repo] + + plugin-[=repo.id] + [=repo.url] +[#if repo.isSnapshot] + + false + + + true + +[/#if] + +[/#list] + +[/#if] org.apache.camel.quarkus camel-quarkus-core -{{ .CamelDependencies }} +[#list Dependencies as dep] + + [=dep.groupId] + [=dep.artifactId] +[#if dep.version??] + [=dep.version] +[/#if] +[#if dep.isLib] + system + ${project.basedir}/lib/[=dep.artifactId]-[=dep.version].jar +[#elseif dep.scope??] + [=dep.scope] +[/#if] +[#if dep.isKameletsUtils] + + + org.apache.camel + * + + +[/#if] + +[/#list] io.quarkus diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/quarkus-pom.tmpl b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/quarkus-pom.ftl similarity index 70% rename from dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/quarkus-pom.tmpl rename to dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/quarkus-pom.ftl index bdd439a8c35fb..d7dd5637dedaa 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/quarkus-pom.tmpl +++ b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/quarkus-pom.ftl @@ -1,24 +1,44 @@ +<#-- + + 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. + +--> 4.0.0 - {{ .GroupId }} - {{ .ArtifactId }} - {{ .Version }} + [=GroupId] + [=ArtifactId] + [=Version] - {{ .ProjectBuildOutputTimestamp }} + [=ProjectBuildOutputTimestamp] 3.15.0 false - {{ .JavaVersion }} + [=JavaVersion] UTF-8 UTF-8 - {{ .QuarkusGroupId }} - {{ .QuarkusArtifactId }} - {{ .QuarkusVersion }} -{{ .BuildProperties }} - {{ .QuarkusPackageType }} + [=QuarkusGroupId] + [=QuarkusArtifactId] + [=QuarkusVersion] +[#if BuildProperties?has_content] +[=BuildProperties] +[/#if] + [=QuarkusPackageType] true 3.5.5 @@ -42,14 +62,69 @@ -{{ .MavenRepositories }} +[#if Repositories?has_content] + +[#list Repositories as repo] + + [=repo.id] + [=repo.url] +[#if repo.isSnapshot] + + false + + + true + +[/#if] + +[/#list] + + +[#list Repositories as repo] + + plugin-[=repo.id] + [=repo.url] +[#if repo.isSnapshot] + + false + + + true + +[/#if] + +[/#list] + +[/#if] org.apache.camel.quarkus camel-quarkus-core -{{ .CamelDependencies }} +[#list Dependencies as dep] + + [=dep.groupId] + [=dep.artifactId] +[#if dep.version??] + [=dep.version] +[/#if] +[#if dep.isLib] + system + ${project.basedir}/lib/[=dep.artifactId]-[=dep.version].jar +[#elseif dep.scope??] + [=dep.scope] +[/#if] +[#if dep.isKameletsUtils] + + + org.apache.camel + * + + +[/#if] + +[/#list] io.quarkus diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/readme.md.ftl b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/readme.md.ftl new file mode 100644 index 0000000000000..58ff6140e70db --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/readme.md.ftl @@ -0,0 +1,49 @@ +<#-- + + 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. + +--> +# How to build and run a Camel application + +This project was generated using [Camel Jbang](https://camel.apache.org/manual/camel-jbang.html). Please, refer to the online documentation for learning more about how to configure the export of your Camel application. + +This is a brief guide explaining how to build, "containerize" and run your Camel application. + +## Build the Maven project + +```bash +./mvnw clean package +``` + +The application could now immediately run: + +```bash +java -jar [=AppRuntimeJar] +``` + +## Create a Docker container + +You can create a container image directly from the `src/main/docker` resources. Here you have a precompiled base configuration which can be enhanced with any further required configuration. + +```bash +docker build -f src/main/docker/Dockerfile -t [=ArtifactId]:[=Version] . +``` + +Once the application is published, you can run it directly from the container: + +```bash +docker run -it [=ArtifactId]:[=Version] +``` diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/readme.md.tmpl b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/readme.md.tmpl deleted file mode 100644 index c0275db1511c5..0000000000000 --- a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/readme.md.tmpl +++ /dev/null @@ -1,31 +0,0 @@ -# How to build and run a Camel application - -This project was generated using [Camel Jbang](https://camel.apache.org/manual/camel-jbang.html). Please, refer to the online documentation for learning more about how to configure the export of your Camel application. - -This is a brief guide explaining how to build, "containerize" and run your Camel application. - -## Build the Maven project - -```bash -./mvnw clean package -``` - -The application could now immediately run: - -```bash -java -jar {{ .AppRuntimeJar }} -``` - -## Create a Docker container - -You can create a container image directly from the `src/main/docker` resources. Here you have a precompiled base configuration which can be enhanced with any further required configuration. - -```bash -docker build -f src/main/docker/Dockerfile -t {{ .ArtifactId }}:{{ .Version }} . -``` - -Once the application is published, you can run it directly from the container: - -```bash -docker run -it {{ .ArtifactId }}:{{ .Version }} -``` diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/readme.native.md.tmpl b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/readme.native.md.ftl similarity index 54% rename from dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/readme.native.md.tmpl rename to dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/readme.native.md.ftl index 509a6e9c3019d..08b0f1ef21bc1 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/readme.native.md.tmpl +++ b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/readme.native.md.ftl @@ -1,3 +1,21 @@ +<#-- + + 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. + +--> # How to build and run a Camel application This project was generated using [Camel Jbang](https://camel.apache.org/manual/camel-jbang.html). Please, refer to the online documentation for learning more about how to configure the export of your Camel application. @@ -13,7 +31,7 @@ This is a brief guide explaining how to build, "containerize" and run your Camel The application could now immediately run: ```bash -java -jar {{ .AppRuntimeJar }} +java -jar [=AppRuntimeJar] ``` ## Create a Docker container (JVM mode) @@ -21,13 +39,13 @@ java -jar {{ .AppRuntimeJar }} You can create a container image directly from the `src/main/docker` resources. Here you have a precompiled base configuration which can be enhanced with any further required configuration. ```bash -docker build -f src/main/docker/Dockerfile -t {{ .ArtifactId }}:{{ .Version }} . +docker build -f src/main/docker/Dockerfile -t [=ArtifactId]:[=Version] . ``` Once the application is published, you can run it directly from the container: ```bash -docker run -it {{ .ArtifactId }}:{{ .Version }} +docker run -it [=ArtifactId]:[=Version] ``` ## Build the Maven project (Native mode) @@ -39,7 +57,7 @@ docker run -it {{ .ArtifactId }}:{{ .Version }} Native compilation can last a few minutes to complete. Once done, the application could immediately run: ```bash -./{{ .ArtifactId }}-{{ .Version }}-runner +./[=ArtifactId]-[=Version]-runner ``` ## Create a Docker container (Native mode) @@ -47,11 +65,11 @@ Native compilation can last a few minutes to complete. Once done, the applicatio You can create a container image directly from the `src/main/docker` resources. Here you have a precompiled base configuration which can be enhanced with any further required configuration. ```bash -docker build -f src/main/docker/Dockerfile.native -t native-{{ .ArtifactId }}:{{ .Version }} . +docker build -f src/main/docker/Dockerfile.native -t native-[=ArtifactId]:[=Version] . ``` Once the application is published, you can run it directly from the container: ```bash -docker run -it native-{{ .ArtifactId }}:{{ .Version }} +docker run -it native-[=ArtifactId]:[=Version] ``` diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/rest-dsl.yaml.ftl b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/rest-dsl.yaml.ftl new file mode 100644 index 0000000000000..1f09c6b9abca6 --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/rest-dsl.yaml.ftl @@ -0,0 +1,23 @@ +<#-- + + 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. + +--> +- restConfiguration: + clientRequestValidation: true +- rest: + openApi: + specification: [=Spec] diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/rest-dsl.yaml.tmpl b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/rest-dsl.yaml.tmpl deleted file mode 100644 index 69f7526db7ed3..0000000000000 --- a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/rest-dsl.yaml.tmpl +++ /dev/null @@ -1,5 +0,0 @@ -- restConfiguration: - clientRequestValidation: true -- rest: - openApi: - specification: {{ .Spec }} \ No newline at end of file diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/run-custom-camel-version.tmpl b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/run-custom-camel-version.ftl similarity index 56% rename from dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/run-custom-camel-version.tmpl rename to dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/run-custom-camel-version.ftl index c73df9c1eb111..5d4cf45420ed2 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/run-custom-camel-version.tmpl +++ b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/run-custom-camel-version.ftl @@ -1,3 +1,21 @@ +<#-- + + 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. + +--> ///usr/bin/env jbang "$0" "$@" ; exit $? /* @@ -17,12 +35,12 @@ * limitations under the License. */ -//JAVA {{ .JavaVersion }}+ -{{ .MavenRepositories }} +//JAVA [=JavaVersion]+ +[=MavenRepositories] //REPOS central=https://repo1.maven.org/maven2,apache-snapshot=https://repository.apache.org/content/groups/snapshots/ -{{ .CamelDependencies }} -{{ .CamelJBangDependencies }} -{{ .CamelKameletsDependencies }} +[=CamelDependencies] +[=CamelJBangDependencies] +[=CamelKameletsDependencies] package main; diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/spring-boot-kubernetes-pom.tmpl b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/spring-boot-kubernetes-pom.ftl similarity index 75% rename from dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/spring-boot-kubernetes-pom.tmpl rename to dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/spring-boot-kubernetes-pom.ftl index cb7efcf4f1987..03b0975f706f6 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/spring-boot-kubernetes-pom.tmpl +++ b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/spring-boot-kubernetes-pom.ftl @@ -1,3 +1,21 @@ +<#-- + + 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. + +--> @@ -6,17 +24,19 @@ org.springframework.boot spring-boot-starter-parent - {{ .SpringBootVersion }} + [=SpringBootVersion] - {{ .GroupId }} - {{ .ArtifactId }} - {{ .Version }} + [=GroupId] + [=ArtifactId] + [=Version] - {{ .JavaVersion }} -{{ .BuildProperties }} + [=JavaVersion] +[#if BuildProperties?has_content] +[=BuildProperties] +[/#if] @@ -25,7 +45,7 @@ org.springframework.boot spring-boot-dependencies - {{ .SpringBootVersion }} + [=SpringBootVersion] pom import @@ -33,14 +53,47 @@ org.apache.camel.springboot camel-spring-boot-bom - {{ .CamelSpringBootVersion }} + [=CamelSpringBootVersion] pom import -{{ .MavenRepositories }} +[#if Repositories?has_content] + +[#list Repositories as repo] + + [=repo.id] + [=repo.url] +[#if repo.isSnapshot] + + false + + + true + +[/#if] + +[/#list] + + +[#list Repositories as repo] + + plugin-[=repo.id] + [=repo.url] +[#if repo.isSnapshot] + + false + + + true + +[/#if] + +[/#list] + +[/#if] @@ -55,7 +108,29 @@ org.apache.camel.springboot camel-spring-boot-starter -{{ .CamelDependencies }} +[#list Dependencies as dep] + + [=dep.groupId] + [=dep.artifactId] +[#if dep.version??] + [=dep.version] +[/#if] +[#if dep.isLib] + system + ${project.basedir}/lib/[=dep.artifactId]-[=dep.version].jar +[#elseif dep.scope??] + [=dep.scope] +[/#if] +[#if dep.isKameletsUtils] + + + org.apache.camel + * + + +[/#if] + +[/#list] org.springframework.boot spring-boot-starter-test diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/spring-boot-main.ftl b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/spring-boot-main.ftl new file mode 100644 index 0000000000000..ce37ebdfd52f6 --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/spring-boot-main.ftl @@ -0,0 +1,31 @@ +<#-- + + 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 [=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-main.tmpl b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/spring-boot-main.tmpl deleted file mode 100644 index a793b4296ca01..0000000000000 --- a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/spring-boot-main.tmpl +++ /dev/null @@ -1,13 +0,0 @@ -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.ftl similarity index 61% rename from dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/spring-boot-pom.tmpl rename to dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/spring-boot-pom.ftl index 8815f37d128c6..5cdda39a50605 100644 --- 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.ftl @@ -1,3 +1,21 @@ +<#-- + + 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. + +--> @@ -6,18 +24,20 @@ org.springframework.boot spring-boot-starter-parent - {{ .SpringBootVersion }} + [=SpringBootVersion] - {{ .GroupId }} - {{ .ArtifactId }} - {{ .Version }} + [=GroupId] + [=ArtifactId] + [=Version] - {{ .JavaVersion }} - {{ .ProjectBuildOutputTimestamp }} -{{ .BuildProperties }} + [=JavaVersion] + [=ProjectBuildOutputTimestamp] +[#if BuildProperties?has_content] +[=BuildProperties] +[/#if] @@ -26,7 +46,7 @@ org.springframework.boot spring-boot-dependencies - {{ .SpringBootVersion }} + [=SpringBootVersion] pom import @@ -34,14 +54,47 @@ org.apache.camel.springboot camel-spring-boot-bom - {{ .CamelSpringBootVersion }} + [=CamelSpringBootVersion] pom import -{{ .MavenRepositories }} +[#if Repositories?has_content] + +[#list Repositories as repo] + + [=repo.id] + [=repo.url] +[#if repo.isSnapshot] + + false + + + true + +[/#if] + +[/#list] + + +[#list Repositories as repo] + + plugin-[=repo.id] + [=repo.url] +[#if repo.isSnapshot] + + false + + + true + +[/#if] + +[/#list] + +[/#if] @@ -52,7 +105,29 @@ org.apache.camel.springboot camel-spring-boot-starter -{{ .CamelDependencies }} +[#list Dependencies as dep] + + [=dep.groupId] + [=dep.artifactId] +[#if dep.version??] + [=dep.version] +[/#if] +[#if dep.isLib] + system + ${project.basedir}/lib/[=dep.artifactId]-[=dep.version].jar +[#elseif dep.scope??] + [=dep.scope] +[/#if] +[#if dep.isKameletsUtils] + + + org.apache.camel + * + + +[/#if] + +[/#list] org.springframework.boot spring-boot-starter-test diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/xml.ftl b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/xml.ftl new file mode 100644 index 0000000000000..66081f2ff61bf --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/xml.ftl @@ -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. + +--> + + + + + + + Hello Camel from ${routeId} + + + + + diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/xml.tmpl b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/xml.tmpl deleted file mode 100644 index 1893bed176edf..0000000000000 --- a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/xml.tmpl +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - Hello Camel from ${routeId} - - - - - diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/yaml.ftl b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/yaml.ftl new file mode 100644 index 0000000000000..48d5a88d02bf7 --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/yaml.ftl @@ -0,0 +1,27 @@ +<#-- + + 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. + +--> +- route: + from: + uri: timer:yaml + parameters: + period: "1000" + steps: + - setBody: + simple: Hello Camel from ${routeId} + - log: ${body} diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/yaml.tmpl b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/yaml.tmpl deleted file mode 100644 index e1cdcb3b6cbf8..0000000000000 --- a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/yaml.tmpl +++ /dev/null @@ -1,9 +0,0 @@ -- route: - from: - uri: timer:yaml - parameters: - period: "1000" - steps: - - setBody: - simple: Hello Camel from ${routeId} - - log: ${body} \ No newline at end of file diff --git a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesExport.java b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesExport.java index 3782d71914126..f1fdf43123c23 100644 --- a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesExport.java +++ b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesExport.java @@ -433,13 +433,13 @@ public Integer export() throws Exception { protected Integer export(Path exportBaseDir, ExportBaseCommand cmd) throws Exception { if (runtime == RuntimeType.quarkus) { - cmd.pomTemplateName = "quarkus-kubernetes-pom.tmpl"; + cmd.pomTemplateName = "quarkus-kubernetes-pom.ftl"; } if (runtime == RuntimeType.springBoot) { - cmd.pomTemplateName = "spring-boot-kubernetes-pom.tmpl"; + cmd.pomTemplateName = "spring-boot-kubernetes-pom.ftl"; } if (runtime == RuntimeType.main) { - cmd.pomTemplateName = "main-kubernetes-pom.tmpl"; + cmd.pomTemplateName = "main-kubernetes-pom.ftl"; } return super.export(exportBaseDir, cmd); } From c52a7ca303976bee303731424b8bb9657dcc8711 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Mon, 23 Mar 2026 16:17:33 +0100 Subject: [PATCH 2/4] CAMEL-21208: Fix review findings - Add backward compat check for old .tmpl catalog template name in ExportSpringBoot - Remove dead model variables (CamelVersion, QuarkusManagementPort) Co-Authored-By: Claude Opus 4.6 --- .../camel/dsl/jbang/core/commands/ExportQuarkus.java | 7 ------- .../camel/dsl/jbang/core/commands/ExportSpringBoot.java | 5 ++++- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportQuarkus.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportQuarkus.java index bf476d6e72bc8..81c39c3d779ce 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportQuarkus.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportQuarkus.java @@ -335,11 +335,6 @@ private void createMavenPom(Path settings, Path pom, Set deps) throws Ex camelVersion = catalog.getCatalogVersion(); } - String mp = prop.getProperty("quarkus.management.port"); - if (mp == null) { - mp = "9876"; - } - // Build template data model List> depList = buildQuarkusDependencyList(deps, catalog); @@ -351,9 +346,7 @@ private void createMavenPom(Path settings, Path pom, Set deps) throws Ex model.put("QuarkusArtifactId", quarkusArtifactId); model.put("QuarkusVersion", quarkusVersion); model.put("QuarkusPackageType", quarkusPackageType); - model.put("QuarkusManagementPort", mp); model.put("JavaVersion", javaVersion); - model.put("CamelVersion", camelVersion); model.put("ProjectBuildOutputTimestamp", this.getBuildMavenProjectDate()); model.put("BuildProperties", formatBuildProperties()); model.put("Repositories", buildRepositoryList(repos)); 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 index 7312187937590..4c76c2dc68fd9 100644 --- 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 @@ -193,7 +193,11 @@ private void createMavenPom(Path settings, Path profile, Path pom, Set d } // Check if catalog provides a custom template (backward compatibility) + // Also check old .tmpl name for catalogs that haven't been updated InputStream catalogTemplate = catalog.loadResource("camel-jbang", pomTemplateName); + if (catalogTemplate == null) { + catalogTemplate = catalog.loadResource("camel-jbang", pomTemplateName.replace(".ftl", ".tmpl")); + } if (catalogTemplate != null) { // Catalog provides a custom template - use legacy regex-based processing String context = IOHelper.loadText(catalogTemplate); @@ -212,7 +216,6 @@ private void createMavenPom(Path settings, Path profile, Path pom, Set d model.put("Version", ids[2]); model.put("SpringBootVersion", springBootVersion); model.put("JavaVersion", javaVersion); - model.put("CamelVersion", camelVersion); model.put("CamelSpringBootVersion", Objects.requireNonNullElseGet(camelSpringBootVersion, () -> camelVersion)); model.put("ProjectBuildOutputTimestamp", this.getBuildMavenProjectDate()); From 2870d106b29d2813f68576bdf1a3ed02e2081d19 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Fri, 27 Mar 2026 09:04:05 +0100 Subject: [PATCH 3/4] CAMEL-21208: Minor cleanup from review - Remove unnecessary bare block in Run.generateOpenApi (leftover from try-with-resources) - Deduplicate model building in Export.copyDockerFiles Co-Authored-By: Claude Opus 4.6 --- .../camel/dsl/jbang/core/commands/Export.java | 13 +++++-------- .../apache/camel/dsl/jbang/core/commands/Run.java | 14 ++++++-------- 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Export.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Export.java index 941a0a9bf3a93..96912391c2660 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Export.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Export.java @@ -313,21 +313,18 @@ protected void copyDockerFiles(String buildDir) throws Exception { Files.createDirectories(docker); String[] ids = gav.split(":"); + Map model = new HashMap<>(); + model.put("ArtifactId", ids[1]); + model.put("Version", ids[2]); + model.put("AppJar", ids[1] + "-" + ids[2] + ".jar"); + String ftlName = "Dockerfile" + javaVersion + ".ftl"; String context; try { - Map model = new HashMap<>(); - model.put("ArtifactId", ids[1]); - model.put("Version", ids[2]); - model.put("AppJar", ids[1] + "-" + ids[2] + ".jar"); context = TemplateHelper.processTemplate(ftlName, model); } catch (IOException e) { // fallback to JDK 21 template printer().printf("No Dockerfile template for Java %s, falling back to Java 21 template%n", javaVersion); - Map model = new HashMap<>(); - model.put("ArtifactId", ids[1]); - model.put("Version", ids[2]); - model.put("AppJar", ids[1] + "-" + ids[2] + ".jar"); context = TemplateHelper.processTemplate("Dockerfile21.ftl", model); } Files.writeString(docker.resolve("Dockerfile"), context); 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 2b7fb76be4532..0a6c79307ff94 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 @@ -1913,15 +1913,13 @@ private void generateOpenApi() throws Exception { throw new FileNotFoundException("Cannot find file: " + filePath); } - { - Map model = new HashMap<>(); - model.put("Spec", filePath.toString()); - String content = TemplateHelper.processTemplate("rest-dsl.yaml.ftl", model); - Files.writeString(Paths.get(OPENAPI_GENERATED_FILE), content); + Map model = new HashMap<>(); + model.put("Spec", filePath.toString()); + String content = TemplateHelper.processTemplate("rest-dsl.yaml.ftl", model); + Files.writeString(Paths.get(OPENAPI_GENERATED_FILE), content); - // we need to include the spec on the classpath - files.add(openapi); - } + // we need to include the spec on the classpath + files.add(openapi); } private boolean knownFile(String file) throws Exception { From 7cddc10ae0c843eeb740b30afec7d21b64b8fd7c Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Fri, 27 Mar 2026 13:52:26 +0100 Subject: [PATCH 4/4] CAMEL-21208: Add unit test for TemplateHelper Co-Authored-By: Claude Opus 4.6 --- .../jbang/core/common/TemplateHelperTest.java | 122 ++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/common/TemplateHelperTest.java diff --git a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/common/TemplateHelperTest.java b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/common/TemplateHelperTest.java new file mode 100644 index 0000000000000..5485f94d6f962 --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/common/TemplateHelperTest.java @@ -0,0 +1,122 @@ +/* + * 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.common; + +import java.io.IOException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class TemplateHelperTest { + + @Test + void testSimpleInterpolation() throws IOException { + Map model = new HashMap<>(); + model.put("Name", "MyRoute"); + model.put("Code", "from(\"timer:tick\").log(\"Hello\");"); + + String result = TemplateHelper.processTemplate("code-java.ftl", model); + + assertTrue(result.contains("class MyRoute"), "Should contain class name"); + assertTrue(result.contains("from(\"timer:tick\").log(\"Hello\");"), "Should contain code"); + assertFalse(result.contains("[="), "Should not contain unresolved interpolations"); + } + + @Test + void testLicenseHeaderStripped() throws IOException { + Map model = new HashMap<>(); + model.put("Name", "Test"); + model.put("Code", "// test"); + + String result = TemplateHelper.processTemplate("code-java.ftl", model); + + assertFalse(result.contains("<#--"), "License header should be stripped"); + assertFalse(result.contains("Licensed to the Apache"), "License text should be stripped"); + } + + @Test + void testConditionalRendering() throws IOException { + // main.ftl has [#if PackageName??] conditional + Map withPackage = new HashMap<>(); + withPackage.put("PackageName", "package com.example;"); + withPackage.put("MainClassname", "MyApp"); + + String result = TemplateHelper.processTemplate("main.ftl", withPackage); + assertTrue(result.contains("package com.example;"), "Should contain package declaration"); + assertTrue(result.contains("class MyApp"), "Should contain class name"); + + // Without package + Map withoutPackage = new HashMap<>(); + withoutPackage.put("MainClassname", "MyApp"); + + result = TemplateHelper.processTemplate("main.ftl", withoutPackage); + assertFalse(result.contains("package "), "Should not contain package declaration"); + assertTrue(result.contains("class MyApp"), "Should contain class name"); + } + + @Test + void testListRendering() throws IOException { + Map model = new HashMap<>(); + model.put("GroupId", "com.example"); + model.put("ArtifactId", "my-app"); + model.put("Version", "1.0.0"); + model.put("SpringBootVersion", "3.4.0"); + model.put("JavaVersion", "21"); + model.put("CamelSpringBootVersion", "4.10.0"); + model.put("ProjectBuildOutputTimestamp", "2024-01-01T00:00:00Z"); + model.put("BuildProperties", ""); + model.put("Repositories", List.of()); + + List> deps = List.of( + Map.of("groupId", "org.apache.camel.springboot", "artifactId", "camel-timer-starter", + "isLib", false, "isKameletsUtils", false)); + + model.put("Dependencies", deps); + + String result = TemplateHelper.processTemplate("spring-boot-pom.ftl", model); + assertTrue(result.contains("com.example"), "Should contain groupId"); + assertTrue(result.contains("camel-timer-starter"), + "Should contain dependency artifactId"); + // Maven ${...} expressions should pass through unmodified + assertTrue(result.contains("${project.basedir}") || !result.contains("isLib"), + "Maven expressions should not be interpreted by FreeMarker"); + } + + @Test + void testMavenExpressionsPreserved() throws IOException { + Map model = new HashMap<>(); + model.put("ArtifactId", "my-app"); + model.put("Version", "1.0.0"); + model.put("AppJar", "my-app-1.0.0.jar"); + + String result = TemplateHelper.processTemplate("Dockerfile21.ftl", model); + assertTrue(result.contains("my-app"), "Should contain artifact id"); + assertFalse(result.contains("[="), "Should not contain unresolved interpolations"); + } + + @Test + void testMissingTemplateThrowsIOException() { + Map model = new HashMap<>(); + assertThrows(IOException.class, () -> TemplateHelper.processTemplate("nonexistent.ftl", model)); + } +}