in dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java [448:971]
private int run() throws Exception {
if (!empty && !files.isEmpty() && sourceDir != null) {
// cannot have both files and source dir at the same time
printer().printErr("Cannot specify both file(s) and source-dir at the same time.");
return 1;
}
// special if user type: camel run .
if (sourceDir == null && (files != null && files.size() == 1 && ".".equals(files.get(0)))) {
files.clear();
File[] fs = new File(".").listFiles();
if (fs != null) {
for (File f : fs) {
// skip hidden files
if (f.isFile() && !f.isHidden()) {
files.add(f.getName());
}
}
}
}
if (!exportRun) {
if (RuntimeType.quarkus == runtime) {
return runQuarkus();
} else if (RuntimeType.springBoot == runtime) {
return runSpringBoot();
}
}
File work = CommandLineHelper.getWorkDir();
removeDir(work);
if (!work.exists() && !work.mkdirs()) {
printer().println("WARN: Failed to create working directory: " + work.getAbsolutePath());
}
Properties profileProperties = !empty ? loadProfileProperties() : null;
configureLogging();
if (openapi != null) {
generateOpenApi();
}
// route code as option
if (!empty && code != null) {
// code may refer to an existing file
String name = "CodeRoute";
boolean file = false;
File f = new File(code);
if (f.isFile() && f.exists()) {
// must be a java file
boolean java = f.getName().endsWith(".java");
if (!java) {
printer().printErr("Only java source files is accepted when using --code parameter");
return 1;
}
code = Files.readString(f.toPath());
name = FileUtil.onlyName(f.getName());
file = true;
}
// store code in temporary file
String codeFile = loadFromCode(code, name, file);
// use code as first file
files.add(0, codeFile);
}
boolean autoDetectFiles = files.isEmpty() || RUN_JAVA_SH.equals(files.get(0));
// if no specific file to run then try to auto-detect
if (!empty && autoDetectFiles) {
if (sourceDir != null) {
// silent-run then auto-detect all initial files for source-dir
String[] allFiles = new File(sourceDir).list();
if (allFiles != null) {
for (String f : allFiles) {
files.add(sourceDir + File.separator + f);
}
}
} else {
String routes
= profileProperties != null ? profileProperties.getProperty("camel.main.routesIncludePattern") : null;
if (routes == null) {
if (!exportRun) {
String run = "run";
if (transformRun) {
run = "transform";
} else if (debugRun) {
run = "debug";
}
System.err
.println("Cannot " + run
+ " because application.properties file does not exist or camel.main.routesIncludePattern is not configured");
return 1;
} else {
// silent-run then auto-detect all files
String[] allFiles = new File(".").list();
if (allFiles != null) {
files.addAll(Arrays.asList(allFiles));
}
}
}
}
}
// filter out duplicate files
if (!files.isEmpty()) {
files = files.stream().distinct().collect(Collectors.toList());
}
final KameletMain main = createMainInstance();
main.setProfile(profile);
if (repositories != null && !repositories.isBlank()) {
main.setRepositories(String.join(",", repositories));
}
main.setDownload(download);
main.setPackageScanJars(packageScanJars);
main.setFresh(fresh);
main.setMavenSettings(mavenSettings);
main.setMavenSettingsSecurity(mavenSettingsSecurity);
main.setMavenCentralEnabled(mavenCentralEnabled);
main.setMavenApacheSnapshotEnabled(mavenApacheSnapshotEnabled);
main.setDownloadListener(new RunDownloadListener());
main.setAppName("Apache Camel (JBang)");
if (stub != null) {
if ("all".equals(stub)) {
stub = "*";
}
// we need to match by wildcard, to make it easier
StringJoiner sj = new StringJoiner(",");
for (String n : stub.split(",")) {
// you can either refer to a name or a specific endpoint
// if there is a colon then we assume its a specific endpoint then we should not add wildcard
boolean colon = n.contains(":");
if (!colon && !n.endsWith("*")) {
n = n + "*";
}
sj.add(n);
}
stub = sj.toString();
writeSetting(main, profileProperties, "camel.jbang.stub", stub);
main.setStubPattern(stub);
}
if (dev) {
writeSetting(main, profileProperties, "camel.main.routesReloadEnabled", "true");
// allow quick shutdown during development
writeSetting(main, profileProperties, "camel.main.shutdownTimeout", "5");
}
if (sourceDir != null) {
writeSetting(main, profileProperties, "camel.jbang.sourceDir", sourceDir);
}
if (trace) {
writeSetting(main, profileProperties, "camel.main.tracing", "true");
}
if (modeline) {
writeSetting(main, profileProperties, "camel.main.modeline", "true");
}
if (ignoreLoadingError) {
writeSetting(main, profileProperties, "camel.jbang.ignoreLoadingError", "true");
}
if (lazyBean) {
writeSetting(main, profileProperties, "camel.jbang.lazyBean", "true");
}
if (prompt) {
writeSetting(main, profileProperties, "camel.jbang.prompt", "true");
}
writeSetting(main, profileProperties, "camel.jbang.compileWorkDir",
CommandLineHelper.CAMEL_JBANG_WORK_DIR + File.separator + "compile");
if (gav != null) {
writeSetting(main, profileProperties, "camel.jbang.gav", gav);
}
writeSetting(main, profileProperties, "camel.jbang.open-api", openapi);
if (repositories != null) {
writeSetting(main, profileProperties, "camel.jbang.repos", String.join(",", repositories));
}
writeSetting(main, profileProperties, "camel.jbang.health", health ? "true" : "false");
writeSetting(main, profileProperties, "camel.jbang.metrics", metrics ? "true" : "false");
writeSetting(main, profileProperties, "camel.jbang.console", console ? "true" : "false");
writeSetting(main, profileProperties, "camel.jbang.verbose", verbose ? "true" : "false");
// the runtime version of Camel is what is loaded via the catalog
writeSetting(main, profileProperties, "camel.jbang.camel-version", new DefaultCamelCatalog().getCatalogVersion());
writeSetting(main, profileProperties, "camel.jbang.springBootVersion", springBootVersion);
writeSetting(main, profileProperties, "camel.jbang.quarkusVersion", quarkusVersion);
writeSetting(main, profileProperties, "camel.jbang.quarkusGroupId", quarkusGroupId);
writeSetting(main, profileProperties, "camel.jbang.quarkusArtifactId", quarkusArtifactId);
if (observe) {
main.addInitialProperty("camel.jbang.dependencies", "camel:observability-services");
}
// command line arguments
if (property != null) {
for (String p : property) {
String k = StringHelper.before(p, "=");
String v = StringHelper.after(p, "=");
if (k != null && v != null) {
main.addArgumentProperty(k, v);
writeSettings(k, v);
}
}
}
if (exportRun) {
if (!verbose) {
main.setSilent(true);
}
main.addInitialProperty("camel.jbang.export", "true");
// enable stub in silent mode so we do not use real components
main.setStubPattern("*");
// do not run for very long in silent run
main.addInitialProperty("camel.main.autoStartup", "false");
main.addInitialProperty("camel.main.durationMaxSeconds", "1");
} else if (debugRun) {
main.addInitialProperty("camel.jbang.debug", "true");
} else if (transformRun) {
main.setSilent(true);
// enable stub in silent mode so we do not use real components
main.setStubPattern("*");
// do not run for very long in silent run
main.addInitialProperty("camel.main.autoStartup", "false");
main.addInitialProperty("camel.main.durationMaxSeconds", "1");
} else if (transformMessageRun) {
// do not start any routes
main.addInitialProperty("camel.main.autoStartup", "false");
} else if (scriptRun) {
// auto terminate if being idle
main.addInitialProperty("camel.main.durationMaxIdleSeconds", "1");
}
// any custom initial property
doAddInitialProperty(main);
writeSetting(main, profileProperties, "camel.main.durationMaxMessages",
() -> maxMessages > 0 ? String.valueOf(maxMessages) : null);
writeSetting(main, profileProperties, "camel.main.durationMaxSeconds",
() -> maxSeconds > 0 ? String.valueOf(maxSeconds) : null);
writeSetting(main, profileProperties, "camel.main.durationMaxIdleSeconds",
() -> maxIdleSeconds > 0 ? String.valueOf(maxIdleSeconds) : null);
writeSetting(main, profileProperties, "camel.jbang.platform-http.port",
() -> port > 0 && port != 8080 ? String.valueOf(port) : null);
writeSetting(main, profileProperties, "camel.jbang.jfr", jfr || jfrProfile != null ? "jfr" : null); // TODO: "true" instead of "jfr" ?
writeSetting(main, profileProperties, "camel.jbang.jfr-profile", jfrProfile != null ? jfrProfile : null);
writeSetting(main, profileProperties, "camel.jbang.kameletsVersion", kameletsVersion);
StringJoiner js = new StringJoiner(",");
StringJoiner sjReload = new StringJoiner(",");
StringJoiner sjClasspathFiles = new StringJoiner(",");
StringJoiner sjScriptFiles = new StringJoiner(",");
StringJoiner sjTlsFiles = new StringJoiner(",");
StringJoiner sjKamelets = new StringJoiner(",");
StringJoiner sjJKubeFiles = new StringJoiner(",");
// include generated openapi to files to run
if (openapi != null) {
files.add(OPENAPI_GENERATED_FILE);
}
// if we only run pom.xml/build.gradle then auto discover from the Maven/Gradle based project
if (files.size() == 1 && ("pom.xml".equals(files.get(0)) || "build.gradle".equals(files.get(0)))) {
// use a better name when running
if (name == null || "CamelJBang".equals(name)) {
name = RunHelper.mavenArtifactId();
}
// find source files
files = RunHelper.scanMavenOrGradleProject();
// include extra dependencies from pom.xml
var pomDependencies = RunHelper.scanMavenDependenciesFromPom();
addDependencies(pomDependencies.toArray(new String[0]));
}
if (profile != null) {
// need to include profile application properties if exists
String name = "application-" + profile + ".properties";
if (new File(name).exists() && !files.contains(name)) {
files.add(name);
}
}
for (String file : files) {
if (file.startsWith("clipboard") && !(new File(file).exists())) {
file = loadFromClipboard(file);
} else if (skipFile(file)) {
continue;
} else if (isScriptFile(file)) {
// script files
sjScriptFiles.add(file);
continue;
} else if (isTlsFile(file)) {
// tls files
sjTlsFiles.add(file);
continue;
} else if (jkubeFile(file)) {
// jkube
sjJKubeFiles.add(file);
continue;
} else if (!knownFile(file) && !file.endsWith(".properties")) {
// unknown files to be added on classpath
sjClasspathFiles.add(file);
continue;
}
// process known files as its likely DSLs or configuration files
// check for properties files
if (file.endsWith(".properties")) {
if (acceptPropertiesFile(file)) {
if (!ResourceHelper.hasScheme(file) && !file.startsWith("github:")) {
file = "file:" + file;
}
if (ObjectHelper.isEmpty(propertiesFiles)) {
propertiesFiles = file;
} else {
propertiesFiles = propertiesFiles + "," + file;
}
if (dev && file.startsWith("file:")) {
// we can only reload if file based
sjReload.add(file.substring(5));
}
}
continue;
}
// Camel DSL files
if (!ResourceHelper.hasScheme(file) && !file.startsWith("github:")) {
file = "file:" + file;
}
if (file.startsWith("file:")) {
// check if file exist
File inputFile = new File(file.substring(5));
if (!inputFile.exists() && !inputFile.isFile()) {
printer().printErr("File does not exist: " + file);
return 1;
}
}
if (file.startsWith("file:") && file.endsWith(".kamelet.yaml")) {
sjKamelets.add(file);
}
// automatic map github https urls to github resolver
if (file.startsWith("https://github.com/")) {
file = evalGithubSource(main, file);
if (file == null) {
continue; // all mapped continue to next
}
} else if (file.startsWith("https://gist.github.com/")) {
file = evalGistSource(main, file);
if (file == null) {
continue; // all mapped continue to next
}
}
if ("CamelJBang".equals(name)) {
// no specific name was given so lets use the name from the first integration file
// remove scheme and keep only the name (no path or ext)
String s = StringHelper.after(file, ":");
if (s.contains(":")) {
// its maybe a gist/github url so we need only the last part which has the name
s = StringHelper.afterLast(s, ":");
}
name = FileUtil.onlyName(s);
}
js.add(file);
if (dev && file.startsWith("file:")) {
// we can only reload if file based
sjReload.add(file.substring(5));
}
}
writeSetting(main, profileProperties, "camel.main.name", name);
if (sourceDir != null) {
// must be an existing directory
File dir = new File(sourceDir);
if (!dir.exists() && !dir.isDirectory()) {
printer().printErr("Directory does not exist: " + sourceDir);
return 1;
}
// make it a pattern as we load all files from this directory
// (optional=true as there may be non Camel routes files as well)
String sdir = "file:" + sourceDir + "/**?optional=true";
main.addInitialProperty("camel.main.routesIncludePattern", sdir);
writeSettings("camel.main.routesIncludePattern", sdir);
} else if (js.length() > 0) {
main.addInitialProperty("camel.main.routesIncludePattern", js.toString());
writeSettings("camel.main.routesIncludePattern", js.toString());
} else {
writeSetting(main, profileProperties, "camel.main.routesIncludePattern", () -> null);
}
if (sjClasspathFiles.length() > 0) {
main.addInitialProperty("camel.jbang.classpathFiles", sjClasspathFiles.toString());
writeSettings("camel.jbang.classpathFiles", sjClasspathFiles.toString());
} else {
writeSetting(main, profileProperties, "camel.jbang.classpathFiles", () -> null);
}
if (sjScriptFiles.length() > 0) {
main.addInitialProperty("camel.jbang.scriptFiles", sjScriptFiles.toString());
writeSettings("camel.jbang.scriptFiles", sjScriptFiles.toString());
} else {
writeSetting(main, profileProperties, "camel.jbang.scriptFiles", () -> null);
}
if (sjTlsFiles.length() > 0) {
main.addInitialProperty("camel.jbang.tlsFiles", sjTlsFiles.toString());
writeSettings("camel.jbang.tlsFiles", sjTlsFiles.toString());
} else {
writeSetting(main, profileProperties, "camel.jbang.tlsFiles", () -> null);
}
if (sjJKubeFiles.length() > 0) {
main.addInitialProperty("camel.jbang.jkubeFiles", sjJKubeFiles.toString());
writeSettings("camel.jbang.jkubeFiles", sjJKubeFiles.toString());
} else {
writeSetting(main, profileProperties, "camel.jbang.jkubeFiles", () -> null);
}
if (sjKamelets.length() > 0) {
String loc = main.getInitialProperties().getProperty("camel.component.kamelet.location");
if (loc != null) {
loc = loc + "," + sjKamelets;
} else {
loc = sjKamelets.toString();
}
main.addInitialProperty("camel.component.kamelet.location", loc);
writeSettings("camel.component.kamelet.location", loc);
} else {
writeSetting(main, profileProperties, "camel.component.kamelet.location", () -> null);
}
// we can only reload if file based
setupReload(main, sjReload);
if (propertiesFiles != null) {
String[] filesLocation = propertiesFiles.split(",");
// sort so general application.properties comes first (we should load profile first)
List<String> names = new ArrayList<>(List.of(filesLocation));
names.sort((o1, o2) -> {
// make sure application.properties is last
if (o1.endsWith("application.properties")) {
return 1;
} else if (o2.endsWith("application.properties")) {
return -1;
}
return 0;
});
StringBuilder locations = new StringBuilder();
for (String file : names) {
if (!file.startsWith("file:")) {
if (!file.startsWith("/")) {
file = FileSystems.getDefault().getPath("").toAbsolutePath() + File.separator + file;
}
file = "file://" + file;
}
if (!locations.isEmpty()) {
locations.append(",");
}
locations.append(file);
}
// there may be existing properties
String loc = main.getInitialProperties().getProperty("camel.component.properties.location");
if (loc != null) {
loc = loc + "," + locations;
} else {
loc = locations.toString();
}
main.addInitialProperty("camel.component.properties.location", loc);
writeSettings("camel.component.properties.location", loc);
main.setPropertyPlaceholderLocations(loc);
}
// merge existing dependencies with --deps
addDependencies(RuntimeUtil.getDependenciesAsArray(profileProperties));
if (!dependencies.isEmpty()) {
var joined = String.join(",", dependencies);
main.addInitialProperty("camel.jbang.dependencies", joined);
writeSettings("camel.jbang.dependencies", joined);
}
// if we have a specific camel version then make sure we really need to switch
if (camelVersion != null) {
CamelCatalog catalog = new DefaultCamelCatalog();
String v = catalog.getCatalogVersion();
if (camelVersion.equals(v)) {
// same version, so we use current
camelVersion = null;
}
}
// okay we have validated all input and are ready to run
// (if exporting then we cannot run a different version)
if (!exportRun && camelVersion != null || isDebugMode()) {
// TODO: debug camel specific version
boolean custom = false;
if (camelVersion != null) {
// run in another JVM with different camel version (foreground or background)
custom = camelVersion.contains("-") && !camelVersion.endsWith("-SNAPSHOT");
if (custom) {
// regular camel versions can also be a milestone or release candidate
custom = !camelVersion.matches(".*-(RC|M)\\d$");
}
}
if (custom) {
// custom camel distribution
return runCustomCamelVersion(main);
} else {
// apache camel distribution or remote debug enabled
return runCamelVersion(main);
}
} else if (debugRun) {
// spawn new JVM to debug in background
return runDebug(main);
} else if (background) {
// spawn new JVM to run in background
return runBackground(main);
} else {
// run default in current JVM with same camel version
try {
return runKameletMain(main);
} catch (FailedToCreateRouteException ex) {
if (ignoreLoadingError) {
printer().printErr(ex);
return 0;
}
throw ex;
}
}
}