This commit is contained in:
Guillaume Nodet
2022-11-22 14:05:27 +01:00
parent 4690bcb7f4
commit a14a1eb80f
174 changed files with 5995 additions and 5221 deletions

View File

@@ -1,3 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright 2019 the original author or authors.
@@ -15,159 +16,156 @@
limitations under the License.
-->
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache.maven.daemon</groupId>
<artifactId>mvnd</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache.maven.daemon</groupId>
<artifactId>mvnd</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>mvnd-client</artifactId>
<artifactId>mvnd-client</artifactId>
<packaging>jar</packaging>
<name>Maven Daemon - Client</name>
<packaging>jar</packaging>
<name>Maven Daemon - Client</name>
<properties>
<maven.compiler.target>11</maven.compiler.target>
<maven.compiler.source>11</maven.compiler.source>
</properties>
<properties>
<maven.compiler.target>11</maven.compiler.target>
<maven.compiler.source>11</maven.compiler.source>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.maven.daemon</groupId>
<artifactId>mvnd-common</artifactId>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-embedder</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
</dependency>
<dependency>
<groupId>org.graalvm.nativeimage</groupId>
<artifactId>svm</artifactId>
<scope>provided</scope>
</dependency>
<dependencies>
<dependency>
<groupId>org.apache.maven.daemon</groupId>
<artifactId>mvnd-common</artifactId>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-embedder</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
</dependency>
<dependency>
<groupId>org.graalvm.nativeimage</groupId>
<artifactId>svm</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>${basedir}/src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<build>
<resources>
<resource>
<filtering>true</filtering>
<directory>${basedir}/src/main/resources</directory>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<executions>
<execution>
<id>enforce-bytecode-version</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<enforceBytecodeVersion>
<excludes>
<exclude>org.graalvm.nativeimage:svm</exclude>
</excludes>
</enforceBytecodeVersion>
</rules>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>buildnumber-maven-plugin</artifactId>
<configuration>
<locale>en_US</locale>
</configuration>
<executions>
<execution>
<goals>
<goal>create</goal>
</goals>
<phase>validate</phase>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<compilerArgs>
<arg>--add-exports=java.base/sun.nio.ch=ALL-UNNAMED</arg>
<arg>--add-exports=java.base/jdk.internal.module=ALL-UNNAMED</arg>
</compilerArgs>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<systemPropertyVariables>
<project.basedir>${project.basedir}</project.basedir>
</systemPropertyVariables>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>native</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<executions>
<execution>
<id>enforce-bytecode-version</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<enforceBytecodeVersion>
<excludes>
<exclude>org.graalvm.nativeimage:svm</exclude>
</excludes>
</enforceBytecodeVersion>
</rules>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>buildnumber-maven-plugin</artifactId>
<configuration>
<locale>en_US</locale>
</configuration>
<executions>
<execution>
<phase>validate</phase>
<goals>
<goal>create</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<compilerArgs>
<arg>--add-exports=java.base/sun.nio.ch=ALL-UNNAMED</arg>
<arg>--add-exports=java.base/jdk.internal.module=ALL-UNNAMED</arg>
</compilerArgs>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<systemPropertyVariables>
<project.basedir>${project.basedir}</project.basedir>
</systemPropertyVariables>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>native</id>
<build>
<plugins>
<plugin>
<groupId>org.graalvm.buildtools</groupId>
<artifactId>native-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>build</goal>
</goals>
<phase>package</phase>
</execution>
</executions>
<configuration>
<skip>false</skip>
<mainClass>org.mvndaemon.mvnd.client.DefaultClient</mainClass>
<imageName>mvnd</imageName>
<buildArgs>
--no-server
<plugin>
<groupId>org.graalvm.buildtools</groupId>
<artifactId>native-maven-plugin</artifactId>
<configuration>
<skip>false</skip>
<mainClass>org.mvndaemon.mvnd.client.DefaultClient</mainClass>
<imageName>mvnd</imageName>
<buildArgs>--no-server
--no-fallback
--allow-incomplete-classpath
-H:IncludeResources=org/mvndaemon/mvnd/.*
-H:IncludeResources=mvnd-bash-completion.bash
-H:-ParseRuntimeOptions
-H:+AddAllCharsets
-ea
</buildArgs>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
-ea</buildArgs>
</configuration>
<executions>
<execution>
<goals>
<goal>build</goal>
</goals>
<phase>package</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
</project>

View File

