Allow unix domain sockets for client/daemon connection (not used by default)

This commit is contained in:
Guillaume Nodet
2021-07-21 22:06:35 +02:00
parent 4b75fec3e1
commit b67ab81c3d
19 changed files with 237 additions and 101 deletions

View File

@@ -16,9 +16,9 @@
package org.mvndaemon.mvnd.client;
import java.io.File;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.io.IOException;
import java.net.SocketAddress;
import java.net.StandardProtocolFamily;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.nio.file.Files;
@@ -32,6 +32,7 @@ import java.util.Map;
import java.util.Optional;
import java.util.Properties;
import java.util.Random;
import java.util.Scanner;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
@@ -49,6 +50,7 @@ import org.mvndaemon.mvnd.common.Environment;
import org.mvndaemon.mvnd.common.MavenDaemon;
import org.mvndaemon.mvnd.common.Message;
import org.mvndaemon.mvnd.common.Os;
import org.mvndaemon.mvnd.common.SocketHelper;
import org.mvndaemon.mvnd.common.logging.ClientOutput;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -371,6 +373,10 @@ public class DaemonConnector {
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 ? StandardProtocolFamily.UNIX : StandardProtocolFamily.INET)
.toString());
parameters.discriminatingCommandLineOptions(args);
args.add(MavenDaemon.class.getName());
command = String.join(" ", args);
@@ -394,6 +400,31 @@ public class DaemonConnector {
}
}
private float getJavaVersion() {
try {
final String java = Os.current().isUnixLike() ? "bin/java" : "bin\\java.exe";
Path javaExec = parameters.javaHome().resolve(java);
List<String> args = new ArrayList<>();
args.add(javaExec.toString());
args.add("-version");
Process process = new ProcessBuilder()
.directory(parameters.mvndHome().toFile())
.command(args)
.start();
process.waitFor();
Scanner sc = new Scanner(process.getErrorStream());
sc.next();
sc.next();
String version = sc.next();
LOGGER.warn("JAVA VERSION: " + version);
int is = version.charAt(0) == '"' ? 1 : 0;
int ie = version.indexOf('.', version.indexOf('.', is));
return Float.parseFloat(version.substring(is, ie));
} catch (Exception e) {
throw new IllegalStateException("Unable to detect java version", e);
}
}
private DaemonClientConnection connectToDaemonWithId(String daemon, boolean newDaemon)
throws DaemonException.ConnectException {
// Look for 'our' daemon among the busy daemons - a daemon will start in busy state so that nobody else will
@@ -444,18 +475,37 @@ public class DaemonConnector {
}
}
public DaemonConnection connect(int port, byte[] token) throws DaemonException.ConnectException {
InetSocketAddress address = new InetSocketAddress(InetAddress.getLoopbackAddress(), port);
public DaemonConnection connect(String str, byte[] token) throws DaemonException.ConnectException {
SocketAddress address = SocketHelper.socketAddressFromString(str);
StandardProtocolFamily family = SocketHelper.getSocketFamily(address);
try {
LOGGER.debug("Trying to connect to address {}.", address);
SocketChannel socketChannel = SocketChannel.open();
Socket socket = socketChannel.socket();
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));
SocketChannel socketChannel = SocketHelper.openSocket(family);
socketChannel.configureBlocking(false);
boolean connected = socketChannel.connect(address);
if (!connected) {
long t0 = System.nanoTime();
long t1 = t0 + TimeUnit.MICROSECONDS.toNanos(CONNECT_TIMEOUT);
while (!connected && t0 < t1) {
Thread.sleep(10);
connected = socketChannel.finishConnect();
if (!connected) {
t0 = System.nanoTime();
}
}
if (!connected) {
throw new IOException("Timeout");
}
}
LOGGER.debug("Connected to address {}.", socket.getRemoteSocketAddress());
socketChannel.configureBlocking(true);
// Socket socket = socketChannel.socket();
// 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));
// }
LOGGER.debug("Connected to address {}.", socketChannel.getRemoteAddress());
ByteBuffer tokenBuffer = ByteBuffer.wrap(token);
do {

View File

@@ -18,6 +18,7 @@ package org.mvndaemon.mvnd.client;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.StandardProtocolFamily;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
@@ -323,6 +324,10 @@ public class DaemonParameters {
return property(Environment.MVND_LOG_PURGE_PERIOD).orFail().asDuration();
}
public Optional<StandardProtocolFamily> socketFamily() {
return property(Environment.MVND_SOCKET_FAMILY).asOptional().map(StandardProtocolFamily::valueOf);
}
public static String findDefaultMultimoduleProjectDirectory(Path pwd) {
Path dir = pwd;
do {

View File

@@ -108,13 +108,47 @@
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<executions>
<execution>
<id>default</id>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<fork>true</fork>
<compilerArgs>
<arg>-XDignore.symbol.file</arg>
</compilerArgs>
</configuration>
</execution>
<execution>
<id>jdk16</id>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<fork>true</fork>
<compilerArgs>
<arg>-XDignore.symbol.file</arg>
</compilerArgs>
<release>16</release>
<multiReleaseOutput>true</multiReleaseOutput>
<compileSourceRoots>
<root>${project.basedir}/src/main/java16</root>
</compileSourceRoots>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<fork>true</fork>
<compilerArgs>
<arg>-XDignore.symbol.file</arg>
</compilerArgs>
<archive>
<manifestFile>src/main/resources/META-INF/MANIFEST.MF</manifestFile>
</archive>
</configuration>
</plugin>
</plugins>

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mvndaemon.mvnd.sync;
package org.mvndaemon.mvnd.common;
import java.io.IOException;
import java.nio.ByteBuffer;

View File

@@ -23,7 +23,7 @@ import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ClosedSelectorException;
import java.nio.channels.SelectionKey;
@@ -47,10 +47,10 @@ public class DaemonConnection implements AutoCloseable {
private final SocketChannel socket;
private final DataInputStream input;
private final DataOutputStream output;
private final InetSocketAddress localAddress;
private final InetSocketAddress remoteAddress;
private final SocketAddress localAddress;
private final SocketAddress remoteAddress;
public DaemonConnection(SocketChannel socket) {
public DaemonConnection(SocketChannel socket) throws IOException {
this.socket = socket;
try {
// NOTE: we use non-blocking IO as there is no reliable way when using blocking IO to shutdown reads while
@@ -61,8 +61,8 @@ public class DaemonConnection implements AutoCloseable {
} catch (IOException e) {
throw new DaemonException.InterruptedException(e);
}
localAddress = (InetSocketAddress) socket.socket().getLocalSocketAddress();
remoteAddress = (InetSocketAddress) socket.socket().getRemoteSocketAddress();
localAddress = socket.getLocalAddress();
remoteAddress = socket.getRemoteAddress();
}
@Override

View File

@@ -32,7 +32,7 @@ public class DaemonInfo {
private final String javaHome;
private final String mvndHome;
private final int pid;
private final int address;
private final String address;
private final byte[] token;
private final String locale;
private final List<String> options;
@@ -41,7 +41,7 @@ public class DaemonInfo {
private final long lastBusy;
public DaemonInfo(String id, String javaHome, String mavenHome,
int pid, int address, byte[] token,
int pid, String address, byte[] token,
String locale, List<String> options,
DaemonState state, long lastIdle, long lastBusy) {
this.id = id;
@@ -73,7 +73,7 @@ public class DaemonInfo {
return pid;
}
public int getAddress() {
public String getAddress() {
return address;
}

View File

@@ -185,7 +185,7 @@ public class DaemonRegistry implements AutoCloseable {
String javaHome = readString();
String mavenHome = readString();
int pid = buffer.getInt();
int address = buffer.getInt();
String address = readString();
byte[] token = new byte[DaemonInfo.TOKEN_SIZE];
buffer.get(token);
@@ -224,7 +224,7 @@ public class DaemonRegistry implements AutoCloseable {
writeString(di.getJavaHome());
writeString(di.getMvndHome());
buffer.putInt(di.getPid());
buffer.putInt(di.getAddress());
writeString(di.getAddress());
buffer.put(di.getToken());
writeString(di.getLocale());
buffer.putInt(di.getOptions().size());

View File

@@ -239,7 +239,11 @@ public enum Environment {
/**
* Log mojos execution time at the end of the build.
*/
MVND_BUILD_TIME("mvnd.buildTime", null, null, OptionType.BOOLEAN, Flags.NONE);
MVND_BUILD_TIME("mvnd.buildTime", null, null, OptionType.BOOLEAN, Flags.NONE),
/**
* Socket family to use
*/
MVND_SOCKET_FAMILY("mvnd.socketFamily", null, "INET", OptionType.STRING, Flags.DISCRIMINATING);
static Properties properties;

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mvndaemon.mvnd.sync;
package org.mvndaemon.mvnd.common;
public class JavaVersion {

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mvndaemon.mvnd.sync;
package org.mvndaemon.mvnd.common;
import java.io.IOException;
import java.net.Inet4Address;
@@ -25,14 +25,30 @@ import java.net.StandardProtocolFamily;
import java.net.UnknownHostException;
import java.nio.channels.ByteChannel;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Objects;
import static java.net.StandardProtocolFamily.INET;
import static java.net.StandardProtocolFamily.INET6;
import static java.util.Objects.requireNonNull;
public class SocketHelper {
public static StandardProtocolFamily getSocketFamily(SocketAddress address) {
if (address instanceof InetSocketAddress) {
InetSocketAddress isa = (InetSocketAddress) address;
InetAddress ia = isa.getAddress();
if (ia instanceof Inet6Address) {
return INET6;
} else {
return INET;
}
// } else if (address instanceof UnixDomainSocketAddress) {
// return UNIX;
} else {
throw new IllegalArgumentException("Unsupported socket address '" + address + "'");
}
}
public static void checkFamily(StandardProtocolFamily family, SocketAddress address) {
Objects.requireNonNull(family);
Objects.requireNonNull(address);
@@ -114,12 +130,28 @@ public class SocketHelper {
// } else if (address instanceof UnixDomainSocketAddress) {
// return "unix:" + address;
} else {
throw new IllegalArgumentException("Unsupported address: " + address);
throw new IllegalArgumentException("Unsupported socket address: '" + address + "'");
}
}
public static SocketChannel openSocket(StandardProtocolFamily family) throws IOException {
Objects.requireNonNull(family);
if (family == INET || family == INET6) {
return SocketChannel.open();
} else {
throw new IllegalArgumentException("Unsupported socket family: " + family);
}
// return SocketChannel.open(family);
}
public static ServerSocketChannel openServerSocket(StandardProtocolFamily family) throws IOException {
return ServerSocketChannel.open(/*family*/).bind(getLoopbackAddress(family), 0);
Objects.requireNonNull(family);
if (family == INET || family == INET6) {
return ServerSocketChannel.open().bind(getLoopbackAddress(family), 0);
} else {
throw new IllegalArgumentException("Unsupported socket family: " + family);
}
// return ServerSocketChannel.open(family).bind(getLoopbackAddress(family), 0);
}
private static SocketAddress getLoopbackAddress(StandardProtocolFamily family) {

View File

@@ -13,20 +13,20 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mvndaemon.mvnd.sync;
package org.mvndaemon.mvnd.common;
import java.io.IOException;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ProtocolFamily;
import java.net.SocketAddress;
import java.net.StandardProtocolFamily;
import java.net.UnixDomainSocketAddress;
import java.net.UnknownHostException;
import java.nio.channels.ByteChannel;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Objects;
import static java.net.StandardProtocolFamily.INET;
@@ -35,6 +35,22 @@ import static java.net.StandardProtocolFamily.UNIX;
public class SocketHelper {
public static StandardProtocolFamily getSocketFamily(SocketAddress address) {
if (address instanceof InetSocketAddress) {
InetSocketAddress isa = (InetSocketAddress) address;
InetAddress ia = isa.getAddress();
if (ia instanceof Inet6Address) {
return INET6;
} else {
return INET;
}
} else if (address instanceof UnixDomainSocketAddress) {
return UNIX;
} else {
throw new IllegalArgumentException("Unsupported socket address '" + address + "'");
}
}
public static void checkFamily(StandardProtocolFamily family, SocketAddress address) {
Objects.requireNonNull(family);
Objects.requireNonNull(address);
@@ -44,14 +60,16 @@ public class SocketHelper {
if (ia != null
&& !(ia instanceof Inet4Address && family == INET)
&& !(ia instanceof Inet6Address && family == INET6)) {
throw new IllegalArgumentException("Socket address '" + address + "' does not match required family '" + family + "'");
throw new IllegalArgumentException(
"Socket address '" + address + "' does not match required family '" + family + "'");
}
} else if (address instanceof UnixDomainSocketAddress) {
if (family != UNIX) {
if (family != StandardProtocolFamily.UNIX) {
throw new IllegalArgumentException("Socket address '" + address + "' does not match required family '" + family + "'");
}
} else {
throw new IllegalArgumentException("Socket address '" + address + "' does not match required family '" + family + "'");
throw new IllegalArgumentException(
"Socket address '" + address + "' does not match required family '" + family + "'");
}
}
@@ -114,12 +132,18 @@ public class SocketHelper {
} else if (address instanceof UnixDomainSocketAddress) {
return "unix:" + address;
} else {
throw new IllegalArgumentException("Unsupported address: " + address);
throw new IllegalArgumentException("Unsupported socket address: '" + address + "'");
}
}
public static SocketChannel openSocket(StandardProtocolFamily family) throws IOException {
Objects.requireNonNull(family);
return SocketChannel.open(family);
}
public static ServerSocketChannel openServerSocket(StandardProtocolFamily family) throws IOException {
return ServerSocketChannel.open(family).bind(getLoopbackAddress(family), 0);
Objects.requireNonNull(family);
return ServerSocketChannel.open(family).bind(getLoopbackAddress(family), 0);
}
private static SocketAddress getLoopbackAddress(StandardProtocolFamily family) {
@@ -129,9 +153,10 @@ public class SocketHelper {
case INET:
return new InetSocketAddress(Inet4Address.getByAddress(new byte[] { 127, 0, 0, 1 }), 0);
case INET6:
return new InetSocketAddress(Inet6Address.getByAddress(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }), 0);
case UNIX:
return null;
return new InetSocketAddress(
Inet6Address.getByAddress(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }), 0);
case UNIX:
return null;
default:
throw new IllegalArgumentException("Unsupported family: " + family);
}

View File

@@ -43,7 +43,7 @@ public class DaemonRegistryTest {
byte[] token = new byte[16];
new Random().nextBytes(token);
reg1.store(new DaemonInfo("12345678", "/java/home/",
"/data/reg/", 0x12345678, 7502, token,
"/data/reg/", 0x12345678, "inet:/127.0.0.1:7502", token,
Locale.getDefault().toLanguageTag(), Arrays.asList("-Xmx"),
DaemonState.Idle, System.currentTimeMillis(), System.currentTimeMillis()));
@@ -63,7 +63,7 @@ public class DaemonRegistryTest {
byte[] token = new byte[16];
new Random().nextBytes(token);
reg1.store(new DaemonInfo("12345678", "/java/home/",
"/data/reg/", 0x12345678, 7502, token,
"/data/reg/", 0x12345678, "inet:/127.0.0.1:7502", token,
Locale.getDefault().toLanguageTag(), Arrays.asList("-Xmx"),
DaemonState.Idle, System.currentTimeMillis(), System.currentTimeMillis()));
assertEquals(1, reg1.getAll().size());

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mvndaemon.mvnd.sync;
package org.mvndaemon.mvnd.common;
import java.net.InetAddress;
import java.net.InetSocketAddress;

View File

@@ -17,8 +17,7 @@ package org.mvndaemon.mvnd.daemon;
import java.io.IOException;
import java.lang.reflect.Field;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.StandardProtocolFamily;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
@@ -55,6 +54,7 @@ import org.mvndaemon.mvnd.common.Environment;
import org.mvndaemon.mvnd.common.Message;
import org.mvndaemon.mvnd.common.Message.BuildRequest;
import org.mvndaemon.mvnd.common.Os;
import org.mvndaemon.mvnd.common.SocketHelper;
import org.mvndaemon.mvnd.daemon.DaemonExpiration.DaemonExpirationResult;
import org.mvndaemon.mvnd.daemon.DaemonExpiration.DaemonExpirationStrategy;
import org.mvndaemon.mvnd.logging.smart.BuildEventListener;
@@ -111,10 +111,15 @@ public class Server implements AutoCloseable, Runnable {
this.noDaemon = Environment.MVND_NO_DAEMON.asBoolean();
this.keepAliveMs = Environment.MVND_KEEP_ALIVE.asDuration().toMillis();
StandardProtocolFamily socketFamily = Environment.MVND_SOCKET_FAMILY
.asOptional()
.map(StandardProtocolFamily::valueOf)
.orElse(StandardProtocolFamily.INET);
try {
cli = new DaemonMavenCli();
registry = new DaemonRegistry(Environment.MVND_REGISTRY.asPath());
socket = ServerSocketChannel.open().bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0));
socket = SocketHelper.openServerSocket(socketFamily);
executor = Executors.newScheduledThreadPool(1);
strategy = DaemonExpiration.master();
memoryStatus = new DaemonMemoryStatus(executor);
@@ -136,7 +141,7 @@ public class Server implements AutoCloseable, Runnable {
Environment.MVND_JAVA_HOME.asString(),
Environment.MVND_HOME.asString(),
DaemonRegistry.getProcessId(),
socket.socket().getLocalPort(),
SocketHelper.socketAddressToString(socket.getLocalAddress()),
token,
Locale.getDefault().toLanguageTag(),
opts,

View File

@@ -147,7 +147,7 @@ _mvnd()
local mvnd_opts="-1"
local mvnd_long_opts="--color|--completion|--purge|--serial|--status|--stop"
local mvnd_properties="-Djava.home|-Djdk.java.options|-Dmaven.multiModuleProjectDirectory|-Dmaven.repo.local|-Dmaven.settings|-Dmvnd.buildTime|-Dmvnd.builder|-Dmvnd.daemonStorage|-Dmvnd.debug|-Dmvnd.duplicateDaemonGracePeriod|-Dmvnd.enableAssertions|-Dmvnd.expirationCheckDelay|-Dmvnd.home|-Dmvnd.idleTimeout|-Dmvnd.jvmArgs|-Dmvnd.keepAlive|-Dmvnd.logPurgePeriod|-Dmvnd.logback|-Dmvnd.maxHeapSize|-Dmvnd.maxLostKeepAlive|-Dmvnd.minHeapSize|-Dmvnd.minThreads|-Dmvnd.noBuffering|-Dmvnd.noDaemon|-Dmvnd.propertiesPath|-Dmvnd.registry|-Dmvnd.rollingWindowSize|-Dmvnd.serial|-Dmvnd.threads|-Dstyle.color|-Duser.dir|-Duser.home"
local mvnd_properties="-Djava.home|-Djdk.java.options|-Dmaven.multiModuleProjectDirectory|-Dmaven.repo.local|-Dmaven.settings|-Dmvnd.buildTime|-Dmvnd.builder|-Dmvnd.daemonStorage|-Dmvnd.debug|-Dmvnd.duplicateDaemonGracePeriod|-Dmvnd.enableAssertions|-Dmvnd.expirationCheckDelay|-Dmvnd.home|-Dmvnd.idleTimeout|-Dmvnd.jvmArgs|-Dmvnd.keepAlive|-Dmvnd.logPurgePeriod|-Dmvnd.logback|-Dmvnd.maxHeapSize|-Dmvnd.maxLostKeepAlive|-Dmvnd.minHeapSize|-Dmvnd.minThreads|-Dmvnd.noBuffering|-Dmvnd.noDaemon|-Dmvnd.propertiesPath|-Dmvnd.registry|-Dmvnd.rollingWindowSize|-Dmvnd.serial|-Dmvnd.socketFamily|-Dmvnd.threads|-Dstyle.color|-Duser.dir|-Duser.home"
local opts="-am|-amd|-B|-C|-c|-cpu|-D|-e|-emp|-ep|-f|-fae|-ff|-fn|-gs|-h|-l|-N|-npr|-npu|-nsu|-o|-P|-pl|-q|-rf|-s|-T|-t|-U|-up|-V|-v|-X|${mvnd_opts}"
local long_opts="--also-make|--also-make-dependents|--batch-mode|--strict-checksums|--lax-checksums|--check-plugin-updates|--define|--errors|--encrypt-master-password|--encrypt-password|--file|--fail-at-end|--fail-fast|--fail-never|--global-settings|--help|--log-file|--non-recursive|--no-plugin-registry|--no-plugin-updates|--no-snapshot-updates|--offline|--activate-profiles|--projects|--quiet|--resume-from|--settings|--threads|--toolchains|--update-snapshots|--update-plugins|--show-version|--version|--debug|${mvnd_long_opts}"

View File

@@ -56,6 +56,10 @@
<artifactId>org.eclipse.sisu.inject</artifactId>
<version>0.3.4</version>
</dependency>
<dependency>
<groupId>org.mvndaemon.mvnd</groupId>
<artifactId>mvnd-common</artifactId>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
@@ -89,40 +93,6 @@
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<executions>
<execution>
<id>default</id>
<goals>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>jdk16</id>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<release>16</release>
<multiReleaseOutput>true</multiReleaseOutput>
<compileSourceRoots>
<root>${project.basedir}/src/main/java16</root>
</compileSourceRoots>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<archive>
<manifestFile>src/main/resources/META-INF/MANIFEST.MF</manifestFile>
</archive>
</configuration>
</plugin>
</plugins>
</build>

View File

@@ -48,6 +48,8 @@ import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import org.mvndaemon.mvnd.common.JavaVersion;
import org.mvndaemon.mvnd.common.SocketHelper;
import static org.mvndaemon.mvnd.sync.IpcMessages.REQUEST_ACQUIRE;
import static org.mvndaemon.mvnd.sync.IpcMessages.REQUEST_CLOSE;
@@ -119,9 +121,14 @@ public class IpcClient {
String tmpaddr = SocketHelper.socketAddressToString(ss.getLocalAddress());
String rand = Long.toHexString(new Random().nextLong());
String noNative = System.getProperty(IpcServer.NO_NATIVE_PROP);
boolean noNative = Boolean.getBoolean(IpcServer.NO_NATIVE_PROP);
boolean win = System.getProperty("os.name").toLowerCase(Locale.ROOT).contains("win");
if (!noNative) {
String syncCmd = win ? "mvnd-sync.exe" : "mvnd-sync";
noNative = !Files.isExecutable(syncServerPath.resolve(syncCmd));
}
Closeable close;
if (Boolean.parseBoolean(noNative)) {
if (noNative) {
String noFork = System.getProperty(IpcServer.NO_FORK_PROP);
if (Boolean.parseBoolean(noFork)) {
IpcServer server = IpcServer.runServer(family, tmpaddr, rand);
@@ -132,20 +139,10 @@ public class IpcClient {
if (javaHome == null) {
javaHome = System.getProperty("java.home");
}
boolean win = System.getProperty("os.name").toLowerCase(Locale.ROOT).contains("win");
String javaCmd = win ? "bin\\java.exe" : "bin/java";
String java = Paths.get(javaHome).resolve(javaCmd).toAbsolutePath().toString();
args.add(java);
String classpath;
String className = getClass().getName().replace('.', '/') + ".class";
String url = getClass().getClassLoader().getResource(className).toString();
if (url.startsWith("jar:")) {
classpath = url.substring("jar:".length(), url.indexOf("!/"));
} else if (url.startsWith("file:")) {
classpath = url.substring("file:".length(), url.indexOf(className));
} else {
throw new IllegalStateException();
}
String classpath = getJarPath(getClass()) + File.pathSeparator + getJarPath(SocketHelper.class);
args.add("-cp");
args.add(classpath);
String timeout = System.getProperty(IpcServer.IDLE_TIMEOUT_PROP);
@@ -169,7 +166,6 @@ public class IpcClient {
}
} else {
List<String> args = new ArrayList<>();
boolean win = System.getProperty("os.name").toLowerCase(Locale.ROOT).contains("win");
String syncCmd = win ? "mvnd-sync.exe" : "mvnd-sync";
args.add(syncServerPath.resolve(syncCmd).toString());
String timeout = System.getProperty(IpcServer.IDLE_TIMEOUT_PROP);
@@ -226,6 +222,20 @@ public class IpcClient {
}
}
private String getJarPath(Class clazz) {
String classpath;
String className = clazz.getName().replace('.', '/') + ".class";
String url = clazz.getClassLoader().getResource(className).toString();
if (url.startsWith("jar:")) {
classpath = url.substring("jar:".length(), url.indexOf("!/"));
} else if (url.startsWith("file:")) {
classpath = url.substring("file:".length(), url.indexOf(className));
} else {
throw new IllegalStateException();
}
return classpath;
}
void receive() {
try {
while (true) {

View File

@@ -35,6 +35,7 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import org.mvndaemon.mvnd.common.SocketHelper;
import static org.mvndaemon.mvnd.sync.IpcMessages.REQUEST_ACQUIRE;
import static org.mvndaemon.mvnd.sync.IpcMessages.REQUEST_CLOSE;