Refactor usage of properties in the client / daemon, fixes #188

This commit is contained in:
Guillaume Nodet
2020-11-05 15:02:24 +01:00
committed by Peter Palaga
parent 759ca73c2d
commit 4030f8b5a4
31 changed files with 932 additions and 941 deletions

View File

@@ -1,101 +0,0 @@
/*
* Copyright 2009 the original author or authors.
*
* Licensed 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.jboss.fuse.mvnd.common;
import java.io.BufferedReader;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.List;
import java.util.stream.Collector;
/**
* File origin:
* https://github.com/gradle/gradle/blob/v5.6.2/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/diagnostics/DaemonDiagnostics.java
*/
public class DaemonDiagnostics {
private final static int TAIL_SIZE = 20;
private final String uid;
private final Layout layout;
public DaemonDiagnostics(String uid, Layout layout) {
this.uid = uid;
this.layout = layout;
}
@Override
public String toString() {
return "{"
+ "uid=" + uid
+ ", layout=" + layout
+ '}';
}
public String describe() {
StringBuilder sb = new StringBuilder();
sb.append("Daemon uid: ").append(uid).append("\n");
tail(sb, "log file", layout.daemonLog(uid));
tail(sb, "output", layout.daemonOutLog(uid));
return sb.toString();
}
static void tail(StringBuilder sb, String name, Path log) {
try {
String tail = tail(log);
sb.append(" ").append(name).append(": ").append(log).append("\n");
sb.append("----- Last " + TAIL_SIZE + " lines from daemon ").append(name).append(" - ").append(log)
.append(" -----\n");
sb.append(tail);
sb.append("----- End of the daemon ").append(name).append(" -----\n");
} catch (NoSuchFileException e) {
sb.append(" no ").append(name).append(" at: ").append(log).append("\n");
} catch (IOException e) {
sb.append(" unable to read from the daemon ").append(name).append(": ").append(log).append(", because of: ")
.append(e);
}
}
/**
* @param path to read from tail
* @return tail content
* @throws IOException when reading failed
*/
static String tail(Path path) throws IOException {
try (BufferedReader r = Files.newBufferedReader(path)) {
return String.join("\n", r.lines().collect(lastN(TAIL_SIZE))) + "\n";
}
}
static <T> Collector<T, ?, List<T>> lastN(int n) {
return Collector.<T, Deque<T>, List<T>> of(ArrayDeque::new, (acc, t) -> {
if (acc.size() == n)
acc.pollFirst();
acc.add(t);
}, (acc1, acc2) -> {
while (acc2.size() < n && !acc1.isEmpty()) {
acc2.addFirst(acc1.pollLast());
}
return acc2;
}, ArrayList::new);
}
}

View File

