in maven-resolver-named-locks-ipc/src/main/java/org/eclipse/aether/named/ipc/IpcServer.java [228:365]
private void client(SocketChannel socket) {
int c;
synchronized (clients) {
clients.put(socket, Thread.currentThread());
c = clients.size();
}
info("New client connected (%d connected)", c);
use();
Map<String, Context> clientContexts = new ConcurrentHashMap<>();
try {
ByteChannel wrapper = new ByteChannelWrapper(socket);
DataInputStream input = new DataInputStream(Channels.newInputStream(wrapper));
DataOutputStream output = new DataOutputStream(Channels.newOutputStream(wrapper));
while (!closing) {
int requestId = input.readInt();
int sz = input.readInt();
List<String> request = new ArrayList<>(sz);
for (int i = 0; i < sz; i++) {
request.add(input.readUTF());
}
if (request.isEmpty()) {
throw new IOException("Received invalid request");
}
use();
String contextId;
Context context;
String command = request.remove(0);
switch (command) {
case IpcMessages.REQUEST_CONTEXT:
if (request.size() != 1) {
throw new IOException("Expected one argument for " + command + " but got " + request);
}
boolean shared = Boolean.parseBoolean(request.remove(0));
context = new Context(shared);
contexts.put(context.id, context);
clientContexts.put(context.id, context);
synchronized (output) {
debug("Created context %s", context.id);
output.writeInt(requestId);
output.writeInt(2);
output.writeUTF(IpcMessages.RESPONSE_CONTEXT);
output.writeUTF(context.id);
output.flush();
}
break;
case IpcMessages.REQUEST_ACQUIRE:
if (request.size() < 1) {
throw new IOException(
"Expected at least one argument for " + command + " but got " + request);
}
contextId = request.remove(0);
context = contexts.get(contextId);
if (context == null) {
throw new IOException(
"Unknown context: " + contextId + ". Known contexts = " + contexts.keySet());
}
context.lock(request).thenRun(() -> {
try {
synchronized (output) {
debug("Locking in context %s", context.id);
output.writeInt(requestId);
output.writeInt(1);
output.writeUTF(IpcMessages.RESPONSE_ACQUIRE);
output.flush();
}
} catch (IOException e) {
try {
socket.close();
} catch (IOException ioException) {
e.addSuppressed(ioException);
}
error("Error writing lock response", e);
}
});
break;
case IpcMessages.REQUEST_CLOSE:
if (request.size() != 1) {
throw new IOException("Expected one argument for " + command + " but got " + request);
}
contextId = request.remove(0);
context = contexts.remove(contextId);
clientContexts.remove(contextId);
if (context == null) {
throw new IOException(
"Unknown context: " + contextId + ". Known contexts = " + contexts.keySet());
}
context.unlock();
synchronized (output) {
debug("Closing context %s", context.id);
output.writeInt(requestId);
output.writeInt(1);
output.writeUTF(IpcMessages.RESPONSE_CLOSE);
output.flush();
}
break;
case IpcMessages.REQUEST_STOP:
if (request.size() != 0) {
throw new IOException("Expected zero argument for " + command + " but got " + request);
}
synchronized (output) {
debug("Stopping server");
output.writeInt(requestId);
output.writeInt(1);
output.writeUTF(IpcMessages.RESPONSE_STOP);
output.flush();
}
close();
break;
default:
throw new IOException("Unknown request: " + request.get(0));
}
}
} catch (Throwable t) {
if (!closing) {
error("Error processing request", t);
}
} finally {
if (!closing) {
info("Client disconnecting...");
}
clientContexts.values().forEach(context -> {
contexts.remove(context.id);
context.unlock();
});
try {
socket.close();
} catch (IOException ioException) {
// ignore
}
synchronized (clients) {
clients.remove(socket);
c = clients.size();
}
if (!closing) {
info("%d clients left", c);
}
}
}