This is an automated email from the ASF dual-hosted git repository. rombert pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/sling-feature-launcher-maven-plugin.git
commit d65f6d72f39f6494229831af315dbcb6eabc15c0 Author: Robert Munteanu <[email protected]> AuthorDate: Thu Jun 25 15:47:45 2020 +0200 SLING-9526 - Allow launching feature model applications in external processes, non-blocking Process tracking improvements. --- pom.xml | 13 ++++ .../maven/feature/launcher/ProcessTracker.java | 73 ++++++++++++++++++++++ .../sling/maven/feature/launcher/Processes.java | 38 ----------- .../sling/maven/feature/launcher/StartMojo.java | 13 ++-- .../sling/maven/feature/launcher/StopMojo.java | 9 +-- 5 files changed, 96 insertions(+), 50 deletions(-) diff --git a/pom.xml b/pom.xml index 996b2fa..582ed80 100644 --- a/pom.xml +++ b/pom.xml @@ -97,6 +97,19 @@ <build> <plugins> <plugin> + <groupId>org.codehaus.plexus</groupId> + <artifactId>plexus-component-metadata</artifactId> + <version>1.7.1</version> + <executions> + <execution> + <id>generate-metadata</id> + <goals> + <goal>generate-metadata</goal> + </goals> + </execution> + </executions> + </plugin> + <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-plugin-plugin</artifactId> <version>3.6.0</version> diff --git a/src/main/java/org/apache/sling/maven/feature/launcher/ProcessTracker.java b/src/main/java/org/apache/sling/maven/feature/launcher/ProcessTracker.java new file mode 100644 index 0000000..694a453 --- /dev/null +++ b/src/main/java/org/apache/sling/maven/feature/launcher/ProcessTracker.java @@ -0,0 +1,73 @@ +/* + * 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.sling.maven.feature.launcher; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import org.codehaus.plexus.component.annotations.Component; + +@Component(role = ProcessTracker.class) +public class ProcessTracker { + + static void stop(Process process) throws InterruptedException { + process.destroy(); + boolean stopped = process.waitFor(30, TimeUnit.SECONDS); + if ( !stopped ) + process.destroyForcibly(); + } + + private final Object sync = new Object(); + + private boolean hookAdded = false; + private final Map<String, Process> processes = new HashMap<>(); + + public void startTracking(String launchId, Process process) { + synchronized (sync) { + if ( processes.containsKey(launchId) ) + throw new IllegalArgumentException("Launch id " + launchId + " already associated with a process"); + processes.put(launchId, process); + if ( ! hookAdded ) { + Runtime.getRuntime().addShutdownHook(new Thread("process-tracker-shutdown") { + @Override + public void run() { + for ( Map.Entry<String, Process> entry : processes.entrySet() ) { + System.err.println("Launch " + entry.getKey() + " was not shut down! Destroying forcibly from shutdown hook.."); + process.destroyForcibly(); + } + } + + }); + hookAdded = true; + } + } + } + + public void stop(String id) throws InterruptedException { + Process process; + synchronized (sync) { + process = processes.remove(id); + } + if ( process == null ) + return; + + stop(process); + } +} diff --git a/src/main/java/org/apache/sling/maven/feature/launcher/Processes.java b/src/main/java/org/apache/sling/maven/feature/launcher/Processes.java deleted file mode 100644 index 79d7351..0000000 --- a/src/main/java/org/apache/sling/maven/feature/launcher/Processes.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.sling.maven.feature.launcher; - -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; - -// TODO - refactor to a Mojo Component -public class Processes { - - private static final Map<String, Process> processes = new HashMap<>(); - - public static void addProcess(String id, Process process) { - // TODO - check for duplicates - processes.put(id, process); - } - - public static Optional<Process> get(String id) { - return Optional.ofNullable(processes.get(id)); - } -} diff --git a/src/main/java/org/apache/sling/maven/feature/launcher/StartMojo.java b/src/main/java/org/apache/sling/maven/feature/launcher/StartMojo.java index 72b82c8..5f6a87c 100644 --- a/src/main/java/org/apache/sling/maven/feature/launcher/StartMojo.java +++ b/src/main/java/org/apache/sling/maven/feature/launcher/StartMojo.java @@ -84,6 +84,9 @@ public class StartMojo @Parameter(property = "session", readonly = true, required = true) protected MavenSession mavenSession; + @Component + private ProcessTracker processes; + public void execute() throws MojoExecutionException, MojoFailureException { @@ -165,17 +168,11 @@ public class StartMojo // TODO - configurable timeouts boolean started = latch.await(3, TimeUnit.MINUTES); if ( !started ) { - process.destroy(); - boolean stopped = process.waitFor(30, TimeUnit.SECONDS); - if ( !stopped ) - process.destroyForcibly(); + ProcessTracker.stop(process); throw new MojoExecutionException("Launch " + launch.getId() + " failed to start in the allocated time."); } - - // TODO - reliably stop started processes in case 'stop' is not invoked - - Processes.addProcess(launch.getId(), process); + processes.startTracking(launch.getId(), process); } // TODO - properly handle interrupted exception diff --git a/src/main/java/org/apache/sling/maven/feature/launcher/StopMojo.java b/src/main/java/org/apache/sling/maven/feature/launcher/StopMojo.java index d3b10bf..d8665d8 100644 --- a/src/main/java/org/apache/sling/maven/feature/launcher/StopMojo.java +++ b/src/main/java/org/apache/sling/maven/feature/launcher/StopMojo.java @@ -19,11 +19,11 @@ package org.apache.sling.maven.feature.launcher; import java.util.List; -import java.util.concurrent.TimeUnit; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; +import org.apache.maven.plugins.annotations.Component; import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; @@ -34,15 +34,16 @@ public class StopMojo extends AbstractMojo { @Parameter(required = true) private List<Launch> launches; + @Component + private ProcessTracker processes; + @Override public void execute() throws MojoExecutionException, MojoFailureException { try { for ( Launch launch : launches ) { getLog().info("Stopping launch with id " + launch.getId()); - Process process = Processes.get(launch.getId()).get(); - process.destroy(); - process.waitFor(30, TimeUnit.SECONDS); + processes.stop(launch.getId()); } } catch (InterruptedException e) { Thread.currentThread().interrupt();
