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 a2fc1032e9e87500f4e0fc7ca275b035346ee245 Author: Robert Munteanu <[email protected]> AuthorDate: Tue Jun 23 00:25:28 2020 +0200 SLING-9526 - Allow launching feature model applications in external processes, non-blocking Started drafting an implementation in a separate project. --- pom.xml | 163 +++++++++++++++++++++ src/it/settings.xml | 53 +++++++ src/it/simple-it/pom.xml | 61 ++++++++ src/it/simple-it/verify.groovy | 21 +++ .../sling/maven/feature/launcher/Processes.java | 35 +++++ .../sling/maven/feature/launcher/StartMojo.java | 129 ++++++++++++++++ .../sling/maven/feature/launcher/StopMojo.java | 49 +++++++ .../maven/feature/launcher/StartMojoTest.java | 54 +++++++ src/test/resources/project-to-test/pom.xml | 56 +++++++ 9 files changed, 621 insertions(+) diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..1305e2b --- /dev/null +++ b/pom.xml @@ -0,0 +1,163 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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. +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.apache.sling</groupId> + <artifactId>sling</artifactId> + <version>39</version> + <relativePath /> + </parent> + + <artifactId>feature-launcher-maven-plugin</artifactId> + <version>1.0-SNAPSHOT</version> + <packaging>maven-plugin</packaging> + + <name>Feature Launcher Maven Plugin</name> + + <prerequisites> + <maven>${maven.version}</maven> + </prerequisites> + + <properties> + <sling.java.version>11</sling.java.version> + <maven.version>3.3.9</maven.version> + </properties> + + <dependencies> + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-plugin-api</artifactId> + <version>${maven.version}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-core</artifactId> + <version>${maven.version}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-artifact</artifactId> + <version>${maven.version}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.apache.maven.plugin-tools</groupId> + <artifactId>maven-plugin-annotations</artifactId> + <version>3.6.0</version> + <scope>provided</scope> + </dependency> + + <dependency> + <groupId>org.apache.sling</groupId> + <artifactId>org.apache.sling.feature.launcher</artifactId> + <version>1.1.4</version> + </dependency> + + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-compat</artifactId> + <version>${maven.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.maven.plugin-testing</groupId> + <artifactId>maven-plugin-testing-harness</artifactId> + <version>3.3.0</version> + <scope>test</scope> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-plugin-plugin</artifactId> + <version>3.6.0</version> + <configuration> + <!-- <goalPrefix>maven-archetype-plugin</goalPrefix> --> + <skipErrorNoDescriptorsFound>true</skipErrorNoDescriptorsFound> + </configuration> + <executions> + <execution> + <id>mojo-descriptor</id> + <goals> + <goal>descriptor</goal> + </goals> + </execution> + <execution> + <id>help-goal</id> + <goals> + <goal>helpmojo</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> + + <profiles> + <profile> + <id>run-its</id> + <build> + + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-invoker-plugin</artifactId> + <configuration> + <debug>true</debug> + <cloneProjectsTo>${project.build.directory}/it</cloneProjectsTo> + <pomIncludes> + <pomInclude>*/pom.xml</pomInclude> + </pomIncludes> + <postBuildHookScript>verify</postBuildHookScript> + <localRepositoryPath>${project.build.directory}/local-repo</localRepositoryPath> + <settingsFile>src/it/settings.xml</settingsFile> + <goals> + <goal>clean</goal> + <goal>verify</goal> + </goals> + </configuration> + <executions> + <execution> + <id>integration-test</id> + <goals> + <goal>install</goal> + <goal>integration-test</goal> + <goal>verify</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> + </profile> + </profiles> +</project> diff --git a/src/it/settings.xml b/src/it/settings.xml new file mode 100644 index 0000000..3395ba3 --- /dev/null +++ b/src/it/settings.xml @@ -0,0 +1,53 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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. +--> +<settings> + <profiles> + <profile> + <id>it-repo</id> + <activation> + <activeByDefault>true</activeByDefault> + </activation> + <repositories> + <repository> + <id>local.central</id> + <url>@localRepositoryUrl@</url> + <releases> + <enabled>true</enabled> + </releases> + <snapshots> + <enabled>true</enabled> + </snapshots> + </repository> + </repositories> + <pluginRepositories> + <pluginRepository> + <id>local.central</id> + <url>@localRepositoryUrl@</url> + <releases> + <enabled>true</enabled> + </releases> + <snapshots> + <enabled>true</enabled> + </snapshots> + </pluginRepository> + </pluginRepositories> + </profile> + </profiles> +</settings> diff --git a/src/it/simple-it/pom.xml b/src/it/simple-it/pom.xml new file mode 100644 index 0000000..e63422f --- /dev/null +++ b/src/it/simple-it/pom.xml @@ -0,0 +1,61 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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. +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <groupId>org.apache.sling</groupId> + <artifactId>simple-it</artifactId> + <version>1.0-SNAPSHOT</version> + + <description>A simple IT verifying the basic use case.</description> + + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + </properties> + + <build> + <plugins> + <plugin> + <groupId>@project.groupId@</groupId> + <artifactId>@project.artifactId@</artifactId> + <version>@project.version@</version> + <configuration> + <toLaunch> + <groupId>org.apache.sling</groupId> + <artifactId>org.apache.sling.starter</artifactId> + <version>12-SNAPSHOT</version> + <classifier>oak_tar</classifier> + <type>slingosgifeature</type> + </toLaunch> + </configuration> + <executions> + <execution> + <id>touch</id> + <goals> + <goal>start</goal> + <goal>stop</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> +</project> diff --git a/src/it/simple-it/verify.groovy b/src/it/simple-it/verify.groovy new file mode 100644 index 0000000..e9b7465 --- /dev/null +++ b/src/it/simple-it/verify.groovy @@ -0,0 +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. + */ +File touchFile = new File( basedir, "build.log" ); + +assert touchFile.isFile() 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 new file mode 100644 index 0000000..85eed28 --- /dev/null +++ b/src/main/java/org/apache/sling/maven/feature/launcher/Processes.java @@ -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. + */ +package org.apache.sling.maven.feature.launcher; + +import java.util.Optional; + +// TODO - refactor to a Mojo Component +public class Processes { + + private static Process process; + + public static void set(Process process) { + Processes.process = process; + } + + public static Optional<Process> get() { + return Optional.ofNullable(process); + } +} 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 new file mode 100644 index 0000000..4b39d99 --- /dev/null +++ b/src/main/java/org/apache/sling/maven/feature/launcher/StartMojo.java @@ -0,0 +1,129 @@ +/* + * 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.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.maven.execution.MavenSession; +import org.apache.maven.model.Dependency; +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; +import org.apache.maven.project.MavenProject; +import org.eclipse.aether.RepositorySystemSession; +import org.eclipse.aether.artifact.Artifact; +import org.eclipse.aether.artifact.DefaultArtifact; +import org.eclipse.aether.impl.ArtifactResolver; +import org.eclipse.aether.resolution.ArtifactRequest; +import org.eclipse.aether.resolution.ArtifactResolutionException; +import org.eclipse.aether.resolution.ArtifactResult; + +@Mojo( name = "start", defaultPhase = LifecyclePhase.PRE_INTEGRATION_TEST ) +public class StartMojo + extends AbstractMojo +{ + /** + * Location of the file. + */ + @Parameter( defaultValue = "${project.build.directory}", property = "outputDir", required = true ) + private File outputDirectory; + + // TODO - support multiple dependencies and also have proper parameter names + @Parameter(required = true) + private Dependency toLaunch; + + @Parameter + private Map<String, String> frameworkProperties = new HashMap<String, String>(); + + @Component + private ArtifactResolver resolver; + + @Parameter(property = "project", readonly = true, required = true) + protected MavenProject project; + + @Parameter(property = "session", readonly = true, required = true) + protected MavenSession mavenSession; + + public void execute() + throws MojoExecutionException, MojoFailureException + { + + try { + RepositorySystemSession repositorySession = mavenSession.getRepositorySession(); + Artifact artifact = toArtifact(toLaunch); + + ArtifactResult result = resolver.resolveArtifact(repositorySession, new ArtifactRequest(artifact, null, null)); + File featureFile = result.getArtifact().getFile(); + + + // TODO - this should be inferred from the plugin's pom.xml dependency (not the project's pom.xml) + Dependency featureLauncherDep = project.getDependencies().stream() + .filter( d -> d.getGroupId().equals("org.apache.sling") && d.getArtifactId().equals("org.apache.sling.feature.launcher")) + .findFirst() + .orElseThrow( () -> new MojoFailureException("No feature launcher dependency found")); + + Artifact launcherArtifact = toArtifact(featureLauncherDep); + File launcher = resolver + .resolveArtifact(repositorySession, new ArtifactRequest(launcherArtifact, null, null)) + .getArtifact() + .getFile(); + + File workDir = new File(outputDirectory, "launchers"); + workDir.mkdirs(); + + List<String> args = new ArrayList<>(); + args.add(System.getenv("JAVA_HOME") + File.separatorChar + "bin" + File.separatorChar + "java"); + args.add("-jar"); + args.add(launcher.getAbsolutePath()); + args.add("-f"); + args.add(featureFile.getAbsolutePath()); + + for ( var frameworkProperty : frameworkProperties.entrySet() ) { + args.add("-D"); + args.add(frameworkProperty.getKey()+"="+frameworkProperty.getValue()); + } + + // TODO - add support for all arguments supported by the feature launcher + ProcessBuilder pb = new ProcessBuilder(args); + pb.inheritIO(); + pb.directory(workDir); + Process process = pb.start(); + + // TODO - reliably stop started processes in case 'stop' is not invoked + + Processes.set(process); + } catch (ArtifactResolutionException | IOException e) { + throw new MojoExecutionException(e.getMessage(), e); + } + } + + private Artifact toArtifact(Dependency dependency) { + return new DefaultArtifact(dependency.getGroupId(), dependency.getArtifactId(), dependency.getClassifier(), dependency.getType(), dependency.getVersion()); + } +} 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 new file mode 100644 index 0000000..837a0c2 --- /dev/null +++ b/src/main/java/org/apache/sling/maven/feature/launcher/StopMojo.java @@ -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. + */ +package org.apache.sling.maven.feature.launcher; + +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.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; + +@Mojo( name = "stop", defaultPhase = LifecyclePhase.POST_INTEGRATION_TEST) +public class StopMojo extends AbstractMojo { + + @Override + public void execute() throws MojoExecutionException, MojoFailureException { + + try { + // TODO - for testing only, remove once the IT does something meaningful + Thread.sleep(30 * 1000); + + Process process = Processes.get() + .get(); + + process.destroy(); + process.waitFor(30, TimeUnit.SECONDS); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + +} diff --git a/src/test/java/org/apache/sling/maven/feature/launcher/StartMojoTest.java b/src/test/java/org/apache/sling/maven/feature/launcher/StartMojoTest.java new file mode 100644 index 0000000..859a706 --- /dev/null +++ b/src/test/java/org/apache/sling/maven/feature/launcher/StartMojoTest.java @@ -0,0 +1,54 @@ +/* + * 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 static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.File; + +import org.apache.maven.plugin.testing.MojoRule; +import org.junit.Ignore; +import org.junit.Rule; +import org.junit.Test; + +public class StartMojoTest { + @Rule + public MojoRule rule = new MojoRule(); + + @Test + @Ignore + // TODO - re-enable + public void startAndStop() throws Exception { + File pom = new File("target/test-classes/project-to-test/"); + assertNotNull(pom); + assertTrue(pom.exists()); + + StartMojo myMojo = (StartMojo) rule.lookupConfiguredMojo(pom, "start"); + assertNotNull(myMojo); + myMojo.execute(); + + File outputDirectory = (File) rule.getVariableValueFromObject(myMojo, "outputDirectory"); + assertNotNull(outputDirectory); + assertTrue(outputDirectory.exists()); + + File touch = new File(outputDirectory, "touch.txt"); + assertTrue(touch.exists()); + } +} diff --git a/src/test/resources/project-to-test/pom.xml b/src/test/resources/project-to-test/pom.xml new file mode 100644 index 0000000..3bf366c --- /dev/null +++ b/src/test/resources/project-to-test/pom.xml @@ -0,0 +1,56 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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. +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <groupId>org.apache.sling</groupId> + <artifactId>feature-launcher-maven-plugin</artifactId> + <version>1.0-SNAPSHOT</version> + <packaging>jar</packaging> + <name>Test StartMojo</name> + + <build> + <plugins> + <plugin> + <artifactId>maven-my-plugin</artifactId> + <version>1.0-SNAPSHOT</version> + <configuration> + <toLaunch> + <groupId>org.apache.sling</groupId> + <artifactId>org.apache.sling.starter</artifactId> + <version>12-SNAPSHOT</version> + <classifier>oak_tar</classifier> + <type>slingosgifeature</type> + </toLaunch> + </configuration> + <executions> + <execution> + <goals> + <goal>start</goal> + <goal>stop</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> +</project>
