mirror of
https://github.com/apache/maven-mvnd.git
synced 2025-09-07 22:08:01 +00:00
Allow unix domain sockets for client/daemon connection (not used by default)
This commit is contained in:
@@ -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 {
|
||||
|
@@ -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 {
|
||||
|
@@ -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>
|
||||
|
@@ -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;
|
@@ -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
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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());
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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 {
|
||||
|
@@ -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) {
|
@@ -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);
|
||||
}
|
@@ -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());
|
||||
|
@@ -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;
|
@@ -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,
|
||||
|
@@ -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}"
|
||||
|
||||
|
38
sync/pom.xml
38
sync/pom.xml
@@ -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>
|
||||
|
||||
|
@@ -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) {
|
||||
|
@@ -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;
|
||||
|
Reference in New Issue
Block a user