mirror of
https://github.com/apache/maven-mvnd.git
synced 2025-09-27 16:08:21 +00:00
Refactor usage of properties in the client / daemon, fixes #188
This commit is contained in:

committed by
Peter Palaga

parent
759ca73c2d
commit
4030f8b5a4
@@ -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);
|
||||
}
|
||||
|
||||
}
|
@@ -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)
|
||||
|
@@ -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()) {
|
||||
|
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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 + "]";
|
||||
}
|
||||
|
||||
}
|
@@ -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();
|
||||
}
|
||||
}
|
||||
|
@@ -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()));
|
||||
|
||||
|
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user