in src/main/java/org/apache/sling/maven/feature/launcher/StartMojo.java [138:319]
public void execute() throws MojoExecutionException, MojoFailureException {
try {
// the feature launcher before version 1.1.28 used a single jar, while versions
// after that provide an assembly per SLING-10956
VersionRange beforeAssemblyRange = VersionRange.createFromVersionSpec("(,1.1.26]");
boolean useAssembly = !beforeAssemblyRange.containsVersion(new DefaultArtifactVersion(featureLauncherVersion));
RepositorySystemSession repositorySession = mavenSession.getRepositorySession();
File workDir = new File(outputDirectory, "launchers");
workDir.mkdirs();
File launcher;
if (useAssembly) {
// fetch the assembly artifact
Artifact launcherAssemblyArtifact = new DefaultArtifact("org.apache.sling:org.apache.sling.feature.launcher:tar.gz:" + featureLauncherVersion);
File assemblyArchive = resolver
.resolveArtifact(repositorySession, new ArtifactRequest(launcherAssemblyArtifact, remoteRepos, null))
.getArtifact()
.getFile();
// unpack the file
UnArchiver unArchiver = archiverManager.getUnArchiver( assemblyArchive );
unArchiver.setSourceFile(assemblyArchive);
unArchiver.setDestFile(workDir);
unArchiver.extract();
// system property
Path relPath = Paths.get(launcherAssemblyArtifact.getArtifactId() + "-" + launcherAssemblyArtifact.getVersion(), "bin");
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
relPath = relPath.resolve("launcher.bat");
} else {
relPath = relPath.resolve("launcher");
}
launcher = workDir.toPath().resolve(relPath).toFile();
} else {
Artifact launcherArtifact = new DefaultArtifact("org.apache.sling:org.apache.sling.feature.launcher:" + featureLauncherVersion);
launcher = resolver
.resolveArtifact(repositorySession, new ArtifactRequest(launcherArtifact, remoteRepos, null))
.getArtifact()
.getFile();
}
for ( Launch launch : launches ) {
if (launch.isSkip()) {
getLog().info("Skipping starting launch with id " + launch.getId());
continue; // skip it
}
launch.validate();
Artifact artifact = toArtifact(launch.getFeature());
ArtifactResult result = resolver.resolveArtifact(repositorySession, new ArtifactRequest(artifact, remoteRepos, null));
File featureFile = result.getArtifact().getFile();
String javahome = System.getenv(JAVA_HOME);
if (javahome == null || javahome.isEmpty()) {
// SLING-9843 fallback to java.home system property if JAVA_HOME env variable is not set
getLog().warn("The JAVA_HOME env variable was not set, falling back to the java.home system property");
javahome = System.getProperty("java.home");
}
List<String> args = new ArrayList<>();
if (useAssembly) {
// use the post v1.1.28 launcher script
Map<String, String> newEnv = new HashMap<>(launch.getEnvironmentVariables());
newEnv.put(JAVA_HOME, javahome);
// SLING-9994 - if any extra vm options were supplied, apply them here
StringBuilder javaOptsBuilder = null;
String[] vmOptions = launch.getLauncherArguments().getVmOptions();
for (String vmOption : vmOptions) {
if (vmOption != null && !vmOption.isEmpty()) {
if (javaOptsBuilder == null) {
javaOptsBuilder = new StringBuilder();
} else {
javaOptsBuilder.append(" ");
}
javaOptsBuilder.append(vmOption);
}
}
if (javaOptsBuilder != null) {
// pass vmOptions through JAVA_OPTS environment variable?
if (newEnv.containsKey(JAVA_OPTS)) {
// if the original value existed append it to our buffer
javaOptsBuilder.append(" ").append(newEnv.get(JAVA_OPTS));
}
newEnv.put(JAVA_OPTS, javaOptsBuilder.toString());
}
args.add(launcher.getAbsolutePath());
launch.setEnvironmentVariables(newEnv);
} else {
// use the pre v1.1.28 single jar technique
args.add(javahome + File.separatorChar + "bin" + File.separatorChar + "java");
// SLING-9994 - if any extra vm options were supplied, apply them here
String[] vmOptions = launch.getLauncherArguments().getVmOptions();
for (String vmOption : vmOptions) {
if (vmOption != null && !vmOption.isEmpty()) {
args.add(vmOption);
}
}
args.add("-jar");
args.add(launcher.getAbsolutePath());
}
if ( launch.getRepositoryUrls() != null && !launch.getRepositoryUrls().isEmpty() ) {
args.add("-u");
StringJoiner joiner = new StringJoiner(",");
launch.getRepositoryUrls().forEach( joiner::add );
args.add(joiner.toString());
}
args.add("-f");
args.add(featureFile.getAbsolutePath());
args.add("-p");
args.add(launch.getId());
for ( Map.Entry<String, String> frameworkProperty : launch.getLauncherArguments().getFrameworkProperties().entrySet() ) {
args.add("-D");
args.add(frameworkProperty.getKey()+"="+frameworkProperty.getValue());
}
for ( Map.Entry<String, String> variable : launch.getLauncherArguments().getVariables().entrySet() ) {
args.add("-V");
args.add(variable.getKey()+"="+variable.getValue());
}
// TODO - add support for all arguments supported by the feature launcher
ProcessBuilder pb = new ProcessBuilder(args);
pb.redirectOutput(Redirect.INHERIT);
pb.redirectInput(Redirect.INHERIT);
pb.directory(workDir);
launch.getEnvironmentVariables().entrySet()
.forEach( e -> {
getLog().info("Setting environment variable '" + e.getKey() + "' to '" + e.getValue() + "'");
pb.environment().put(e.getKey(), e.getValue());
} );
getLog().info("Starting launch with id '" + launch.getId() + "', args=" + args);
CountDownLatch latch = new CountDownLatch(1);
Process process = pb.start();
Thread monitor = new Thread("launch-monitor-" + launch.getId()) {
@Override
public void run() {
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
String line;
try {
while ( (line = reader.readLine()) != null ) {
System.out.println(line); // NOSONAR - we pass through the subprocess stderr
if ( line.contains("Framework started")) {
latch.countDown();
break;
}
}
} catch (IOException e) {
getLog().warn(e.getMessage(), e);
}
}
};
monitor.start();
getLog().info("Waiting for " + launch.getId() + " to start");
boolean started = latch.await(launch.getStartTimeoutSeconds(), TimeUnit.SECONDS);
if ( !started ) {
ProcessTracker.stop(process);
throw new MojoExecutionException("Launch " + launch.getId() + " failed to start in " + launch.getStartTimeoutSeconds() + " seconds.");
}
processes.startTracking(launch.getId(), process);
}
} catch (NoSuchArchiverException | InvalidVersionSpecificationException | ArtifactResolutionException | IOException e) {
throw new MojoExecutionException(e.getMessage(), e);
} catch ( InterruptedException e ) {
Thread.currentThread().interrupt();
throw new MojoExecutionException("Execution interrupted", e);
}
}