Skip to content
Closed
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
d31fc6d
[CAMEL-22557] AS2: Fix configuration isolation and enable port sharin…
brunovg Oct 21, 2025
24577e4
added comment on requestUriPattern. ran mvn formatter:format on camel…
brunovg Oct 22, 2025
e96c252
using ObjectHelper.isNotEmpty to check if requestUriPattern is not empty
brunovg Oct 22, 2025
618d396
removed requestUriPattern declaration on AS2Configuration. requestUri…
brunovg Oct 23, 2025
79580ca
restore security context in AS2ServerConnection to resolve MDN signin…
brunovg Oct 23, 2025
6fe5a4a
[CAMEL-22557] AS2: Fix configuration isolation and enable port sharin…
brunovg Oct 21, 2025
fd67a1b
added comment on requestUriPattern. ran mvn formatter:format on camel…
brunovg Oct 22, 2025
fdc3c10
using ObjectHelper.isNotEmpty to check if requestUriPattern is not empty
brunovg Oct 22, 2025
b9cd21d
removed requestUriPattern declaration on AS2Configuration. requestUri…
brunovg Oct 23, 2025
4014d98
restore security context in AS2ServerConnection to resolve MDN signin…
brunovg Oct 23, 2025
660e170
Initialize AS2ServerConnection in AS2ConnectionHelper using the actua…
brunovg Oct 24, 2025
eb4b3ee
Initialize AS2ServerConnection in AS2ConnectionHelper using the actua…
brunovg Oct 24, 2025
6e82b26
Revert "Initialize AS2ServerConnection in AS2ConnectionHelper using t…
brunovg Oct 24, 2025
ff95019
AS2 unit tests with two consumers
brunovg Oct 27, 2025
dfd89e3
using the right signing private key on createReceivedContentMic method
brunovg Oct 28, 2025
acb3930
Introduce AS2ConsumerConfigInterceptor and ThreadLocal state to enabl…
brunovg Oct 29, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -64,57 +64,84 @@ public class AS2ServerConnection {
private static final String REQUEST_LISTENER_THREAD_NAME_PREFIX = "AS2Svr-";
private static final String REQUEST_HANDLER_THREAD_NAME_PREFIX = "AS2Hdlr-";

class RequestListenerThread extends Thread {
private ServerSocket serversocket;
private RequestListenerService listenerService;
private RequestAcceptorThread acceptorThread;
private final Lock lock = new ReentrantLock();

private final String as2Version;
private final String originServer;
private final String serverFqdn;
private final Certificate[] signingCertificateChain;
private final PrivateKey signingPrivateKey;
private final PrivateKey decryptingPrivateKey;
private final Certificate[] validateSigningCertificateChain;
private final AS2SignatureAlgorithm signingAlgorithm;

class RequestListenerService {

private final ServerSocket serversocket;
private final HttpService httpService;
private final RequestHandlerRegistry registry;
private final HttpServerRequestHandler handler;

public RequestListenerThread(String as2Version,
String originServer,
String serverFqdn,
int port,
AS2SignatureAlgorithm signatureAlgorithm,
Certificate[] signingCertificateChain,
PrivateKey signingPrivateKey,
PrivateKey decryptingPrivateKey,
String mdnMessageTemplate,
Certificate[] validateSigningCertificateChain,
SSLContext sslContext)
throws IOException {
setName(REQUEST_LISTENER_THREAD_NAME_PREFIX + port);

if (sslContext == null) {
serversocket = new ServerSocket(port);
} else {
SSLServerSocketFactory factory = sslContext.getServerSocketFactory();
serversocket = factory.createServerSocket(port);
}
public RequestListenerService(String as2Version,
String originServer,
String serverFqdn,
AS2SignatureAlgorithm signatureAlgorithm,
String mdnMessageTemplate,
Certificate[] validateSigningCertificateChain)
throws IOException {

// Set up HTTP protocol processor for incoming connections
final HttpProcessor inhttpproc = initProtocolProcessor(as2Version, originServer, serverFqdn,
signatureAlgorithm, signingCertificateChain, signingPrivateKey, decryptingPrivateKey, mdnMessageTemplate,
null, null, null, null, mdnMessageTemplate,
validateSigningCertificateChain);

registry = new RequestHandlerRegistry<>();
handler = new BasicHttpServerRequestHandler(registry);
HttpServerRequestHandler handler = new BasicHttpServerRequestHandler(registry);

// Set up the HTTP service
httpService = new HttpService(inhttpproc, handler);
}

void registerHandler(String requestUriPattern, HttpRequestHandler httpRequestHandler) {
registry.register(null, requestUriPattern, httpRequestHandler);
}

void unregisterHandler(String requestUriPattern) {
// we cannot remove from http registry, but we can replace with a not found to simulate 404
registry.register(null, requestUriPattern, new NotFoundHttpRequestHandler());
}
}

class RequestAcceptorThread extends Thread {

private final RequestListenerService service;

public RequestAcceptorThread(int port, SSLContext sslContext, RequestListenerService service)
throws IOException {
setName(REQUEST_LISTENER_THREAD_NAME_PREFIX + port);
this.service = service;

// 2. BIND THE PORT HERE! This happens only once.
if (sslContext == null) {
serversocket = new ServerSocket(port);
} else {
SSLServerSocketFactory factory = sslContext.getServerSocketFactory();
serversocket = factory.createServerSocket(port);
}
}

@Override
public void run() {
LOG.info("Listening on port {}", this.serversocket.getLocalPort());
// serversocket is now a field of the outer AS2ServerConnection class
LOG.info("Listening on port {}", serversocket.getLocalPort());
while (!Thread.interrupted()) {
try {

// Set up incoming HTTP connection
final Socket inSocket = this.serversocket.accept();
final Socket inSocket = serversocket.accept();

// Start worker thread
final Thread t = new RequestHandlerThread(this.httpService, inSocket);
// Start worker thread, using the service's HttpService
final Thread t = new RequestHandlerThread(this.service.httpService, inSocket);
t.setDaemon(true);
t.start();
} catch (final InterruptedIOException | SocketException ex) {
Expand All @@ -126,15 +153,6 @@ public void run() {
}
}
}

void registerHandler(String requestUriPattern, HttpRequestHandler httpRequestHandler) {
registry.register(null, requestUriPattern, httpRequestHandler);
}

void unregisterHandler(String requestUriPattern) {
// we cannot remove from http registry, but we can replace with a not found to simulate 404
registry.register(null, requestUriPattern, new NotFoundHttpRequestHandler());
}
}

class RequestHandlerThread extends Thread {
Expand Down Expand Up @@ -219,17 +237,6 @@ public void run() {

}

private RequestListenerThread listenerThread;
private final Lock lock = new ReentrantLock();
private final String as2Version;
private final String originServer;
private final String serverFqdn;
private final Certificate[] signingCertificateChain;
private final PrivateKey signingPrivateKey;
private final PrivateKey decryptingPrivateKey;
private final Certificate[] validateSigningCertificateChain;
private final AS2SignatureAlgorithm signingAlgorithm;

public AS2ServerConnection(String as2Version,
String originServer,
String serverFqdn,
Expand All @@ -250,14 +257,15 @@ public AS2ServerConnection(String as2Version,
this.signingPrivateKey = signingPrivateKey;
this.decryptingPrivateKey = decryptingPrivateKey;
this.validateSigningCertificateChain = validateSigningCertificateChain;

this.signingAlgorithm = signingAlgorithm;
listenerThread = new RequestListenerThread(

listenerService = new RequestListenerService(
this.as2Version, this.originServer, this.serverFqdn,
parserServerPortNumber, signingAlgorithm, this.signingCertificateChain, this.signingPrivateKey,
this.decryptingPrivateKey, mdnMessageTemplate, validateSigningCertificateChain, sslContext);
listenerThread.setDaemon(true);
listenerThread.start();
signingAlgorithm, mdnMessageTemplate, validateSigningCertificateChain);

acceptorThread = new RequestAcceptorThread(parserServerPortNumber, sslContext, listenerService);
acceptorThread.setDaemon(true);
acceptorThread.start();
}

public Certificate[] getValidateSigningCertificateChain() {
Expand All @@ -273,15 +281,19 @@ public PrivateKey getDecryptingPrivateKey() {
}

public void close() {
if (listenerThread != null) {
if (acceptorThread != null) {
lock.lock();
try {
try {
listenerThread.serversocket.close();
// 3. Close the shared ServerSocket
if (serversocket != null) {
serversocket.close();
}
} catch (IOException e) {
LOG.debug(e.getMessage(), e);
} finally {
listenerThread = null;
acceptorThread = null;
listenerService = null;
}
} finally {
lock.unlock();
Expand All @@ -290,21 +302,21 @@ public void close() {
}

public void listen(String requestUri, HttpRequestHandler handler) {
if (listenerThread != null) {
if (listenerService != null) {
lock.lock();
try {
listenerThread.registerHandler(requestUri, handler);
listenerService.registerHandler(requestUri, handler);
} finally {
lock.unlock();
}
}
}

public void unlisten(String requestUri) {
if (listenerThread != null) {
if (listenerService != null) {
lock.lock();
try {
listenerThread.unregisterHandler(requestUri);
listenerService.unregisterHandler(requestUri);
} finally {
lock.unlock();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ public class AS2ClientManagerEndpointConfigurationConfigurer extends org.apache.
map.put("MethodName", java.lang.String.class);
map.put("ReceiptDeliveryOption", java.lang.String.class);
map.put("RequestUri", java.lang.String.class);
map.put("RequestUriPattern", java.lang.String.class);
map.put("Server", java.lang.String.class);
map.put("ServerFqdn", java.lang.String.class);
map.put("ServerPortNumber", java.lang.Integer.class);
Expand Down Expand Up @@ -122,6 +123,8 @@ public boolean configure(CamelContext camelContext, Object obj, String name, Obj
case "receiptDeliveryOption": target.setReceiptDeliveryOption(property(camelContext, java.lang.String.class, value)); return true;
case "requesturi":
case "requestUri": target.setRequestUri(property(camelContext, java.lang.String.class, value)); return true;
case "requesturipattern":
case "requestUriPattern": target.setRequestUriPattern(property(camelContext, java.lang.String.class, value)); return true;
case "server": target.setServer(property(camelContext, java.lang.String.class, value)); return true;
case "serverfqdn":
case "serverFqdn": target.setServerFqdn(property(camelContext, java.lang.String.class, value)); return true;
Expand Down Expand Up @@ -211,6 +214,8 @@ public Class<?> getOptionType(String name, boolean ignoreCase) {
case "receiptDeliveryOption": return java.lang.String.class;
case "requesturi":
case "requestUri": return java.lang.String.class;
case "requesturipattern":
case "requestUriPattern": return java.lang.String.class;
case "server": return java.lang.String.class;
case "serverfqdn":
case "serverFqdn": return java.lang.String.class;
Expand Down Expand Up @@ -296,6 +301,8 @@ public Object getOptionValue(Object obj, String name, boolean ignoreCase) {
case "receiptDeliveryOption": return target.getReceiptDeliveryOption();
case "requesturi":
case "requestUri": return target.getRequestUri();
case "requesturipattern":
case "requestUriPattern": return target.getRequestUriPattern();
case "server": return target.getServer();
case "serverfqdn":
case "serverFqdn": return target.getServerFqdn();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ public class AS2ConfigurationConfigurer extends org.apache.camel.support.compone
map.put("MethodName", java.lang.String.class);
map.put("ReceiptDeliveryOption", java.lang.String.class);
map.put("RequestUri", java.lang.String.class);
map.put("RequestUriPattern", java.lang.String.class);
map.put("Server", java.lang.String.class);
map.put("ServerFqdn", java.lang.String.class);
map.put("ServerPortNumber", java.lang.Integer.class);
Expand Down Expand Up @@ -116,6 +117,8 @@ public boolean configure(CamelContext camelContext, Object obj, String name, Obj
case "receiptDeliveryOption": target.setReceiptDeliveryOption(property(camelContext, java.lang.String.class, value)); return true;
case "requesturi":
case "requestUri": target.setRequestUri(property(camelContext, java.lang.String.class, value)); return true;
case "requesturipattern":
case "requestUriPattern": target.setRequestUriPattern(property(camelContext, java.lang.String.class, value)); return true;
case "server": target.setServer(property(camelContext, java.lang.String.class, value)); return true;
case "serverfqdn":
case "serverFqdn": target.setServerFqdn(property(camelContext, java.lang.String.class, value)); return true;
Expand Down Expand Up @@ -201,6 +204,8 @@ public Class<?> getOptionType(String name, boolean ignoreCase) {
case "receiptDeliveryOption": return java.lang.String.class;
case "requesturi":
case "requestUri": return java.lang.String.class;
case "requesturipattern":
case "requestUriPattern": return java.lang.String.class;
case "server": return java.lang.String.class;
case "serverfqdn":
case "serverFqdn": return java.lang.String.class;
Expand Down Expand Up @@ -282,6 +287,8 @@ public Object getOptionValue(Object obj, String name, boolean ignoreCase) {
case "receiptDeliveryOption": return target.getReceiptDeliveryOption();
case "requesturi":
case "requestUri": return target.getRequestUri();
case "requesturipattern":
case "requestUriPattern": return target.getRequestUriPattern();
case "server": return target.getServer();
case "serverfqdn":
case "serverFqdn": return target.getServerFqdn();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ public class AS2EndpointConfigurer extends PropertyConfigurerSupport implements
map.put("MdnMessageTemplate", java.lang.String.class);
map.put("ReceiptDeliveryOption", java.lang.String.class);
map.put("RequestUri", java.lang.String.class);
map.put("RequestUriPattern", java.lang.String.class);
map.put("Server", java.lang.String.class);
map.put("ServerFqdn", java.lang.String.class);
map.put("ServerPortNumber", java.lang.Integer.class);
Expand Down Expand Up @@ -124,6 +125,8 @@ public boolean configure(CamelContext camelContext, Object obj, String name, Obj
case "receiptDeliveryOption": target.getConfiguration().setReceiptDeliveryOption(property(camelContext, java.lang.String.class, value)); return true;
case "requesturi":
case "requestUri": target.getConfiguration().setRequestUri(property(camelContext, java.lang.String.class, value)); return true;
case "requesturipattern":
case "requestUriPattern": target.getConfiguration().setRequestUriPattern(property(camelContext, java.lang.String.class, value)); return true;
case "server": target.getConfiguration().setServer(property(camelContext, java.lang.String.class, value)); return true;
case "serverfqdn":
case "serverFqdn": target.getConfiguration().setServerFqdn(property(camelContext, java.lang.String.class, value)); return true;
Expand Down Expand Up @@ -213,6 +216,8 @@ public Class<?> getOptionType(String name, boolean ignoreCase) {
case "receiptDeliveryOption": return java.lang.String.class;
case "requesturi":
case "requestUri": return java.lang.String.class;
case "requesturipattern":
case "requestUriPattern": return java.lang.String.class;
case "server": return java.lang.String.class;
case "serverfqdn":
case "serverFqdn": return java.lang.String.class;
Expand Down Expand Up @@ -298,6 +303,8 @@ public Object getOptionValue(Object obj, String name, boolean ignoreCase) {
case "receiptDeliveryOption": return target.getConfiguration().getReceiptDeliveryOption();
case "requesturi":
case "requestUri": return target.getConfiguration().getRequestUri();
case "requesturipattern":
case "requestUriPattern": return target.getConfiguration().getRequestUriPattern();
case "server": return target.getConfiguration().getServer();
case "serverfqdn":
case "serverFqdn": return target.getConfiguration().getServerFqdn();
Expand Down
Loading
Loading