@@ -28,10 +28,9 @@ public class DaemonInfo {
private final String uid;
private final String javaHome;
private final String mavenHome;
private final String mvndHome;
private final int pid;
private final int address;
private final int idleTimeout;
private final String locale;
private final List<String> options;
private final DaemonState state;
@@ -39,15 +38,14 @@ public class DaemonInfo {
private final long lastBusy;
public DaemonInfo(String uid, String javaHome, String mavenHome,
int pid, int address, int idleTimeout,
int pid, int address,
String locale, List<String> options,
DaemonState state, long lastIdle, long lastBusy) {
this.uid = uid;
this.javaHome = javaHome;
this.mavenHome = mavenHome;
this.mvndHome = mavenHome;
this.pid = pid;
this.address = address;
this.idleTimeout = idleTimeout;
this.locale = locale;
this.options = options;
this.state = state;
@@ -63,8 +61,8 @@ public class DaemonInfo {
return javaHome;
}
public String getMavenHome() {
return mavenHome;
public String getMvndHome() {
return mvndHome;
}
public int getPid() {
@@ -75,10 +73,6 @@ public class DaemonInfo {
return address;
}
public int getIdleTimeout() {
return idleTimeout;
}
public String getLocale() {
return locale;
}
@@ -111,8 +105,8 @@ public class DaemonInfo {
li = lastIdle;
lb = lastBusy;
}
return new DaemonInfo(uid, javaHome, mavenHome, pid, address,
idleTimeout, locale, options, state, li, lb);
return new DaemonInfo(uid, javaHome, mvndHome, pid, address,
locale, options, state, li, lb);
}
@Override
@@ -125,10 +119,9 @@ public class DaemonInfo {
public StringBuilder appendNonKeyFields(StringBuilder sb) {
return sb.append("javaHome=").append(javaHome)
.append(", options=").append(options)
.append(", mavenHome=").append(mavenHome)
.append(", mavenHome=").append(mvndHome)
.append(", pid=").append(pid)
.append(", address=").append(address)
.append(", idleTimeout=").append(idleTimeout)
.append(", locale=").append(locale)
.append(", state=").append(state)
.append(", lastIdle=").append(lastIdle)

View File

@@ -242,7 +242,6 @@ public class DaemonRegistry implements AutoCloseable {
String mavenHome = readString();
int pid = buffer.getInt();
int address = buffer.getInt();
int idle = buffer.getInt();
String locale = readString();
List<String> opts = new ArrayList<>();
int nbOpts = buffer.getInt();
@@ -252,7 +251,7 @@ public class DaemonRegistry implements AutoCloseable {
DaemonState state = DaemonState.values()[buffer.get()];
long lastIdle = buffer.getLong();
long lastBusy = buffer.getLong();
DaemonInfo di = new DaemonInfo(uid, javaHome, mavenHome, pid, address, idle, locale, opts, state,
DaemonInfo di = new DaemonInfo(uid, javaHome, mavenHome, pid, address, locale, opts, state,
lastIdle, lastBusy);
infosMap.putIfAbsent(di.getUid(), di);
}
@@ -276,10 +275,9 @@ public class DaemonRegistry implements AutoCloseable {
for (DaemonInfo di : infosMap.values()) {
writeString(di.getUid());
writeString(di.getJavaHome());
writeString(di.getMavenHome());
writeString(di.getMvndHome());
buffer.putInt(di.getPid());
buffer.putInt(di.getAddress());
buffer.putInt(di.getIdleTimeout());
writeString(di.getLocale());
buffer.putInt(di.getOptions().size());
for (String opt : di.getOptions()) {

View File

@@ -15,367 +15,208 @@
*/
package org.jboss.fuse.mvnd.common;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collection;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.Objects;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Collects system properties and environment variables used by mvnd client or server.
*/
public enum Environment {
LOGBACK_CONFIGURATION_FILE("logback.configurationFile", null),
JAVA_HOME("java.home", "JAVA_HOME"),
MVND_HOME("mvnd.home", "MVND_HOME"),
MAVEN_REPO_LOCAL("maven.repo.local", null),
MAVEN_MULTIMODULE_PROJECT_DIRECTORY("maven.multiModuleProjectDirectory", null),
MVND_PROPERTIES_PATH("mvnd.properties.path", "MVND_PROPERTIES_PATH"),
DAEMON_DEBUG("daemon.debug", null),
DAEMON_IDLE_TIMEOUT_MS("daemon.idleTimeoutMs", null),
DAEMON_KEEP_ALIVE_MS("daemon.keepAliveMs", null),
DAEMON_MAX_LOST_KEEP_ALIVE("daemon.maxLostKeepAlive", null),
LOGBACK_CONFIGURATION_FILE("logback.configurationFile", null, null, false),
JAVA_HOME("java.home", "JAVA_HOME", null, false),
MVND_HOME("mvnd.home", "MVND_HOME", null, false),
USER_HOME("user.home", null, null, false),
USER_DIR("user.dir", null, null, false),
MAVEN_REPO_LOCAL("maven.repo.local", null, null, false),
MAVEN_SETTINGS("maven.settings", null, null, false) {
@Override
public boolean hasCommandLineProperty(Collection<String> args) {
return args.stream().anyMatch(arg -> arg.startsWith("-s") || arg.startsWith("--settings"));
}
@Override
public String asCommandLineProperty(String value) {
return "--settings=" + value;
}
},
MAVEN_MULTIMODULE_PROJECT_DIRECTORY("maven.multiModuleProjectDirectory", null, null, false),
MVND_PROPERTIES_PATH("mvnd.properties.path", "MVND_PROPERTIES_PATH", null, false),
MVND_DAEMON_STORAGE("mvnd.daemon.storage", null, null, false),
/**
* The path to the daemon registry
*/
DAEMON_REGISTRY("daemon.registry", null, null, false),
DAEMON_DEBUG("daemon.debug", null, false, true),
DAEMON_IDLE_TIMEOUT_MS("daemon.idleTimeoutMs", null, TimeUnit.HOURS.toMillis(3), true),
DAEMON_KEEP_ALIVE_MS("daemon.keepAliveMs", null, TimeUnit.SECONDS.toMillis(1), true),
DAEMON_MAX_LOST_KEEP_ALIVE("daemon.maxLostKeepAlive", null, 3, false),
/**
* The minimum number of threads to use when constructing the default {@code -T} parameter for the daemon.
* This value is ignored if the user passes @{@code-T}, @{@code --threads} or {@code -Dmvnd.threads} on the command
* This value is ignored if the user passes @{@code -T}, @{@code --threads} or {@code -Dmvnd.threads} on the command
* line or if he sets {@code mvnd.threads} in {@code ~/.m2/mvnd.properties}.
*/
MVND_MIN_THREADS("mvnd.minThreads", null),
MVND_MIN_THREADS("mvnd.minThreads", null, 1, false),
/**
* The number of threads to pass to the daemon; same syntax as Maven's {@code -T}/{@code --threads} option. Ignored
* if the user passes @{@code-T}, @{@code --threads} or {@code -Dmvnd.threads} on the command
* if the user passes @{@code -T}, @{@code --threads} or {@code -Dmvnd.threads} on the command
* line.
*/
MVND_THREADS("mvnd.threads", null),
DAEMON_UID("daemon.uid", null),
MVND_THREADS("mvnd.threads", null, null, false) {
@Override
public boolean hasCommandLineProperty(Collection<String> args) {
return args.stream().anyMatch(arg -> arg.startsWith("-T") || arg.startsWith("--threads"));
}
@Override
public String asCommandLineProperty(String value) {
return "--threads=" + value;
}
},
/**
* The maven builder name to use. Ignored if the user passes
*
* @{@code -b} or @{@code --builder} on the command line
*/
MVND_BUILDER("mvnd.builder", null, "smart", false) {
@Override
public boolean hasCommandLineProperty(Collection<String> args) {
return args.stream().anyMatch(arg -> arg.startsWith("-b") || arg.startsWith("--builder"));
}
@Override
public String asCommandLineProperty(String value) {
return "--builder=" + value;
}
},
/**
* Internal system property set by the client when starting the daemon to identify its id
*/
DAEMON_UID("daemon.uid", null, null, false),
/**
* Internal option to specify the maven extension classpath
*/
DAEMON_EXT_CLASSPATH("daemon.ext.classpath", null),
DAEMON_EXT_CLASSPATH("daemon.ext.classpath", null, null, true),
/**
* Internal option to specify the list of maven extension to register
*/
DAEMON_CORE_EXTENSIONS("daemon.core.extensions", null),
DAEMON_CORE_EXTENSIONS("daemon.core.extensions", null, null, true),
/**
* JVM options for the daemon
*/
DAEMON_MIN_HEAP_SIZE("daemon.minHeapSize", null, "128M", true),
/**
* JVM options for the daemon
*/
DAEMON_MAX_HEAP_SIZE("daemon.maxHeapSize", null, "2G", true),
/**
* JVM options for the daemon
*/
DAEMON_ENABLE_ASSERTIONS("daemon.enableAssertions", null, false, true),
/**
* Interval to check if the daemon should expire
*/
EXPIRATION_CHECK_DELAY_MS("daemon.expirationCheckDelayMs", null),
DAEMON_EXPIRATION_CHECK_DELAY_MS("daemon.expirationCheckDelayMs", null, TimeUnit.SECONDS.toMillis(10), true),
/**
* Period after which idle daemons will shut down
*/
DAEMON_DUPLICATE_DAEMON_GRACE_PERIOD_MS("daemon.duplicateDaemonGracePeriodMs", null, TimeUnit.SECONDS.toMillis(10), true),
;
public static final int DEFAULT_IDLE_TIMEOUT = (int) TimeUnit.HOURS.toMillis(3);
public static final int DEFAULT_KEEP_ALIVE = (int) TimeUnit.SECONDS.toMillis(1);
public static final int DEFAULT_EXPIRATION_CHECK_DELAY = (int) TimeUnit.SECONDS.toMillis(10);
static Properties properties = System.getProperties();
public static final int DEFAULT_MAX_LOST_KEEP_ALIVE = 3;
public static final int DEFAULT_MIN_THREADS = 1;
private static final Consumer<String> LOG;
private static final boolean DEBUG_ENABLED;
public static final String DEBUG_ENVIRONMENT_PROP = "mvnd.environment.debug";
static {
Consumer<String> log = null;
boolean debugEnabled = false;
try {
Logger logger = LoggerFactory.getLogger(Environment.class);
log = logger::debug;
debugEnabled = logger.isDebugEnabled();
} catch (java.lang.NoClassDefFoundError e) {
if (e.getMessage().contains("org/slf4j/LoggerFactory")) {
/* This is when we are in the daemon's boot class path where slf4j is not available */
if (Boolean.getBoolean(DEBUG_ENVIRONMENT_PROP)) {
log = s -> System.out.println("mvnd.environment: " + s);
debugEnabled = true;
}
} else {
throw e;
}
}
LOG = log != null ? log : s -> {
};
DEBUG_ENABLED = debugEnabled;
public static void setProperties(Properties properties) {
Environment.properties = properties;
}
static Properties properties = System.getProperties();
static Map<String, String> env = System.getenv();
public static String getProperty(String property) {
return properties.getProperty(property);
}
private final String property;
private final String environmentVariable;
private final String def;
private final boolean discriminating;
Environment(String property, String environmentVariable) {
this.property = property;
Environment(String property, String environmentVariable, Object def, boolean discriminating) {
this.property = Objects.requireNonNull(property);
this.environmentVariable = environmentVariable;
this.def = def != null ? def.toString() : null;
this.discriminating = discriminating;
}
public Environment.EnvValue systemProperty() {
return new EnvValue(this, systemPropertySource());
public String getProperty() {
return property;
}
public Environment.EnvValue commandLineProperty(Supplier<Properties> commandLineProperties) {
return new EnvValue(this, new ValueSource(
description -> description.append("command line property ").append(property),
() -> commandLineProperties.get().getProperty(property)));
public String getEnvironmentVariable() {
return environmentVariable;
}
public Environment.EnvValue environmentVariable() {
return new EnvValue(this, environmentVariableSource());
public String getDef() {
return def;
}
public EnvValue fromValueSource(ValueSource valueSource) {
return new EnvValue(this, valueSource);
public boolean isDiscriminating() {
return discriminating;
}
public String asString() {
String val = getProperty(property);
if (val == null) {
throw new IllegalStateException("The system property " + property + " is missing");
}
return val;
}
public int asInt() {
return Integer.parseInt(asString());
}
public boolean asBoolean() {
return Boolean.parseBoolean(asString());
}
public Path asPath() {
String result = asString();
if (Os.current().isCygwin()) {
result = cygpath(result);
}
return Paths.get(result);
}
public String asCommandLineProperty(String value) {
return "-D" + property + "=" + value;
}
public String asDaemonOpt(String value) {
return property + "=" + value;
}
public boolean hasCommandLineProperty(Collection<String> args) {
final String prefix = "-D" + property + "=";
final String prefix = "-D" + getProperty() + "=";
return args.stream().anyMatch(s -> s.startsWith(prefix));
}
public static Path findJavaHome(Supplier<Properties> mvndProperties, Path mvndPropertiesPath) {
final Path result = JAVA_HOME
.environmentVariable()
.orLocalProperty(mvndProperties, mvndPropertiesPath)
.orSystemProperty()
.orFail()
.asPath();
try {
return result
.toRealPath();
} catch (IOException e) {
throw new RuntimeException("Could not get a real path from path " + result);
public static String cygpath(String result) {
String path = result.replace('/', '\\');
if (path.matches("\\\\cygdrive\\\\[a-z]\\\\.*")) {
String s = path.substring("\\cygdrive\\".length());
result = s.substring(0, 1).toUpperCase(Locale.ENGLISH) + ":" + s.substring(1);
}
}
public static Path findMvndPropertiesPath() {
return MVND_PROPERTIES_PATH
.environmentVariable()
.orSystemProperty()
.orDefault(() -> Paths.get(System.getProperty("user.home"), ".m2", "mvnd.properties").toString())
.asPath()
.toAbsolutePath().normalize();
}
public static EnvValue findBasicMavenHome() {
return MVND_HOME
.environmentVariable()
.orSystemProperty();
}
public static Path findMultiModuleProjectDirectory(Path pwd) {
return MAVEN_MULTIMODULE_PROJECT_DIRECTORY
.systemProperty()
.orDefault(() -> findDefaultMultimoduleProjectDirectory(pwd))
.asPath()
.toAbsolutePath().normalize();
}
public static String findDefaultMultimoduleProjectDirectory(Path pwd) {
Path dir = pwd;
do {
if (Files.isDirectory(dir.resolve(".mvn"))) {
return dir.toString();
}
dir = dir.getParent();
} while (dir != null);
/*
* Return pwd if .mvn directory was not found in the hierarchy.
* Maven does the same thing in mvn shell script's find_maven_basedir()
* and find_file_argument_basedir() routines
*/
return pwd.toString();
}
public static Path findLogbackConfigurationPath(Supplier<Properties> mvndProperties, Path mvndPropertiesPath,
Path mvndHome) {
return LOGBACK_CONFIGURATION_FILE
.systemProperty()
.orLocalProperty(mvndProperties, mvndPropertiesPath)
.orDefault(() -> mvndHome.resolve("mvn/conf/logging/logback.xml").toString())
.orFail()
.asPath();
return result;
}
public static boolean isNative() {
return "executable".equals(System.getProperty("org.graalvm.nativeimage.kind"));
}
private Environment.ValueSource systemPropertySource() {
if (property == null) {
throw new IllegalStateException("Cannot use " + Environment.class.getName() + " for getting a system property");
}
return new ValueSource(
description -> description.append("system property ").append(property),
() -> properties.getProperty(property));
}
private Environment.ValueSource environmentVariableSource() {
if (environmentVariable == null) {
throw new IllegalStateException(
"Cannot use " + Environment.class.getName() + "." + name() + " for getting an environment variable");
}
return new ValueSource(
description -> description.append("environment variable ").append(environmentVariable),
() -> env.get(environmentVariable));
}
/**
* A source of an environment value with a description capability.
*/
public static class ValueSource {
final Function<StringBuilder, StringBuilder> descriptionFunction;
final Supplier<String> valueSupplier;
public ValueSource(Function<StringBuilder, StringBuilder> descriptionFunction, Supplier<String> valueSupplier) {
this.descriptionFunction = descriptionFunction;
this.valueSupplier = valueSupplier;
}
/** Mostly for debugging */
@Override
public String toString() {
return descriptionFunction.apply(new StringBuilder()).toString();
}
}
/**
* A chained lazy environment value.
*/
public static class EnvValue {
private final Environment envKey;
private final Environment.ValueSource valueSource;
protected Environment.EnvValue previous;
public EnvValue(Environment envKey, Environment.ValueSource valueSource) {
this.previous = null;
this.envKey = envKey;
this.valueSource = valueSource;
}
public EnvValue(Environment.EnvValue previous, Environment envKey, Environment.ValueSource valueSource) {
this.previous = previous;
this.envKey = envKey;
this.valueSource = valueSource;
}
public Environment.EnvValue orSystemProperty() {
return new EnvValue(this, envKey, envKey.systemPropertySource());
}
public Environment.EnvValue orLocalProperty(Supplier<Properties> localProperties, Path localPropertiesPath) {
return new EnvValue(this, envKey, new ValueSource(
description -> description.append("property ").append(envKey.property).append(" in ")
.append(localPropertiesPath),
() -> localProperties.get().getProperty(envKey.property)));
}
public Environment.EnvValue orEnvironmentVariable() {
return new EnvValue(this, envKey, envKey.environmentVariableSource());
}
public EnvValue or(ValueSource source) {
return new EnvValue(this, envKey, source);
}
public Environment.EnvValue orDefault(Supplier<String> defaultSupplier) {
return new EnvValue(this, envKey,
new ValueSource(sb -> sb.append("default: ").append(defaultSupplier.get()), defaultSupplier));
}
public Environment.EnvValue orFail() {
return new EnvValue(this, envKey, new ValueSource(sb -> sb, () -> {
final StringBuilder sb = new StringBuilder("Could not get value for ")
.append(Environment.class.getSimpleName())
.append(".").append(envKey.name()).append(" from any of the following sources: ");
/*
* Compose the description functions to invert the order thus getting the resolution order in the
* message
*/
Function<StringBuilder, StringBuilder> description = (s -> s);
EnvValue val = this;
while (val != null) {
description = description.compose(val.valueSource.descriptionFunction);
val = val.previous;
if (val != null) {
description = description.compose(s -> s.append(", "));
}
}
description.apply(sb);
throw new IllegalStateException(sb.toString());
}));
}
String get() {
if (previous != null) {
final String result = previous.get();
if (result != null) {
return result;
}
}
final String result = valueSource.valueSupplier.get();
if (result != null && DEBUG_ENABLED) {
StringBuilder sb = new StringBuilder("Loaded environment value for key [")
.append(envKey.name())
.append("] from ");
valueSource.descriptionFunction.apply(sb);
sb.append(": [")
.append(result)
.append(']');
LOG.accept(sb.toString());
}
return result;
}
public String asString() {
return get();
}
public Optional<String> asOptional() {
return Optional.ofNullable(get());
}
public Path asPath() {
String result = get();
if (result != null && Os.current().isCygwin()) {
result = cygpath(result);
}
return result == null ? null : Paths.get(result);
}
static String cygpath(String result) {
String path = result.replace('/', '\\');
if (path.matches("\\\\cygdrive\\\\[a-z]\\\\.*")) {
String s = path.substring("\\cygdrive\\".length());
result = s.substring(0, 1).toUpperCase(Locale.ENGLISH) + ":" + s.substring(1);
}
return result;
}
public boolean asBoolean() {
return Boolean.parseBoolean(get());
}
public int asInt() {
return Integer.parseInt(get());
}
}
}

View File

@@ -1,120 +0,0 @@
/*
* Copyright 2019 the original author or authors.
*
* Licensed 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.jboss.fuse.mvnd.common;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Properties;
import java.util.function.Supplier;
public class Layout {
private static Layout ENV_INSTANCE;
protected final Path mavenHome;
protected final Path userDir;
protected final Path multiModuleProjectDirectory;
protected final Path mvndPropertiesPath;
public Layout(Path mvndPropertiesPath, Path mavenHome, Path userDir, Path multiModuleProjectDirectory) {
super();
this.mvndPropertiesPath = mvndPropertiesPath;
this.mavenHome = mavenHome;
this.userDir = userDir;
this.multiModuleProjectDirectory = multiModuleProjectDirectory;
}
public Path mavenHome() {
return mavenHome;
}
public Path userDir() {
return userDir;
}
public Path registry() {
return mavenHome.resolve("daemon/registry.bin");
}
public Path daemonLog(String daemon) {
return mavenHome.resolve("daemon/daemon-" + daemon + ".log");
}
public Path daemonOutLog(String daemon) {
return mavenHome.resolve("daemon/daemon-" + daemon + ".out.log");
}
public Path multiModuleProjectDirectory() {
return multiModuleProjectDirectory;
}
public Path getMvndPropertiesPath() {
return mvndPropertiesPath;
}
public static Layout getEnvInstance() {
if (ENV_INSTANCE == null) {
final Path mvndPropertiesPath = Environment.findMvndPropertiesPath();
final Supplier<Properties> mvndProperties = lazyMvndProperties(mvndPropertiesPath);
final Path pwd = Paths.get(".").toAbsolutePath().normalize();
ENV_INSTANCE = new Layout(
mvndPropertiesPath,
Environment.MVND_HOME
.systemProperty()
.orFail()
.asPath()
.toAbsolutePath().normalize(),
pwd,
Environment.findMultiModuleProjectDirectory(pwd));
}
return ENV_INSTANCE;
}
public static Supplier<Properties> lazyMvndProperties(Path mvndPropertiesPath) {
return new Supplier<Properties>() {
private volatile Properties properties;
@Override
public Properties get() {
Properties result = this.properties;
if (result == null) {
result = new Properties();
if (Files.exists(mvndPropertiesPath)) {
try (InputStream in = Files.newInputStream(mvndPropertiesPath)) {
result.load(in);
} catch (IOException e) {
throw new RuntimeException("Could not read " + mvndPropertiesPath);
}
}
this.properties = result;
}
return result;
}
};
}
@Override
public String toString() {
return "Layout [mavenHome=" + mavenHome + ", userDir=" + userDir + ", multiModuleProjectDirectory="
+ multiModuleProjectDirectory + "]";
}
}

View File

@@ -30,8 +30,7 @@ public class MavenDaemon {
// loaded from jars that are built by a previous run
new File("txt").toURI().toURL().openConnection().setDefaultUseCaches(false);
final String uidStr = Environment.DAEMON_UID.systemProperty().orFail().asString();
final Path mvndHome = Environment.MVND_HOME.systemProperty().orFail().asPath();
final Path mvndHome = Environment.MVND_HOME.asPath();
URL[] classpath = Stream.concat(
/* jars */
Stream.of("mvn/lib/ext", "mvn/lib", "mvn/boot")
@@ -73,7 +72,7 @@ public class MavenDaemon {
};
Thread.currentThread().setContextClassLoader(loader);
Class<?> clazz = loader.loadClass("org.jboss.fuse.mvnd.daemon.Server");
try (AutoCloseable server = (AutoCloseable) clazz.getConstructor(String.class).newInstance(uidStr)) {
try (AutoCloseable server = (AutoCloseable) clazz.getConstructor().newInstance()) {
((Runnable) server).run();
}
}

View File

@@ -42,7 +42,7 @@ public class DaemonRegistryTest {
byte[] token = new byte[16];
new Random().nextBytes(token);
reg1.store(new DaemonInfo("the-uid", "/java/home/",
"/data/reg/", 0x12345678, 7502, 65536,
"/data/reg/", 0x12345678, 7502,
Locale.getDefault().toLanguageTag(), Arrays.asList("-Xmx"),
DaemonState.Idle, System.currentTimeMillis(), System.currentTimeMillis()));

View File

@@ -1,127 +0,0 @@
/*
* Copyright 2019 the original author or authors.
*
* Licensed 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.jboss.fuse.mvnd.common;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
public class EnvironmentTest {
@Test
void prop() {
try (EnvironmentResource env = new EnvironmentResource()) {
env.props("mvnd.home", "/maven/home/prop");
Assertions.assertEquals("/maven/home/prop", Environment.MVND_HOME.systemProperty().asString());
}
}
@Test
void env() {
try (EnvironmentResource env = new EnvironmentResource()) {
env.env("MVND_HOME", "/maven/home/env");
Assertions.assertEquals("/maven/home/env", Environment.MVND_HOME.environmentVariable().asString());
}
}
@Test
void localProps() {
try (EnvironmentResource env = new EnvironmentResource()) {
final Properties localProps = new Properties();
localProps.put("mvnd.home", "/maven/home/local");
Assertions.assertEquals(Paths.get("/maven/home/local"),
Environment.MVND_HOME
.environmentVariable()
.orSystemProperty()
.orLocalProperty(() -> localProps, Paths.get("/local/properties"))
.orFail()
.asPath());
}
}
@Test
void envBeforeProp() {
try (EnvironmentResource env = new EnvironmentResource()) {
env.props("mvnd.home", "/maven/home/prop");
env.env("MVND_HOME", "/maven/home/env");
Assertions.assertEquals("/maven/home/env",
Environment.MVND_HOME
.environmentVariable()
.orSystemProperty()
.asString());
}
}
@Test
void fail() {
try (EnvironmentResource env = new EnvironmentResource()) {
try {
Assertions.assertEquals("/maven/home/env",
Environment.MVND_HOME
.environmentVariable()
.orSystemProperty()
.orFail()
.asString());
Assertions.fail("IllegalStateException expected");
} catch (IllegalStateException e) {
Assertions.assertEquals(
"Could not get value for Environment.MVND_HOME from any of the following sources: environment variable MVND_HOME, system property mvnd.home",
e.getMessage());
}
}
}
@Test
void cygwin() {
Assertions.assertEquals("C:\\jdk-11.0.2\\", Environment.EnvValue.cygpath("/cygdrive/c/jdk-11.0.2/"));
}
static class EnvironmentResource implements AutoCloseable {
private final Properties props = new Properties();
private final Map<String, String> env = new HashMap<>();
public EnvironmentResource() {
Environment.env = env;
Environment.properties = props;
}
public void props(String... props) {
int i = 0;
while (i < props.length) {
this.props.setProperty(props[i++], props[i++]);
}
}
public void env(String... env) {
int i = 0;
while (i < env.length) {
this.env.put(env[i++], env[i++]);
}
}
@Override
public void close() {
Environment.env = System.getenv();
Environment.properties = System.getProperties();
}
}
}