@@ -1,17 +1,20 @@
/*
* Copyright 2018 the original author or authors.
* 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
*
* 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
*
* 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.
* 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.mvndaemon.mvnd.client;

View File

@@ -1,17 +1,20 @@
/*
* Copyright 2019 the original author or authors.
* 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
*
* 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
*
* 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.
* 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.mvndaemon.mvnd.client;
@@ -26,5 +29,4 @@ public interface Client {
default ExecutionResult execute(ClientOutput output, String... args) throws InterruptedException {
return execute(output, Arrays.asList(args));
}
}

View File

@@ -1,17 +1,20 @@
/*
* Copyright 2019 the original author or authors.
* 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
*
* 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
*
* 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.
* 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.mvndaemon.mvnd.client;
@@ -37,5 +40,4 @@ public class Completion {
throw new UncheckedIOException("Could not read " + bashCompletionPath, e);
}
}
}

View File

@@ -1,17 +1,20 @@
/*
* Copyright 2019 the original author or authors.
* 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
*
* 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
*
* 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.
* 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.mvndaemon.mvnd.client;
@@ -41,7 +44,7 @@ import org.slf4j.LoggerFactory;
*/
public class DaemonClientConnection implements Closeable {
private final static Logger LOG = LoggerFactory.getLogger(DaemonClientConnection.class);
private static final Logger LOG = LoggerFactory.getLogger(DaemonClientConnection.class);
private final DaemonConnection connection;
private final DaemonInfo daemon;
@@ -56,8 +59,12 @@ public class DaemonClientConnection implements Closeable {
private final long maxKeepAliveMs;
private final DaemonParameters parameters;
public DaemonClientConnection(DaemonConnection connection, DaemonInfo daemon,
StaleAddressDetector staleAddressDetector, boolean newDaemon, DaemonParameters parameters) {
public DaemonClientConnection(
DaemonConnection connection,
DaemonInfo daemon,
StaleAddressDetector staleAddressDetector,
boolean newDaemon,
DaemonParameters parameters) {
this.connection = connection;
this.daemon = daemon;
this.staleAddressDetector = staleAddressDetector;
@@ -126,7 +133,8 @@ public class DaemonClientConnection implements Closeable {
if (!hasReceived && newDaemon) {
throw new ConnectException("Could not receive a message from the daemon.\n" + diag.describe(), e);
} else if (staleAddressDetector.maybeStaleAddress(e)) {
throw new StaleAddressException("Could not receive a message from the daemon.\n" + diag.describe(), e);
throw new StaleAddressException(
"Could not receive a message from the daemon.\n" + diag.describe(), e);
}
} finally {
hasReceived = true;
@@ -171,5 +179,4 @@ public class DaemonClientConnection implements Closeable {
*/
boolean maybeStaleAddress(Exception failure);
}
}

View File

@@ -1,20 +1,26 @@
/*
* Copyright 2011-2021 the original author or authors.
* 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
*
* 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
*
* 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.
* 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.mvndaemon.mvnd.client;
import static java.lang.Thread.sleep;
import static org.mvndaemon.mvnd.common.DaemonState.Canceled;
import java.io.File;
import java.io.IOException;
import java.net.SocketAddress;
@@ -53,9 +59,6 @@ import org.mvndaemon.mvnd.common.logging.ClientOutput;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static java.lang.Thread.sleep;
import static org.mvndaemon.mvnd.common.DaemonState.Canceled;
/**
* File origin:
* https://github.com/gradle/gradle/blob/v5.6.2/subprojects/launcher/src/main/java/org/gradle/launcher/daemon/client/DefaultDaemonConnector.java
@@ -94,11 +97,11 @@ public class DaemonConnector {
return connectNoDaemon();
}
final DaemonCompatibilitySpec constraint = new DaemonCompatibilitySpec(
parameters.javaHome(), parameters.getDaemonOpts());
final DaemonCompatibilitySpec constraint =
new DaemonCompatibilitySpec(parameters.javaHome(), parameters.getDaemonOpts());
output.accept(Message.buildStatus("Looking up daemon..."));
Map<Boolean, List<DaemonInfo>> idleBusy = registry.getAll().stream()
.collect(Collectors.groupingBy(di -> di.getState() == DaemonState.Idle));
Map<Boolean, List<DaemonInfo>> idleBusy =
registry.getAll().stream().collect(Collectors.groupingBy(di -> di.getState() == DaemonState.Idle));
final Collection<DaemonInfo> idleDaemons = idleBusy.getOrDefault(true, Collections.emptyList());
final Collection<DaemonInfo> busyDaemons = idleBusy.getOrDefault(false, Collections.emptyList());
@@ -128,20 +131,27 @@ public class DaemonConnector {
}
String daemon = ProcessHandle.current().pid() + "-" + System.currentTimeMillis();
Properties properties = new Properties();
properties.put(Environment.JAVA_HOME.getProperty(), parameters.javaHome().toString());
properties.put(
Environment.JAVA_HOME.getProperty(), parameters.javaHome().toString());
properties.put(Environment.USER_DIR.getProperty(), parameters.userDir().toString());
properties.put(Environment.USER_HOME.getProperty(), parameters.userHome().toString());
properties.put(Environment.MVND_HOME.getProperty(), parameters.mvndHome().toString());
properties.put(
Environment.USER_HOME.getProperty(), parameters.userHome().toString());
properties.put(
Environment.MVND_HOME.getProperty(), parameters.mvndHome().toString());
properties.put(Environment.MVND_ID.getProperty(), daemon);
properties.put(Environment.MVND_DAEMON_STORAGE.getProperty(), parameters.daemonStorage().toString());
properties.put(Environment.MVND_REGISTRY.getProperty(), parameters.registry().toString());
properties.put(
Environment.MVND_DAEMON_STORAGE.getProperty(),
parameters.daemonStorage().toString());
properties.put(
Environment.MVND_REGISTRY.getProperty(), parameters.registry().toString());
properties.putAll(parameters.getDaemonOptsMap());
Environment.setProperties(properties);
AtomicReference<Throwable> throwable = new AtomicReference<>();
Thread serverThread = new Thread(() -> {
try {
Class<?> clazz = getClass().getClassLoader().loadClass("org.mvndaemon.mvnd.daemon.Server");
try (AutoCloseable server = (AutoCloseable) clazz.getConstructor().newInstance()) {
try (AutoCloseable server =
(AutoCloseable) clazz.getConstructor().newInstance()) {
((Runnable) server).run();
}
} catch (Throwable t) {
@@ -164,34 +174,37 @@ public class DaemonConnector {
throw new RuntimeException("Unable to connect to internal daemon", throwable.get());
}
private String handleStopEvents(String daemonId, Collection<DaemonInfo> idleDaemons, Collection<DaemonInfo> busyDaemons) {
private String handleStopEvents(
String daemonId, Collection<DaemonInfo> idleDaemons, Collection<DaemonInfo> busyDaemons) {
final List<DaemonStopEvent> stopEvents = registry.getStopEvents();
// Clean up old stop events
long time = System.currentTimeMillis() - TimeUnit.HOURS.toMillis(1);
List<DaemonStopEvent> oldStopEvents = stopEvents.stream()
.filter(e -> e.getTimestamp() < time)
.collect(Collectors.toList());
List<DaemonStopEvent> oldStopEvents =
stopEvents.stream().filter(e -> e.getTimestamp() < time).collect(Collectors.toList());
registry.removeStopEvents(oldStopEvents);
final List<DaemonStopEvent> recentStopEvents = stopEvents.stream()
.filter(e -> e.getTimestamp() >= time)
.collect(Collectors.groupingBy(DaemonStopEvent::getDaemonId,
Collectors.minBy(this::compare)))
.collect(Collectors.groupingBy(DaemonStopEvent::getDaemonId, Collectors.minBy(this::compare)))
.values()
.stream()
.map(Optional::get)
.collect(Collectors.toList());
for (DaemonStopEvent stopEvent : recentStopEvents) {
LOGGER.debug("Previous Daemon ({}) stopped at {} {}",
stopEvent.getDaemonId(), stopEvent.getTimestamp(), stopEvent.getReason());
LOGGER.debug(
"Previous Daemon ({}) stopped at {} {}",
stopEvent.getDaemonId(),
stopEvent.getTimestamp(),
stopEvent.getReason());
}
return generate(daemonId, busyDaemons.size(), idleDaemons.size(), recentStopEvents.size());
}
public static String generate(final String daemonId, final int numBusy, final int numIncompatible, final int numStopped) {
public static String generate(
final String daemonId, final int numBusy, final int numIncompatible, final int numStopped) {
final int totalUnavailableDaemons = numBusy + numIncompatible + numStopped;
if (totalUnavailableDaemons > 0) {
final List<String> reasons = new ArrayList<>();
@@ -223,21 +236,23 @@ public class DaemonConnector {
return 0;
}
private DaemonClientConnection connectToIdleDaemon(Collection<DaemonInfo> idleDaemons, DaemonCompatibilitySpec constraint) {
private DaemonClientConnection connectToIdleDaemon(
Collection<DaemonInfo> idleDaemons, DaemonCompatibilitySpec constraint) {
final List<DaemonInfo> compatibleIdleDaemons = getCompatibleDaemons(idleDaemons, constraint);
LOGGER.debug("Found {} idle daemons, {} compatibles", idleDaemons.size(), compatibleIdleDaemons.size());
return findConnection(compatibleIdleDaemons);
}
private DaemonClientConnection connectToCanceledDaemon(Collection<DaemonInfo> busyDaemons,
DaemonCompatibilitySpec constraint) {
private DaemonClientConnection connectToCanceledDaemon(
Collection<DaemonInfo> busyDaemons, DaemonCompatibilitySpec constraint) {
DaemonClientConnection connection = null;
List<DaemonInfo> canceledBusy = busyDaemons.stream()
.filter(di -> di.getState() == Canceled)
.collect(Collectors.toList());
final List<DaemonInfo> compatibleCanceledDaemons = getCompatibleDaemons(
canceledBusy, constraint);
LOGGER.debug("Found {} busy daemons, {} cancelled, {} compatibles", busyDaemons.size(), canceledBusy.size(),
List<DaemonInfo> canceledBusy =
busyDaemons.stream().filter(di -> di.getState() == Canceled).collect(Collectors.toList());
final List<DaemonInfo> compatibleCanceledDaemons = getCompatibleDaemons(canceledBusy, constraint);
LOGGER.debug(
"Found {} busy daemons, {} cancelled, {} compatibles",
busyDaemons.size(),
canceledBusy.size(),
compatibleCanceledDaemons.size());
if (!compatibleCanceledDaemons.isEmpty()) {
LOGGER.debug("Waiting for daemons with canceled builds to become available");
@@ -261,8 +276,10 @@ public class DaemonConnector {
if (result.isCompatible()) {
compatibleDaemons.add(daemon);
} else {
LOGGER.debug("{} daemon {} does not match the desired criteria: "
+ result.getWhy(), daemon.getState(), daemon.getId());
LOGGER.debug(
"{} daemon {} does not match the desired criteria: " + result.getWhy(),
daemon.getState(),
daemon.getId());
}
}
return compatibleDaemons;
@@ -295,7 +312,8 @@ public class DaemonConnector {
}
} while (process.isAlive() && System.currentTimeMillis() - start < DEFAULT_CONNECT_TIMEOUT);
DaemonDiagnostics diag = new DaemonDiagnostics(daemonId, parameters);
throw new DaemonException.ConnectException("Timeout waiting to connect to the Maven daemon.\n" + diag.describe());
throw new DaemonException.ConnectException(
"Timeout waiting to connect to the Maven daemon.\n" + diag.describe());
}
static String newId() {
@@ -364,24 +382,33 @@ public class DaemonConnector {
args.add("-Dmaven.home=" + mvndHome.resolve("mvn"));
args.add("-Dmaven.conf=" + mvndHome.resolve("mvn/conf"));
Environment.MVND_JAVA_HOME.addCommandLineOption(args, parameters.javaHome().toString());
Environment.LOGBACK_CONFIGURATION_FILE
.addCommandLineOption(args, parameters.logbackConfigurationPath().toString());
Environment.MVND_JAVA_HOME.addCommandLineOption(
args, parameters.javaHome().toString());
Environment.LOGBACK_CONFIGURATION_FILE.addCommandLineOption(
args, parameters.logbackConfigurationPath().toString());
Environment.MVND_ID.addCommandLineOption(args, daemonId);
Environment.MVND_DAEMON_STORAGE.addCommandLineOption(args, parameters.daemonStorage().toString());
Environment.MVND_REGISTRY.addCommandLineOption(args, parameters.registry().toString());
Environment.MVND_SOCKET_FAMILY.addCommandLineOption(args,
parameters.socketFamily().orElseGet(
() -> getJavaVersion() >= 16.0f ? SocketFamily.unix : SocketFamily.inet)
Environment.MVND_DAEMON_STORAGE.addCommandLineOption(
args, parameters.daemonStorage().toString());
Environment.MVND_REGISTRY.addCommandLineOption(
args, parameters.registry().toString());
Environment.MVND_SOCKET_FAMILY.addCommandLineOption(
args,
parameters
.socketFamily()
.orElseGet(() -> getJavaVersion() >= 16.0f ? SocketFamily.unix : SocketFamily.inet)
.toString());
parameters.discriminatingCommandLineOptions(args);
args.add(MavenDaemon.class.getName());
command = String.join(" ", args);
LOGGER.debug("Starting daemon process: id = {}, workingDir = {}, daemonArgs: {}", daemonId, workingDir, command);
ProcessBuilder.Redirect redirect = ProcessBuilder.Redirect.appendTo(parameters.daemonOutLog(daemonId).toFile());
LOGGER.debug(
"Starting daemon process: id = {}, workingDir = {}, daemonArgs: {}", daemonId, workingDir, command);
ProcessBuilder.Redirect redirect = ProcessBuilder.Redirect.appendTo(
parameters.daemonOutLog(daemonId).toFile());
ProcessBuilder processBuilder = new ProcessBuilder();
processBuilder.environment().put(Environment.JDK_JAVA_OPTIONS.getEnvironmentVariable(), parameters.jdkJavaOpts());
processBuilder
.environment()
.put(Environment.JDK_JAVA_OPTIONS.getEnvironmentVariable(), parameters.jdkJavaOpts());
Process process = processBuilder
.directory(workingDir.toFile())
.command(args)
@@ -391,7 +418,8 @@ public class DaemonConnector {
return process;
} catch (Exception e) {
throw new DaemonException.StartException(
String.format("Error starting daemon: id = %s, workingDir = %s, daemonArgs: %s",
String.format(
"Error starting daemon: id = %s, workingDir = %s, daemonArgs: %s",
daemonId, workingDir, command),
e);
}
@@ -432,14 +460,15 @@ public class DaemonConnector {
return connectToDaemon(daemonInfo, new CleanupOnStaleAddress(daemonInfo), newDaemon);
} catch (DaemonException.ConnectException e) {
DaemonDiagnostics diag = new DaemonDiagnostics(daemon, parameters);
throw new DaemonException.ConnectException("Could not connect to the Maven daemon.\n" + diag.describe(), e);
throw new DaemonException.ConnectException(
"Could not connect to the Maven daemon.\n" + diag.describe(), e);
}
}
return null;
}
private DaemonClientConnection connectToDaemon(DaemonInfo daemon,
DaemonClientConnection.StaleAddressDetector staleAddressDetector, boolean newDaemon)
private DaemonClientConnection connectToDaemon(
DaemonInfo daemon, DaemonClientConnection.StaleAddressDetector staleAddressDetector, boolean newDaemon)
throws DaemonException.ConnectException {
LOGGER.debug("Connecting to Daemon");
try {
@@ -462,10 +491,11 @@ public class DaemonConnector {
@Override
public boolean maybeStaleAddress(Exception failure) {
LOGGER.debug("Removing daemon from the registry due to communication failure. Daemon information: {}", daemon);
LOGGER.debug(
"Removing daemon from the registry due to communication failure. Daemon information: {}", daemon);
final long timestamp = System.currentTimeMillis();
final DaemonStopEvent stopEvent = new DaemonStopEvent(daemon.getId(), timestamp, null,
"by user or operating system");
final DaemonStopEvent stopEvent =
new DaemonStopEvent(daemon.getId(), timestamp, null, "by user or operating system");
registry.storeStopEvent(stopEvent);
registry.remove(daemon.getId());
return true;
@@ -500,7 +530,8 @@ public class DaemonConnector {
// socket.connect(address, CONNECT_TIMEOUT);
// if (socket.getLocalSocketAddress().equals(socket.getRemoteSocketAddress())) {
// socketChannel.close();
// throw new DaemonException.ConnectException(String.format("Socket connected to itself on %s.", address));
// throw new DaemonException.ConnectException(String.format("Socket connected to itself on
// %s.", address));
// }
LOGGER.debug("Connected to address {}.", socketChannel.getRemoteAddress());
@@ -517,5 +548,4 @@ public class DaemonConnector {
throw new DaemonException.ConnectException(String.format("Could not connect to server %s.", address), e);
}
}
}

View File

@@ -1,17 +1,20 @@
/*
* Copyright 2009 the original author or authors.
* 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
*
* 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
*
* 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.
* 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.mvndaemon.mvnd.client;
@@ -32,7 +35,7 @@ import java.util.stream.Collector;
*/
public class DaemonDiagnostics {
private final static int TAIL_SIZE = 200;
private static final int TAIL_SIZE = 200;
private final String id;
private final DaemonParameters parameters;
@@ -44,10 +47,7 @@ public class DaemonDiagnostics {
@Override
public String toString() {
return "{"
+ "id=" + id
+ ", parameters=" + parameters
+ '}';
return "{" + "id=" + id + ", parameters=" + parameters + '}';
}
public String describe() {
@@ -62,14 +62,21 @@ public class DaemonDiagnostics {
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)
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: ")
sb.append(" unable to read from the daemon ")
.append(name)
.append(": ")
.append(log)
.append(", because of: ")
.append(e);
}
}
@@ -86,16 +93,18 @@ public class DaemonDiagnostics {
}
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);
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

@@ -1,17 +1,20 @@
/*
* Copyright 2019 the original author or authors.
* 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
*
* 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
*
* 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.
* 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.mvndaemon.mvnd.client;
@@ -63,8 +66,8 @@ public class DaemonParameters {
private static final String ENV_PREFIX = "env.";
protected final Map<Path, Properties> mvndProperties = new ConcurrentHashMap<>();
protected final Function<Path, Properties> provider = path -> mvndProperties.computeIfAbsent(path,
p -> loadProperties(path));
protected final Function<Path, Properties> provider =
path -> mvndProperties.computeIfAbsent(path, p -> loadProperties(path));
private final Map<String, String> properties;
public DaemonParameters() {
@@ -83,9 +86,7 @@ public class DaemonParameters {
public Map<String, String> getDaemonOptsMap() {
return discriminatingValues()
.collect(Collectors.toMap(
envValue -> envValue.envKey.getProperty(),
EnvValue::asString));
.collect(Collectors.toMap(envValue -> envValue.envKey.getProperty(), EnvValue::asString));
}
Stream<EnvValue> discriminatingValues() {
@@ -96,8 +97,7 @@ public class DaemonParameters {
}
public void discriminatingCommandLineOptions(List<String> args) {
discriminatingValues()
.forEach(envValue -> envValue.envKey.addCommandLineOption(args, envValue.asString()));
discriminatingValues().forEach(envValue -> envValue.envKey.addCommandLineOption(args, envValue.asString()));
}
public Path mvndHome() {
@@ -112,7 +112,8 @@ public class DaemonParameters {
.orEnvironmentVariable()
.orFail()
.asPath()
.toAbsolutePath().normalize();
.toAbsolutePath()
.normalize();
}
private String mvndHomeFromExecutable() {
@@ -120,8 +121,8 @@ public class DaemonParameters {
if (Environment.isNative() && cmd.isPresent()) {
final Path mvndH = Paths.get(cmd.get()).getParent().getParent();
if (mvndH != null) {
final Path mvndDaemonLib = mvndH
.resolve("mvn/lib/ext/mvnd-daemon-" + BuildProperties.getInstance().getVersion() + ".jar");
final Path mvndDaemonLib = mvndH.resolve("mvn/lib/ext/mvnd-daemon-"
+ BuildProperties.getInstance().getVersion() + ".jar");
if (Files.exists(mvndDaemonLib)) {
return mvndH.toString();
}
@@ -138,9 +139,7 @@ public class DaemonParameters {
.orLocalProperty(provider, globalPropertiesPath())
.orSystemProperty()
.orEnvironmentVariable()
.or(new ValueSource(
description -> description.append("java command"),
this::javaHomeFromPath))
.or(new ValueSource(description -> description.append("java command"), this::javaHomeFromPath))
.orFail()
.asPath();
try {
@@ -159,19 +158,11 @@ public class DaemonParameters {
}
public Path userDir() {
return value(Environment.USER_DIR)
.orSystemProperty()
.orFail()
.asPath()
.toAbsolutePath();
return value(Environment.USER_DIR).orSystemProperty().orFail().asPath().toAbsolutePath();
}
public Path userHome() {
return value(Environment.USER_HOME)
.orSystemProperty()
.orFail()
.asPath()
.toAbsolutePath();
return value(Environment.USER_HOME).orSystemProperty().orFail().asPath().toAbsolutePath();
}
public Path suppliedPropertiesPath() {
@@ -207,8 +198,10 @@ public class DaemonParameters {
.orSystemProperty()
.orLocalProperty(provider, globalPropertiesPath())
.orEnvironmentVariable()
.orDefault(
() -> userHome().resolve(".m2/mvnd/registry/" + BuildProperties.getInstance().getVersion()).toString())
.orDefault(() -> userHome()
.resolve(".m2/mvnd/registry/"
+ BuildProperties.getInstance().getVersion())
.toString())
.asPath();
}
@@ -233,7 +226,8 @@ public class DaemonParameters {
.orSystemProperty()
.orDefault(() -> findDefaultMultimoduleProjectDirectory(projectDir))
.asPath()
.toAbsolutePath().normalize();
.toAbsolutePath()
.normalize();
}
public Path logbackConfigurationPath() {
@@ -317,10 +311,7 @@ public class DaemonParameters {
* @return if mvnd should behave as maven
*/
public boolean serial() {
return value(Environment.SERIAL)
.orSystemProperty()
.orDefault()
.asBoolean();
return value(Environment.SERIAL).orSystemProperty().orDefault().asBoolean();
}
/**
@@ -333,14 +324,14 @@ public class DaemonParameters {
public DaemonParameters withJdkJavaOpts(String opts, boolean before) {
String org = this.properties.getOrDefault(Environment.JDK_JAVA_OPTIONS.getProperty(), "");
return derive(b -> b.put(Environment.JDK_JAVA_OPTIONS,
org.isEmpty() ? opts : before ? opts + " " + org : org + " " + opts));
return derive(b -> b.put(
Environment.JDK_JAVA_OPTIONS, org.isEmpty() ? opts : before ? opts + " " + org : org + " " + opts));
}
public DaemonParameters withJvmArgs(String opts, boolean before) {
String org = this.properties.getOrDefault(Environment.MVND_JVM_ARGS.getProperty(), "");
return derive(b -> b.put(Environment.MVND_JVM_ARGS,
org.isEmpty() ? opts : before ? opts + " " + org : org + " " + opts));
return derive(b ->
b.put(Environment.MVND_JVM_ARGS, org.isEmpty() ? opts : before ? opts + " " + org : org + " " + opts));
}
protected DaemonParameters derive(Consumer<PropertiesBuilder> customizer) {
@@ -400,9 +391,11 @@ public class DaemonParameters {
}
protected EnvValue value(Environment env) {
return new EnvValue(env, new ValueSource(
description -> description.append("value: ").append(env.getProperty()),
() -> properties.get(env.getProperty())));
return new EnvValue(
env,
new ValueSource(
description -> description.append("value: ").append(env.getProperty()),
() -> properties.get(env.getProperty())));
}
public static EnvValue systemProperty(Environment env) {
@@ -519,7 +512,6 @@ public class DaemonParameters {
public String toString() {
return descriptionFunction.apply(new StringBuilder()).toString();
}
}
/**
@@ -548,7 +540,8 @@ public class DaemonParameters {
private static ValueSource systemPropertySource(Environment env) {
String property = env.getProperty();
if (property == null) {
throw new IllegalStateException("Cannot use " + Environment.class.getName() + " for getting a system property");
throw new IllegalStateException(
"Cannot use " + Environment.class.getName() + " for getting a system property");
}
return new ValueSource(
description -> description.append("system property ").append(property),
@@ -558,9 +551,8 @@ public class DaemonParameters {
private static ValueSource environmentVariableSource(Environment env) {
String envVar = env.getEnvironmentVariable();
if (envVar == null) {
throw new IllegalStateException(
"Cannot use " + Environment.class.getName() + "." + env.name()
+ " for getting an environment variable");
throw new IllegalStateException("Cannot use " + Environment.class.getName() + "." + env.name()
+ " for getting an environment variable");
}
return new ValueSource(
description -> description.append("environment variable ").append(envVar),
@@ -573,10 +565,16 @@ public class DaemonParameters {
public EnvValue orLocalProperty(Function<Path, Properties> provider, Path localPropertiesPath) {
if (localPropertiesPath != null) {
return new EnvValue(this, envKey, new ValueSource(
description -> description.append("property ").append(envKey.getProperty()).append(" in ")
.append(localPropertiesPath),
() -> provider.apply(localPropertiesPath).getProperty(envKey.getProperty())));
return new EnvValue(
this,
envKey,
new ValueSource(
description -> description
.append("property ")
.append(envKey.getProperty())
.append(" in ")
.append(localPropertiesPath),
() -> provider.apply(localPropertiesPath).getProperty(envKey.getProperty())));
} else {
return this;
}
@@ -595,7 +593,9 @@ public class DaemonParameters {
}
public EnvValue orDefault(Supplier<String> defaultSupplier) {
return new EnvValue(this, envKey,
return new EnvValue(
this,
envKey,
new ValueSource(sb -> sb.append("default: ").append(defaultSupplier.get()), defaultSupplier));
}
@@ -609,7 +609,9 @@ public class DaemonParameters {
EnvValue val = this;
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: ");
.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
@@ -640,9 +642,7 @@ public class DaemonParameters {
.append(envKey.name())
.append("] from ");
valueSource.descriptionFunction.apply(sb);
sb.append(": [")
.append(result)
.append(']');
sb.append(": [").append(result).append(']');
LOG.trace(sb.toString());
}
return result;
@@ -690,6 +690,5 @@ public class DaemonParameters {
throw couldNotgetValue();
}
}
}
}

View File

@@ -1,20 +1,25 @@
/*
* Copyright 2019 the original author or authors.
* 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
*
* 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
*
* 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.
* 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.mvndaemon.mvnd.client;
import static org.mvndaemon.mvnd.client.DaemonParameters.LOG_EXTENSION;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.file.Files;
@@ -56,8 +61,6 @@ import org.mvndaemon.mvnd.common.logging.TerminalOutput;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static org.mvndaemon.mvnd.client.DaemonParameters.LOG_EXTENSION;
public class DefaultClient implements Client {
private static final Logger LOGGER = LoggerFactory.getLogger(DefaultClient.class);
@@ -88,7 +91,8 @@ public class DefaultClient implements Client {
|| Environment.COMPLETION.hasCommandLineOption(args);
// Color
Color styleColor = Color.of(Environment.MAVEN_COLOR.removeCommandLineOption(args)).orElse(Color.auto);
Color styleColor =
Color.of(Environment.MAVEN_COLOR.removeCommandLineOption(args)).orElse(Color.auto);
if (styleColor == Color.auto) {
/* Translate from auto to either always or never */
/* stdout is not a terminal e.g. when stdout is redirected to a file */
@@ -114,7 +118,8 @@ public class DefaultClient implements Client {
System.setProperty(Environment.MVND_NO_BUFERING.getProperty(), Boolean.toString(true));
}
System.setProperty(Environment.MVND_HOME.getProperty(), parameters.mvndHome().toString());
System.setProperty(
Environment.MVND_HOME.getProperty(), parameters.mvndHome().toString());
Path dir;
if (Environment.MAVEN_FILE.hasCommandLineOption(args)) {
@@ -126,7 +131,8 @@ public class DefaultClient implements Client {
} else {
dir = parameters.userDir();
}
System.setProperty(Environment.MAVEN_MULTIMODULE_PROJECT_DIRECTORY.getProperty(),
System.setProperty(
Environment.MAVEN_MULTIMODULE_PROJECT_DIRECTORY.getProperty(),
parameters.multiModuleProjectDirectory(dir).toString());
// .mvn/jvm.config
@@ -158,7 +164,8 @@ public class DefaultClient implements Client {
boolean defineIsEmpty = false;
while (iterator.hasNext()) {
final String arg = iterator.next();
String val = Environment.MAVEN_DEFINE.removeCommandLineOption(new ArrayList<>(Collections.singletonList(arg)));
String val =
Environment.MAVEN_DEFINE.removeCommandLineOption(new ArrayList<>(Collections.singletonList(arg)));
/* not -D or --define and pre define is empty */
if (val == null && defineIsEmpty) {
defineIsEmpty = false;
@@ -187,8 +194,7 @@ public class DefaultClient implements Client {
private static boolean maybeDefineCommandLineOption(String arg) {
// if arg maybe MAVEN_DEFINE value
return EnumSet.allOf(Environment.class)
.stream()
return EnumSet.allOf(Environment.class).stream()
.filter(e -> e != Environment.MAVEN_DEFINE)
.noneMatch(e -> e.hasCommandLineOption(Collections.singletonList(arg)));
}
@@ -245,15 +251,19 @@ public class DefaultClient implements Client {
try (DaemonRegistry registry = new DaemonRegistry(parameters.registry())) {
if (Environment.STATUS.removeCommandLineOption(args) != null) {
final String template = "%8s %7s %24s %7s %5s %23s %s";
output.accept(Message.out(String.format(template,
"ID", "PID", "Address", "Status", "RSS", "Last activity", "Java home")));
output.accept(Message.out(String.format(
template, "ID", "PID", "Address", "Status", "RSS", "Last activity", "Java home")));
for (DaemonInfo d : registry.getAll()) {
if (ProcessHandle.of(d.getPid()).isEmpty()) {
/* The process does not exist anymore - remove it from the registry */
registry.remove(d.getId());
} else {
output.accept(Message.out(String.format(template,
d.getId(), d.getPid(), d.getAddress(), d.getState(),
output.accept(Message.out(String.format(
template,
d.getId(),
d.getPid(),
d.getAddress(),
d.getState(),
OsUtils.kbTohumanReadable(OsUtils.findProcessRssInKb(d.getPid())),
LocalDateTime.ofInstant(
Instant.ofEpochMilli(Math.max(d.getLastIdle(), d.getLastBusy())),
@@ -318,14 +328,16 @@ public class DefaultClient implements Client {
parameters.multiModuleProjectDirectory().toString(),
System.getenv()));
output.accept(Message
.buildStatus("Connected to daemon " + daemon.getDaemon().getId() + ", scanning for projects..."));
output.accept(Message.buildStatus(
"Connected to daemon " + daemon.getDaemon().getId() + ", scanning for projects..."));
// We've sent the request, so it gives us a bit of time to purge the logs
AtomicReference<String> purgeMessage = new AtomicReference<>();
Thread purgeLog = new Thread(() -> {
purgeMessage.set(purgeLogs());
}, "Log purge");
Thread purgeLog = new Thread(
() -> {
purgeMessage.set(purgeLogs());
},
"Log purge");
purgeLog.setDaemon(true);
purgeLog.start();
@@ -335,16 +347,18 @@ public class DefaultClient implements Client {
output.accept(messages);
for (Message m : messages) {
switch (m.getType()) {
case Message.CANCEL_BUILD:
return new DefaultResult(argv,
new InterruptedException("The build was canceled"), 130);
case Message.BUILD_EXCEPTION:
final BuildException e = (BuildException) m;
return new DefaultResult(argv,
new Exception(e.getClassName() + ": " + e.getMessage() + "\n" + e.getStackTrace()),
1);
case Message.BUILD_FINISHED:
return new DefaultResult(argv, null, ((BuildFinished) m).getExitCode());
case Message.CANCEL_BUILD:
return new DefaultResult(
argv, new InterruptedException("The build was canceled"), 130);
case Message.BUILD_EXCEPTION:
final BuildException e = (BuildException) m;
return new DefaultResult(
argv,
new Exception(e.getClassName() + ": " + e.getMessage() + "\n"
+ e.getStackTrace()),
1);
case Message.BUILD_FINISHED:
return new DefaultResult(argv, null, ((BuildFinished) m).getExitCode());
}
}
}
@@ -364,13 +378,16 @@ public class DefaultClient implements Client {
if (!Files.isDirectory(storage) || !TimeUtils.isPositive(purgeLogPeriod)) {
return null;
}
String date = DateTimeFormatter.ofPattern("yyyy-MM-dd").withZone(ZoneId.systemDefault()).format(Instant.now());
String date = DateTimeFormatter.ofPattern("yyyy-MM-dd")
.withZone(ZoneId.systemDefault())
.format(Instant.now());
Path log = storage.resolve("purge-" + date + ".log");
List<Path> deleted = new ArrayList<>();
List<Throwable> exceptions = new ArrayList<>();
FileTime limit = FileTime.from(Instant.now().minus(purgeLogPeriod));
try (Stream<Path> storagePath = Files.list(storage)) {
storagePath.filter(p -> p.getFileName().toString().endsWith(LOG_EXTENSION))
storagePath
.filter(p -> p.getFileName().toString().endsWith(LOG_EXTENSION))
.filter(p -> !log.equals(p))
.filter(p -> {
try {
@@ -396,8 +413,8 @@ public class DefaultClient implements Client {
return null;
}
String logMessage;
try (PrintWriter w = new PrintWriter(Files.newBufferedWriter(log,
StandardOpenOption.WRITE, StandardOpenOption.APPEND, StandardOpenOption.CREATE))) {
try (PrintWriter w = new PrintWriter(Files.newBufferedWriter(
log, StandardOpenOption.WRITE, StandardOpenOption.APPEND, StandardOpenOption.CREATE))) {
w.printf("Purge executed at %s%n", Instant.now().toString());
if (deleted.isEmpty()) {
w.printf("No files deleted.%n");
@@ -423,7 +440,8 @@ public class DefaultClient implements Client {
if (exceptions.isEmpty()) {
return String.format("Purged %d log files (%s)", deleted.size(), logMessage);
} else {
return String.format("Purged %d log files with %d exceptions (%s)", deleted.size(), exceptions.size(), logMessage);
return String.format(
"Purged %d log files with %d exceptions (%s)", deleted.size(), exceptions.size(), logMessage);
}
}
@@ -447,13 +465,17 @@ public class DefaultClient implements Client {
@Override
public ExecutionResult assertSuccess() {
if (exception != null) {
throw new AssertionError(ExecutionResult.appendCommand(new StringBuilder("Build failed: "), args).toString(),
throw new AssertionError(
ExecutionResult.appendCommand(new StringBuilder("Build failed: "), args)
.toString(),
exception);
}
if (exitCode != 0) {
throw new AssertionError(
ExecutionResult.appendCommand(
new StringBuilder("Build exited with non-zero exit code " + exitCode + ": "), args).toString(),
new StringBuilder("Build exited with non-zero exit code " + exitCode + ": "),
args)
.toString(),
exception);
}
return this;
@@ -462,7 +484,8 @@ public class DefaultClient implements Client {
@Override
public ExecutionResult assertFailure() {
if (exception == null && exitCode == 0) {
throw new AssertionError(ExecutionResult.appendCommand(new StringBuilder("Build did not fail: "), args));
throw new AssertionError(
ExecutionResult.appendCommand(new StringBuilder("Build did not fail: "), args));
}
return this;
}
@@ -476,7 +499,5 @@ public class DefaultClient implements Client {
public boolean isSuccess() {
return exception == null;
}
}
}

View File

@@ -1,17 +1,20 @@
/*
* Copyright 2019 the original author or authors.
* 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
*
* 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
*
* 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.
* 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.mvndaemon.mvnd.client;
@@ -37,5 +40,4 @@ public interface ExecutionResult {
}
return sb;
}
}

View File

@@ -1,17 +1,20 @@
/*
* Copyright 2019 the original author or authors.
* 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
*
* 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
*
* 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.
* 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.mvndaemon.mvnd.client.svm;

View File

@@ -1,17 +1,20 @@
/*
* Copyright 2019 the original author or authors.
* 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
*
* 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
*
* 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.
* 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.mvndaemon.mvnd.client.svm;
@@ -28,5 +31,4 @@ final class StaticMDCBinderSubstitution {
private static MDCAdapter bwCompatibleGetMDCAdapterFromBinder() throws NoClassDefFoundError {
return StaticMDCBinder.SINGLETON.getMDCA();
}
}

View File

@@ -1,17 +1,20 @@
/*
* Copyright 2019 the original author or authors.
* 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
*
* 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
*
* 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.
* 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.mvndaemon.mvnd.client;
@@ -34,8 +37,8 @@ public class CompletionGeneratorTest {
@Test
void generate() throws IOException {
String template = IoUtils.readResource(Completion.class.getClassLoader(),
"completion-templates/mvnd-bash-completion.bash");
String template = IoUtils.readResource(
Completion.class.getClassLoader(), "completion-templates/mvnd-bash-completion.bash");
final String shortOpts = Stream.of(Environment.values())
.filter(env -> !env.isInternal())
@@ -71,7 +74,5 @@ public class CompletionGeneratorTest {
final byte[] bytes = template.getBytes(StandardCharsets.UTF_8);
Files.write(baseDir.resolve("../dist/src/main/distro/bin/mvnd-bash-completion.bash"), bytes);
}
}

View File

@@ -1,25 +1,28 @@
/*
* Copyright 2019 the original author or authors.
* 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
*
* 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
*
* 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.
* 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.mvndaemon.mvnd.client;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import org.junit.jupiter.api.Test;
public class DaemonConnectorTest {
@Test

View File

@@ -1,20 +1,25 @@
/*
* Copyright 2019 the original author or authors.
* 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
*
* 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
*
* 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.
* 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.mvndaemon.mvnd.client;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
@@ -28,8 +33,6 @@ import org.mvndaemon.mvnd.client.DaemonParameters.EnvValue;
import org.mvndaemon.mvnd.client.DaemonParameters.ValueSource;
import org.mvndaemon.mvnd.common.Environment;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class EnvironmentTest {
@Test
@@ -57,7 +60,9 @@ public class EnvironmentTest {
void prop() {
try (EnvironmentResource env = new EnvironmentResource()) {
env.props("mvnd.home", "/maven/home/prop");
assertEquals("/maven/home/prop", DaemonParameters.systemProperty(Environment.MVND_HOME).asString());
assertEquals(
"/maven/home/prop",
DaemonParameters.systemProperty(Environment.MVND_HOME).asString());
}
}
@@ -65,7 +70,9 @@ public class EnvironmentTest {
void env() {
try (EnvironmentResource env = new EnvironmentResource()) {
env.env("MVND_HOME", "/maven/home/env");
assertEquals("/maven/home/env", DaemonParameters.environmentVariable(Environment.MVND_HOME).asString());
assertEquals(
"/maven/home/env",
DaemonParameters.environmentVariable(Environment.MVND_HOME).asString());
}
}
@@ -74,9 +81,9 @@ public class EnvironmentTest {
try (EnvironmentResource env = new EnvironmentResource()) {
final Properties localProps = new Properties();
localProps.put("mvnd.home", "/maven/home/local");
assertEquals(Paths.get("/maven/home/local"),
DaemonParameters
.environmentVariable(Environment.MVND_HOME)
assertEquals(
Paths.get("/maven/home/local"),
DaemonParameters.environmentVariable(Environment.MVND_HOME)
.orSystemProperty()
.orLocalProperty(path -> localProps, Paths.get("/local/properties"))
.orFail()
@@ -89,9 +96,9 @@ public class EnvironmentTest {
try (EnvironmentResource env = new EnvironmentResource()) {
env.props("mvnd.home", "/maven/home/prop");
env.env("MVND_HOME", "/maven/home/env");
assertEquals("/maven/home/env",
DaemonParameters
.environmentVariable(Environment.MVND_HOME)
assertEquals(
"/maven/home/env",
DaemonParameters.environmentVariable(Environment.MVND_HOME)
.orSystemProperty()
.asString());
}
@@ -101,9 +108,9 @@ public class EnvironmentTest {
void fail() {
try (EnvironmentResource env = new EnvironmentResource()) {
try {
assertEquals("/maven/home/env",
DaemonParameters
.environmentVariable(Environment.MVND_HOME)
assertEquals(
"/maven/home/env",
DaemonParameters.environmentVariable(Environment.MVND_HOME)
.orSystemProperty()
.orFail()
.asString());
@@ -124,7 +131,8 @@ public class EnvironmentTest {
@Test
void emptyBooleanEnvValueIsTrue() {
final String EMPTY_STRING = "";
final EnvValue envVal = new EnvValue(Environment.MVND_NO_BUFERING,
final EnvValue envVal = new EnvValue(
Environment.MVND_NO_BUFERING,
new ValueSource(sb -> sb.append("envValueAsBoolean"), () -> EMPTY_STRING));
assertEquals(true, envVal.asBoolean());
}
@@ -158,7 +166,5 @@ public class EnvironmentTest {
DaemonParameters.EnvValue.env = System.getenv();
Environment.setProperties(System.getProperties());
}
}
}

View File

@@ -1,17 +1,20 @@
/*
* Copyright 2019 the original author or authors.
* 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
*
* 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
*
* 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.
* 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.mvndaemon.mvnd.client;