InternalContext.java
/*
* SPDX-FileCopyrightText: 2023-2025 Lucimber UG
* SPDX-License-Identifier: Apache-2.0
*/
package com.lucimber.dbus.connection;
import com.lucimber.dbus.message.InboundMessage;
import com.lucimber.dbus.message.OutboundMessage;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Internal implementation of {@link Context} used for doubly-linked pipeline structure. Only used
* within {@link DefaultPipeline}.
*/
final class InternalContext implements Context {
private static final Logger LOGGER = LoggerFactory.getLogger(InternalContext.class);
private final Connection connection;
private final DefaultPipeline pipeline;
private final String name;
private final Handler handler;
private InternalContext prev;
private InternalContext next;
InternalContext(Connection connection, DefaultPipeline pipeline, String name, Handler handler) {
this.connection = Objects.requireNonNull(connection, "connection must not be null");
this.pipeline = Objects.requireNonNull(pipeline, "pipeline must not be null");
this.name = Objects.requireNonNull(name, "name must not be null");
this.handler = Objects.requireNonNull(handler, "handler must not be null");
}
public InternalContext getNext() {
return next;
}
public void setNext(InternalContext next) {
this.next = next;
}
public InternalContext getPrev() {
return prev;
}
public void setPrev(InternalContext prev) {
this.prev = prev;
}
@Override
public Pipeline getPipeline() {
return pipeline;
}
@Override
public Connection getConnection() {
return connection;
}
@Override
public String getName() {
return name;
}
@Override
public Handler getHandler() {
return handler;
}
@Override
public void propagateConnectionActive() {
if (isRemoved()) {
String msg =
"Not propagating connection-active event, "
+ "because this handler is removed from the pipeline.";
throw new IllegalArgumentException(msg);
}
InternalContext ctx = getNext();
if (ctx == null) {
LOGGER.debug(
"Connection-active event received, evaluated, and ceremonially ignored. "
+ "It's now haunting /dev/null.");
} else {
ctx.onConnectionActive();
}
}
@Override
public void propagateConnectionInactive() {
if (isRemoved()) {
String msg =
"Not propagating connection-inactive event, "
+ "because this handler is removed from the pipeline.";
throw new IllegalArgumentException(msg);
}
InternalContext ctx = getNext();
if (ctx == null) {
LOGGER.debug(
"Connection-inactive event received, evaluated, and ceremonially ignored. "
+ "It's now haunting /dev/null.");
} else {
ctx.onConnectionInactive();
}
}
@Override
public void propagateInboundMessage(InboundMessage msg) {
if (isRemoved()) {
String s =
"Not propagating inbound message, "
+ "because this handler is removed from the pipeline.";
throw new IllegalArgumentException(s);
}
InternalContext ctx = getNext();
if (ctx == null) {
LOGGER.warn(
"Inbound message received, evaluated, and ceremonially ignored. "
+ "It's now haunting /dev/null.");
} else {
ctx.handleInboundMessage(msg);
}
}
@Override
public void propagateOutboundMessage(OutboundMessage msg, CompletableFuture<Void> future) {
if (isRemoved()) {
String s =
"Not propagating outbound message, "
+ "because this handler is removed from the pipeline.";
throw new IllegalArgumentException(s);
}
InternalContext ctx = getPrev();
if (ctx == null) {
throw new IllegalStateException(
"Cannot propagate an outbound message any further on this pipeline. "
+ "Please execute handleOutboundMessage on this context instead.");
} else {
ctx.handleOutboundMessage(msg, future);
}
}
@Override
public void propagateInboundFailure(Throwable cause) {
if (isRemoved()) {
String msg =
"Not propagating inbound failure, "
+ "because this handler is removed from the pipeline.";
throw new IllegalArgumentException(msg);
}
InternalContext ctx = getNext();
if (ctx == null) {
LOGGER.warn(
"Inbound failure received, evaluated, and ceremonially ignored. "
+ "It's now haunting /dev/null.");
} else {
ctx.handleInboundFailure(cause);
}
}
@Override
public void propagateUserEvent(Object evt) {
if (isRemoved()) {
String msg =
"Not propagating user-defined event, "
+ "because this handler is removed from the pipeline.";
throw new IllegalArgumentException(msg);
}
InternalContext ctx = getNext();
if (ctx == null) {
LOGGER.debug(
"User-defined event received, evaluated, and ceremonially ignored. "
+ "It's now haunting /dev/null.");
} else {
ctx.handleUserEvent(evt);
}
}
@Override
public boolean isRemoved() {
return next == null && prev == null;
}
public void handleInboundMessage(InboundMessage msg) {
if (handler instanceof InboundHandler inboundHandler) {
try {
inboundHandler.handleInboundMessage(this, msg);
} catch (Throwable t) {
handleInboundFailure(t);
}
} else {
propagateInboundMessage(msg);
}
}
public void handleOutboundMessage(OutboundMessage msg, CompletableFuture<Void> future) {
if (handler instanceof OutboundHandler outboundHandler) {
try {
outboundHandler.handleOutboundMessage(this, msg, future);
} catch (Throwable t) {
LOGGER.error(
"Outbound message event fumbled into chaos. "
+ "Terminating the connection with prejudice.");
try {
pipeline.getConnection().close();
} catch (Exception ignored) {
// Intentionally ignoring exception during emergency close
}
}
} else {
propagateOutboundMessage(msg, future);
}
}
public void handleInboundFailure(Throwable cause) {
if (handler instanceof InboundHandler inboundHandler) {
try {
inboundHandler.handleInboundFailure(this, cause);
} catch (Throwable t) {
LOGGER.error(
"Failure caused by inbound message event fumbled into chaos. "
+ "Recovery was a nice idea. "
+ "Terminating the connection with prejudice.");
try {
pipeline.getConnection().close();
} catch (Exception ignored) {
// Intentionally ignoring exception during emergency close
}
}
} else {
propagateInboundFailure(cause);
}
}
public void handleUserEvent(Object evt) {
try {
handler.handleUserEvent(this, evt);
} catch (Throwable t) {
LOGGER.error(
"User-defined event fumbled into chaos. "
+ "Terminating the connection with prejudice.");
try {
pipeline.getConnection().close();
} catch (Exception ignored) {
// Intentionally ignoring exception during emergency close
}
}
}
public void onConnectionActive() {
try {
handler.onConnectionActive(this);
} catch (Throwable t) {
LOGGER.error(
"Connection-active event fumbled into chaos. "
+ "Terminating the connection with prejudice.");
try {
pipeline.getConnection().close();
} catch (Exception ignored) {
// Intentionally ignoring exception during emergency close
}
}
}
public void onConnectionInactive() {
try {
handler.onConnectionInactive(this);
} catch (Throwable t) {
LOGGER.error(
"Connection-inactive event fumbled into chaos. "
+ "Terminating the connection with prejudice.");
try {
pipeline.getConnection().close();
} catch (Exception ignored) {
// Intentionally ignoring exception during emergency close
}
}
}
}