You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by jb...@apache.org on 2020/09/04 16:43:08 UTC
[karaf] branch master updated: Enhance RunMojo to let it configure
main args, console log level,
system properties and be able to deploy a bundle before/after the features
with local lookup instead of assuming the artifact is attached to the
project (karaf:run without any other goal)
This is an automated email from the ASF dual-hosted git repository.
jbonofre pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/karaf.git
The following commit(s) were added to refs/heads/master by this push:
new 84273d8 Enhance RunMojo to let it configure main args, console log level, system properties and be able to deploy a bundle before/after the features with local lookup instead of assuming the artifact is attached to the project (karaf:run without any other goal)
new 2973e54 This closes #1169
84273d8 is described below
commit 84273d897a0b8035e2369db05c3743da0a30e350
Author: Romain Manni-Bucau <rm...@gmail.com>
AuthorDate: Fri Aug 28 09:40:47 2020 +0200
Enhance RunMojo to let it configure main args, console log level, system properties and be able to deploy a bundle before/after the features with local lookup instead of assuming the artifact is attached to the project (karaf:run without any other goal)
---
.../java/org/apache/karaf/tooling/RunMojo.java | 112 +++++++++++++--
.../java/org/apache/karaf/tooling/RunMojoTest.java | 153 +++++++++++++++++----
2 files changed, 227 insertions(+), 38 deletions(-)
diff --git a/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/RunMojo.java b/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/RunMojo.java
index feeb878..8aa6ba0 100644
--- a/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/RunMojo.java
+++ b/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/RunMojo.java
@@ -48,6 +48,8 @@ import java.lang.reflect.Method;
import java.net.URI;
import java.nio.file.Files;
import java.util.List;
+import java.util.Map;
+import java.util.Properties;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -78,6 +80,22 @@ public class RunMojo extends MojoSupport {
private boolean deployProjectArtifact = true;
/**
+ * If set and the artifact is not attached to the project, this location will be used.
+ * It enables to launch <code>karaf:run</code> without building/attaching the artifact.
+ * A typical good value is
+ * {@code <fallbackLocalProjectArtifact>${project.build.directory}/${project.build.finalName}.jar</fallbackLocalProjectArtifact>}.
+ */
+ @Parameter
+ private File fallbackLocalProjectArtifact;
+
+ /**
+ * If true project and <code>deployProjectArtifact</code> is true,
+ * artifact is deployed after the feature installation, otherwise before.
+ */
+ @Parameter(defaultValue = "false")
+ private boolean deployAfterFeatures = false;
+
+ /**
* A list of URLs referencing feature repositories that will be added
* to the karaf instance started by this goal.
*/
@@ -85,6 +103,22 @@ public class RunMojo extends MojoSupport {
private String[] featureRepositories = null;
/**
+ * Karaf main args.
+ */
+ @Parameter
+ private String[] mainArgs;
+
+ /**
+ * Karaf console log level
+ * (<code>karaf.log.console</code> value used in default karaf logging configuration).
+ */
+ @Parameter
+ private String consoleLogLevel;
+
+ @Parameter
+ private Map<String, String> systemProperties;
+
+ /**
* Comma-separated list of features to install.
*/
@Parameter(defaultValue = "")
@@ -111,6 +145,13 @@ public class RunMojo extends MojoSupport {
private static final Pattern mvnPattern = Pattern.compile("mvn:([^/ ]+)/([^/ ]+)/([^/ ]*)(/([^/ ]+)(/([^/ ]+))?)?");
public void execute() throws MojoExecutionException, MojoFailureException {
+ // reset system properties after the execution to ensure not not pollute the maven build
+ final Properties originalProperties = new Properties();
+ originalProperties.putAll(System.getProperties());
+
+ // before any mkdir or so since "clean" is handled
+ final String[] args = handleArgs(karafDirectory, mainArgs == null ? new String[0] : mainArgs);
+
if (karafDirectory.exists()) {
getLog().info("Using Karaf container located " + karafDirectory.getAbsolutePath());
} else {
@@ -130,9 +171,18 @@ public class RunMojo extends MojoSupport {
System.setProperty("karaf.etc", karafDirectory.getAbsolutePath() + "/etc");
System.setProperty("karaf.log", karafDirectory.getAbsolutePath() + "/data/log");
System.setProperty("karaf.instances", karafDirectory.getAbsolutePath() + "/instances");
- System.setProperty("karaf.startLocalConsole", "false");
+ if (System.getProperty("karaf.startLocalConsole") == null) {
+ System.setProperty("karaf.startLocalConsole", "false");
+ }
System.setProperty("karaf.startRemoteShell", startSsh);
System.setProperty("karaf.lock", "false");
+ if (consoleLogLevel != null && !consoleLogLevel.isEmpty()) {
+ System.setProperty("karaf.log.console", consoleLogLevel);
+ }
+ // last to ensure it wins over defaults/shortcuts
+ if (systemProperties != null) {
+ systemProperties.forEach(System::setProperty);
+ }
String featureBootFinished = BootFinished.class.getName();
Thread bootThread = Thread.currentThread();
@@ -147,12 +197,7 @@ public class RunMojo extends MojoSupport {
return super.loadClass(name, resolve);
}
};
- Main main = new Main(new String[0]) {
- @Override
- protected ClassLoader getParentClassLoader() {
- return bootLoader;
- }
- };
+ final Main main = newMain(bootLoader, args);
try {
long start = System.nanoTime();
@@ -204,8 +249,13 @@ public class RunMojo extends MojoSupport {
Object featureService = findFeatureService(featureBundleCtx);
addFeatureRepositories(featureService);
- deploy(featureBundleCtx, featureService);
+ if (!deployAfterFeatures) {
+ deploy(featureBundleCtx, featureService);
+ }
addFeatures(featureService);
+ if (deployAfterFeatures) {
+ deploy(featureBundleCtx, featureService);
+ }
if (keepRunning)
main.awaitShutdown();
main.destroy();
@@ -213,9 +263,44 @@ public class RunMojo extends MojoSupport {
throw new MojoExecutionException("Can't start container", e);
} finally {
System.gc();
+ System.getProperties().clear();
+ System.getProperties().putAll(originalProperties);
}
}
+ private String[] handleArgs(final File base, final String[] strings) {
+ return Stream.of(strings)
+ .filter(it -> {
+ switch (it) {
+ case "console":
+ System.setProperty("karaf.startLocalConsole", "true");
+ return false;
+ case "clean":
+ if (base.exists()) {
+ getLog().info("Cleaning " + base);
+ try {
+ FileUtils.deleteDirectory(base);
+ } catch (final IOException e) { // assuming it failed on win
+ getLog().error(e.getMessage(), e);
+ }
+ }
+ return false;
+ default:
+ return true;
+ }
+ })
+ .toArray(String[]::new);
+ }
+
+ protected Main newMain(final ClassLoader bootLoader, final String[] args) {
+ return new Main(args) {
+ @Override
+ protected ClassLoader getParentClassLoader() {
+ return bootLoader;
+ }
+ };
+ }
+
// todo: maybe add it as a mojo parameter to reduce it for light distro?
private void waitForValidState() throws InterruptedException {
Thread.sleep(1000);
@@ -248,7 +333,7 @@ public class RunMojo extends MojoSupport {
void deploy(BundleContext bundleContext, Object featureService) throws MojoExecutionException {
if (deployProjectArtifact) {
- File artifact = project.getArtifact().getFile();
+ File artifact = getProjectArtifact();
File attachedFeatureFile = getAttachedFeatureFile(project);
boolean artifactExists = artifact != null && artifact.exists();
if (!artifactExists) {
@@ -274,6 +359,15 @@ public class RunMojo extends MojoSupport {
}
}
+ private File getProjectArtifact() {
+ final File file = project.getArtifact().getFile();
+ if ((file == null || !file.exists()) &&
+ fallbackLocalProjectArtifact != null && fallbackLocalProjectArtifact.exists()) {
+ return fallbackLocalProjectArtifact;
+ }
+ return file;
+ }
+
void addFeatures(Object featureService) throws MojoExecutionException {
if (featuresToInstall != null) {
try {
diff --git a/tooling/karaf-maven-plugin/src/test/java/org/apache/karaf/tooling/RunMojoTest.java b/tooling/karaf-maven-plugin/src/test/java/org/apache/karaf/tooling/RunMojoTest.java
index b584a7e..6b8b9c2 100644
--- a/tooling/karaf-maven-plugin/src/test/java/org/apache/karaf/tooling/RunMojoTest.java
+++ b/tooling/karaf-maven-plugin/src/test/java/org/apache/karaf/tooling/RunMojoTest.java
@@ -16,27 +16,87 @@
*/
package org.apache.karaf.tooling;
+import static java.util.Collections.singletonMap;
import static org.junit.Assert.*;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.net.URI;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Function;
+import java.util.stream.Stream;
import org.apache.karaf.features.FeaturesService;
+import org.apache.karaf.main.Main;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.project.MavenProject;
import static org.easymock.EasyMock.*;
import org.easymock.EasyMock;
import org.easymock.EasyMockSupport;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.osgi.framework.ServiceReference;
public class RunMojoTest extends EasyMockSupport {
+ @Rule
+ public final TemporaryFolder temporaryFolder = new TemporaryFolder();
+
+ @Test
+ public void testArgs() throws IllegalAccessException,
+ MojoFailureException, MojoExecutionException, IOException {
+ final AtomicReference<String[]> capturedArgs = new AtomicReference<>();
+ final RunMojo mojo = newRunMojo(args -> {
+ capturedArgs.set(args);
+ throw new FastExit();
+ });
+ setPrivateField(mojo, "mainArgs", new String[]{"foo"});
+ try {
+ mojo.execute();
+ } catch (final FastExit fe) {
+ // expected
+ }
+ assertArrayEquals(new String[]{"foo"}, capturedArgs.get());
+ }
+
+ @Test
+ public void testSystemProperties() throws IllegalAccessException,
+ MojoFailureException, MojoExecutionException, IOException {
+ final RunMojo mojo = newRunMojo(args -> {
+ throw new FastExit();
+ });
+ setPrivateField(mojo, "systemProperties", singletonMap("RunMojoTest.testSystemProperties", "set"));
+ try {
+ mojo.execute();
+ } catch (final FastExit fe) {
+ // expected
+ }
+ assertEquals("set", System.clearProperty("RunMojoTest.testSystemProperties"));
+ }
+
+ @Test
+ public void testConsoleLevel() throws IllegalAccessException,
+ MojoFailureException, MojoExecutionException, IOException {
+ final RunMojo mojo = newRunMojo(args -> {
+ throw new FastExit();
+ });
+ setPrivateField(mojo, "consoleLogLevel", "INFO");
+ try {
+ mojo.execute();
+ } catch (final FastExit fe) {
+ // expected
+ }
+ assertEquals("INFO", System.clearProperty("karaf.log.console"));
+ }
@Test
public void testAddFeatureRepositoriesWithNullRepoList() throws MojoExecutionException {
@@ -49,7 +109,7 @@ public class RunMojoTest extends EasyMockSupport {
}
@Test
- public void testAddFeatureRepositoriesWithEmptyRepoListAndNullFeatureService() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, MojoExecutionException {
+ public void testAddFeatureRepositoriesWithEmptyRepoListAndNullFeatureService() throws SecurityException, IllegalArgumentException, IllegalAccessException, MojoExecutionException {
RunMojo mojo = new RunMojo();
String[] empty = new String[0];
setPrivateField(mojo, "featureRepositories", empty);
@@ -62,7 +122,7 @@ public class RunMojoTest extends EasyMockSupport {
}
@Test
- public void testAddFeatureRepositoriesWithEmptyRepoList() throws MojoExecutionException, NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
+ public void testAddFeatureRepositoriesWithEmptyRepoList() throws MojoExecutionException, SecurityException, IllegalArgumentException, IllegalAccessException {
FeaturesService featureService = mock(FeaturesService.class);
replay(featureService);
@@ -88,7 +148,7 @@ public class RunMojoTest extends EasyMockSupport {
}
@Test
- public void testDeployWithDeployProjectArtifactFalse() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, MojoExecutionException {
+ public void testDeployWithDeployProjectArtifactFalse() throws SecurityException, IllegalArgumentException, IllegalAccessException, MojoExecutionException {
BundleContext context = mock(BundleContext.class);
RunMojo mojo = new RunMojo();
setPrivateField(mojo, "deployProjectArtifact", false);
@@ -96,13 +156,13 @@ public class RunMojoTest extends EasyMockSupport {
}
@Test
- public void testDeployWithNullArtifact() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
+ public void testDeployWithNullArtifact() throws SecurityException, IllegalArgumentException, IllegalAccessException {
BundleContext context = mock(BundleContext.class);
Artifact artifact = mock(Artifact.class);
RunMojo mojo = new RunMojo();
MavenProject project = new MavenProject();
project.setArtifact(artifact);
- setInheritedPrivateField(mojo, "project", project);
+ setPrivateField(mojo, "project", project);
try {
mojo.deploy(context, null);
fail("Expected MojoExecutionException");
@@ -112,16 +172,18 @@ public class RunMojoTest extends EasyMockSupport {
}
@Test
- public void testDeployWithNonExistingArtifact() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
+ public void testDeployWithNonExistingArtifact() throws SecurityException, IllegalArgumentException, IllegalAccessException {
BundleContext context = mock(BundleContext.class);
Artifact artifact = mock(Artifact.class);
File artifactFile = mock(File.class);
expect(artifact.getFile()).andReturn(artifactFile);
+ expect(artifactFile.exists()).andReturn(false).times(2);
+ replay(artifactFile);
replay(artifact);
RunMojo mojo = new RunMojo();
MavenProject project = new MavenProject();
project.setArtifact(artifact);
- setInheritedPrivateField(mojo, "project", project);
+ setPrivateField(mojo, "project", project);
try {
mojo.deploy(context, null);
fail("Expected MojoExecutionException");
@@ -131,18 +193,18 @@ public class RunMojoTest extends EasyMockSupport {
}
@Test
- public void testDeployWithExistingArtifactButProjectNotBundle() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
+ public void testDeployWithExistingArtifactButProjectNotBundle() throws SecurityException, IllegalArgumentException, IllegalAccessException {
BundleContext context = mock(BundleContext.class);
Artifact artifact = mock(Artifact.class);
File artifactFile = mock(File.class);
- expect(artifactFile.exists()).andReturn(true);
+ expect(artifactFile.exists()).andReturn(true).times(2);
replay(artifactFile);
expect(artifact.getFile()).andReturn(artifactFile);
replay(artifact);
RunMojo mojo = new RunMojo();
MavenProject project = new MavenProject();
project.setArtifact(artifact);
- setInheritedPrivateField(mojo, "project", project);
+ setPrivateField(mojo, "project", project);
try {
mojo.deploy(context, null);
fail("Expected MojoExecutionException");
@@ -152,11 +214,11 @@ public class RunMojoTest extends EasyMockSupport {
}
@Test
- public void testDeployWithExistingArtifactFailsInInstall() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
+ public void testDeployWithExistingArtifactFailsInInstall() throws SecurityException, IllegalArgumentException, IllegalAccessException {
BundleContext context = mock(BundleContext.class);
Artifact artifact = mock(Artifact.class);
File artifactFile = niceMock(File.class);
- expect(artifactFile.exists()).andReturn(true);
+ expect(artifactFile.exists()).andReturn(true).times(2);
replay(artifactFile);
expect(artifact.getFile()).andReturn(artifactFile);
replay(artifact);
@@ -164,7 +226,7 @@ public class RunMojoTest extends EasyMockSupport {
MavenProject project = new MavenProject();
project.setPackaging("bundle");
project.setArtifact(artifact);
- setInheritedPrivateField(mojo, "project", project);
+ setPrivateField(mojo, "project", project);
try {
mojo.deploy(context, null);
fail("Expected MojoExecutionException");
@@ -174,7 +236,7 @@ public class RunMojoTest extends EasyMockSupport {
}
@Test
- public void testDeployWithExistingArtifact() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, IOException, BundleException, MojoExecutionException {
+ public void testDeployWithExistingArtifact() throws SecurityException, IllegalArgumentException, IllegalAccessException, IOException, BundleException, MojoExecutionException {
BundleContext context = niceMock(BundleContext.class);
Bundle bundle = niceMock(Bundle.class);
expect(context.installBundle(anyString())).andReturn(bundle);
@@ -188,7 +250,7 @@ public class RunMojoTest extends EasyMockSupport {
MavenProject project = new MavenProject();
project.setPackaging("bundle");
project.setArtifact(artifact);
- setInheritedPrivateField(mojo, "project", project);
+ setPrivateField(mojo, "project", project);
replay(bundle);
mojo.deploy(context, null);
verify(bundle);
@@ -198,7 +260,7 @@ public class RunMojoTest extends EasyMockSupport {
}
@Test
- public void testDeployWithPomArtifactAndAttachedFeatureXmlNoFeatureService() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, IOException, BundleException, MojoExecutionException {
+ public void testDeployWithPomArtifactAndAttachedFeatureXmlNoFeatureService() throws SecurityException, IllegalArgumentException, IllegalAccessException, IOException, BundleException, MojoExecutionException {
File artifactFeaturesAttachmentFile = File.createTempFile("someproject-features", ".xml");
try {
BundleContext context = niceMock(BundleContext.class);
@@ -218,7 +280,7 @@ public class RunMojoTest extends EasyMockSupport {
project.setPackaging("pom");
project.setArtifact(artifact);
project.addAttachedArtifact(artifactFeaturesAttachment);
- setInheritedPrivateField(mojo, "project", project);
+ setPrivateField(mojo, "project", project);
replay(bundle);
try {
mojo.deploy(context, null);
@@ -258,7 +320,7 @@ public class RunMojoTest extends EasyMockSupport {
project.setPackaging("pom");
project.setArtifact(artifact);
project.addAttachedArtifact(artifactFeaturesAttachment);
- setInheritedPrivateField(mojo, "project", project);
+ setPrivateField(mojo, "project", project);
try {
mojo.deploy(context, featureService);
fail("Expected MojoExecutionException");
@@ -295,7 +357,7 @@ public class RunMojoTest extends EasyMockSupport {
project.setPackaging("pom");
project.setArtifact(artifact);
project.addAttachedArtifact(artifactFeaturesAttachment);
- setInheritedPrivateField(mojo, "project", project);
+ setPrivateField(mojo, "project", project);
mojo.deploy(context, featureService);
verify(featureService);
} finally {
@@ -328,7 +390,7 @@ public class RunMojoTest extends EasyMockSupport {
project.setPackaging("pom");
project.setArtifact(artifact);
project.addAttachedArtifact(artifactFeaturesAttachment);
- setInheritedPrivateField(mojo, "project", project);
+ setPrivateField(mojo, "project", project);
setPrivateField(mojo, "featuresToInstall", "liquibase-core, ukelonn-db-derby-test, ukelonn");
String[] featureRepos = { "mvn:org.ops4j.pax.jdbc/pax-jdbc-features/LATEST/xml/features" };
setPrivateField(mojo, "featureRepositories", featureRepos);
@@ -369,7 +431,7 @@ public class RunMojoTest extends EasyMockSupport {
}
@Test
- public void testAddFeaturesNullFeatureService() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
+ public void testAddFeaturesNullFeatureService() throws SecurityException, IllegalArgumentException, IllegalAccessException {
RunMojo mojo = new RunMojo();
setPrivateField(mojo, "featuresToInstall", "liquibase-core, ukelonn-db-derby-test, ukelonn");
@@ -419,16 +481,49 @@ public class RunMojoTest extends EasyMockSupport {
assertNotNull(service);
}
- private void setPrivateField(Object obj, String fieldName, Object value) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
- Field field = obj.getClass().getDeclaredField(fieldName);
- field.setAccessible(true);
- field.set(obj, value);
+ private RunMojo newRunMojo(final Function<String[], Main> mainFactory)
+ throws IllegalAccessException, IOException {
+ final Path base = temporaryFolder.getRoot().toPath();
+ Stream.of("config.properties", "jre.properties").forEach(etc -> {
+ final Path configProperties = base.resolve("etc").resolve(etc);
+ try {
+ Files.createDirectories(configProperties.getParent());
+ Files.copy(
+ Paths.get("../../main/src/test/resources/test-karaf-home/etc").resolve(etc),
+ configProperties);
+ } catch (final IOException e) {
+ fail(e.getMessage());
+ }
+ });
+ Files.createDirectories(base.resolve("system"));
+ final RunMojo mojo = new RunMojo() {
+ @Override
+ protected Main newMain(final ClassLoader bootLoader, final String[] args) {
+ if (mainFactory == null) {
+ return super.newMain(bootLoader, args);
+ }
+ return mainFactory.apply(args);
+ }
+ };
+ setPrivateField(mojo, "karafDirectory", temporaryFolder.getRoot());
+ return mojo;
}
- private void setInheritedPrivateField(Object obj, String fieldName, Object value) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
- Field field = obj.getClass().getSuperclass().getDeclaredField(fieldName);
- field.setAccessible(true);
- field.set(obj, value);
+ private void setPrivateField(Object obj, String fieldName, Object value) throws SecurityException, IllegalArgumentException, IllegalAccessException {
+ Class<?> aClass = obj.getClass();
+ while (aClass != null) {
+ try {
+ Field field = aClass.getDeclaredField(fieldName);
+ field.setAccessible(true);
+ field.set(obj, value);
+ return;
+ } catch (final NoSuchFieldException nsfe) {
+ aClass = aClass.getSuperclass();
+ }
+ }
+ fail("cant set " + fieldName);
}
+ private static class FastExit extends RuntimeException {
+ }
}