in maven-resolver-named-locks-ipc/src/main/java/org/eclipse/aether/named/ipc/IpcClient.java [112:256]
SocketChannel createClient() throws IOException {
String familyProp = System.getProperty(IpcServer.SYSTEM_PROP_FAMILY, IpcServer.DEFAULT_FAMILY);
SocketFamily family = familyProp != null ? SocketFamily.valueOf(familyProp) : SocketFamily.inet;
Path lockPath = this.lockPath.toAbsolutePath().normalize();
Path lockFile =
lockPath.resolve(".maven-resolver-ipc-lock-" + family.name().toLowerCase(Locale.ENGLISH));
if (!Files.isRegularFile(lockFile)) {
if (!Files.isDirectory(lockFile.getParent())) {
Files.createDirectories(lockFile.getParent());
}
}
try (RandomAccessFile raf = new RandomAccessFile(lockFile.toFile(), "rw")) {
try (FileLock lock = raf.getChannel().lock()) {
String line = raf.readLine();
if (line != null) {
try {
SocketAddress address = SocketFamily.fromString(line);
return SocketChannel.open(address);
} catch (IOException e) {
// ignore
}
}
ServerSocketChannel ss = family.openServerSocket();
String tmpaddr = SocketFamily.toString(ss.getLocalAddress());
String rand = Long.toHexString(new Random().nextLong());
String nativeName =
System.getProperty(IpcServer.SYSTEM_PROP_NATIVE_NAME, IpcServer.DEFAULT_NATIVE_NAME);
String syncCmd = IS_WINDOWS ? nativeName + ".exe" : nativeName;
boolean debug = Boolean.parseBoolean(
System.getProperty(IpcServer.SYSTEM_PROP_DEBUG, Boolean.toString(IpcServer.DEFAULT_DEBUG)));
boolean noNative = Boolean.parseBoolean(System.getProperty(
IpcServer.SYSTEM_PROP_NO_NATIVE, Boolean.toString(IpcServer.DEFAULT_NO_NATIVE)));
if (!noNative) {
noNative = !Files.isExecutable(syncPath.resolve(syncCmd));
}
Closeable close;
Path logFile = logPath.resolve("resolver-ipcsync-" + rand + ".log");
List<String> args = new ArrayList<>();
if (noNative) {
boolean noFork = Boolean.parseBoolean(System.getProperty(
IpcServer.SYSTEM_PROP_NO_FORK, Boolean.toString(IpcServer.DEFAULT_NO_FORK)));
if (noFork) {
IpcServer server = IpcServer.runServer(family, tmpaddr, rand);
close = server::close;
} else {
String javaHome = System.getenv("JAVA_HOME");
if (javaHome == null) {
javaHome = System.getProperty("java.home");
}
String javaCmd = IS_WINDOWS ? "bin\\java.exe" : "bin/java";
String java = Paths.get(javaHome)
.resolve(javaCmd)
.toAbsolutePath()
.toString();
args.add(java);
String classpath = getJarPath(getClass()) + File.pathSeparator + getJarPath(IpcServer.class);
args.add("-cp");
args.add(classpath);
String timeout = System.getProperty(IpcServer.SYSTEM_PROP_IDLE_TIMEOUT);
if (timeout != null) {
args.add("-D" + IpcServer.SYSTEM_PROP_IDLE_TIMEOUT + "=" + timeout);
}
args.add("-D" + IpcServer.SYSTEM_PROP_DEBUG + "=" + debug);
args.add(IpcServer.class.getName());
args.add(family.name());
args.add(tmpaddr);
args.add(rand);
ProcessBuilder processBuilder = new ProcessBuilder();
ProcessBuilder.Redirect discard = ProcessBuilder.Redirect.to(logFile.toFile());
Files.createDirectories(logPath);
Process process = processBuilder
.directory(lockFile.getParent().toFile())
.command(args)
.redirectOutput(discard)
.redirectError(discard)
.start();
close = process::destroyForcibly;
}
} else {
args.add(syncPath.resolve(syncCmd).toString());
String timeout = System.getProperty(IpcServer.SYSTEM_PROP_IDLE_TIMEOUT);
if (timeout != null) {
args.add("-D" + IpcServer.SYSTEM_PROP_IDLE_TIMEOUT + "=" + timeout);
}
args.add("-D" + IpcServer.SYSTEM_PROP_DEBUG + "=" + debug);
args.add(family.name());
args.add(tmpaddr);
args.add(rand);
ProcessBuilder processBuilder = new ProcessBuilder();
ProcessBuilder.Redirect discard = ProcessBuilder.Redirect.to(logFile.toFile());
Files.createDirectories(logPath);
Process process = processBuilder
.directory(lockFile.getParent().toFile())
.command(args)
.redirectOutput(discard)
.redirectError(discard)
.start();
close = process::destroyForcibly;
}
ExecutorService es = Executors.newSingleThreadExecutor();
Future<String[]> future = es.submit(() -> {
SocketChannel s = ss.accept();
DataInputStream dis = new DataInputStream(Channels.newInputStream(s));
String rand2 = dis.readUTF();
String addr2 = dis.readUTF();
return new String[] {rand2, addr2};
});
String[] res;
try {
res = future.get(5, TimeUnit.SECONDS);
} catch (Exception e) {
try (PrintWriter writer = new PrintWriter(new FileWriter(logFile.toFile(), true))) {
writer.println("Arguments:");
args.forEach(writer::println);
writer.println();
writer.println("Exception:");
e.printStackTrace(writer);
}
close.close();
throw e;
} finally {
es.shutdownNow();
ss.close();
}
if (!Objects.equals(rand, res[0])) {
close.close();
throw new IllegalStateException("IpcServer did not respond with the correct random");
}
SocketAddress addr = SocketFamily.fromString(res[1]);
SocketChannel socket = SocketChannel.open(addr);
raf.seek(0);
raf.writeBytes(res[1] + "\n");
return socket;
} catch (Exception e) {
throw new RuntimeException("Unable to create and connect to lock server", e);
}
}
}