private void client()

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);
            }
        }
    }