Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions dsl/camel-jbang/camel-jbang-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,13 @@
<artifactId>plexus-xml</artifactId>
</dependency>

<!-- template engine for code generation -->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>${freemarker-version}</version>
</dependency>

<!-- test dependencies -->
<dependency>
<groupId>org.apache.camel</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,24 @@
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;
import org.apache.camel.dsl.jbang.core.common.PropertyResolver;
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;
Expand Down Expand Up @@ -300,72 +300,6 @@ protected String getVersion() {
return "1.0-SNAPSHOT";
}

public Comparator<MavenGav> mavenGavComparator() {
return new Comparator<MavenGav>() {
@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
Expand All @@ -378,33 +312,33 @@ 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) {

Map<String, Object> 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 {
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");
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<String, Object> 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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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(" <repositories>\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<Map<String, Object>> buildRepositoryList(String repos) {
List<Map<String, Object>> result = new ArrayList<>();
if (repos != null && !repos.isEmpty()) {
int i = 1;
for (String repo : repos.split(",")) {
sb.append(" <repository>\n");
sb.append(" <id>custom").append(i++).append("</id>\n");
sb.append(" <url>").append(repo).append("</url>\n");
if (repo.contains("snapshots")) {
sb.append(" <releases>\n");
sb.append(" <enabled>false</enabled>\n");
sb.append(" </releases>\n");
sb.append(" <snapshots>\n");
sb.append(" <enabled>true</enabled>\n");
sb.append(" </snapshots>\n");
}
sb.append(" </repository>\n");
Map<String, Object> r = new HashMap<>();
r.put("id", "custom" + i++);
r.put("url", repo);
r.put("isSnapshot", repo.contains("snapshots"));
result.add(r);
}
}
sb.append(" </repositories>\n");
sb.append(" <pluginRepositories>\n");
if (!repos.isEmpty()) {
for (String repo : repos.split(",")) {
sb.append(" <pluginRepository>\n");
sb.append(" <id>custom").append(i++).append("</id>\n");
sb.append(" <url>").append(repo).append("</url>\n");
if (repo.contains("snapshots")) {
sb.append(" <releases>\n");
sb.append(" <enabled>false</enabled>\n");
sb.append(" </releases>\n");
sb.append(" <snapshots>\n");
sb.append(" <enabled>true</enabled>\n");
sb.append(" </snapshots>\n");
return result;
}

/**
* Builds a list of dependency data maps from the deps set, for use with FreeMarker templates.
*/
protected List<Map<String, Object>> buildDependencyList(Set<String> deps) {
List<MavenGav> 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<Map<String, Object>> result = new ArrayList<>();
for (MavenGav gav : gavs) {
Map<String, Object> 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<MavenGav> mavenGavComparator() {
return new Comparator<MavenGav>() {
@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(" </pluginRepository>\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<PluginExporter> 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(" </pluginRepositories>\n");
return sb.toString();

return properties.entrySet().stream()
.map(item -> String.format(" <%s>%s</%s>", item.getKey(), item.getValue(), item.getKey()))
.collect(Collectors.joining(System.lineSeparator()));
}

protected abstract Integer export() throws Exception;
Expand Down Expand Up @@ -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<PluginExporter> 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</%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 }}"), "");
}
Expand Down
Loading
Loading