Skip to content

Commit 3fd8237

Browse files
authored
1 parent f75f600 commit 3fd8237

27 files changed

Lines changed: 176 additions & 115 deletions

components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/AS2AsyncMDNServerConnection.java

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
import java.net.ServerSocket;
2222
import java.net.Socket;
2323
import java.net.SocketException;
24+
import java.util.LinkedHashMap;
25+
import java.util.Map;
2426
import java.util.concurrent.locks.Lock;
2527
import java.util.concurrent.locks.ReentrantLock;
2628

@@ -29,18 +31,19 @@
2931

3032
import org.apache.camel.component.as2.api.io.AS2BHttpServerConnection;
3133
import org.apache.camel.util.ObjectHelper;
34+
import org.apache.hc.core5.http.ClassicHttpRequest;
3235
import org.apache.hc.core5.http.HttpException;
3336
import org.apache.hc.core5.http.config.Http1Config;
3437
import org.apache.hc.core5.http.impl.io.HttpService;
38+
import org.apache.hc.core5.http.impl.routing.RequestRouter;
3539
import org.apache.hc.core5.http.io.HttpRequestHandler;
3640
import org.apache.hc.core5.http.io.HttpServerConnection;
3741
import org.apache.hc.core5.http.io.HttpServerRequestHandler;
3842
import org.apache.hc.core5.http.io.support.BasicHttpServerRequestHandler;
39-
import org.apache.hc.core5.http.protocol.BasicHttpContext;
4043
import org.apache.hc.core5.http.protocol.DefaultHttpProcessor;
4144
import org.apache.hc.core5.http.protocol.HttpContext;
45+
import org.apache.hc.core5.http.protocol.HttpCoreContext;
4246
import org.apache.hc.core5.http.protocol.HttpProcessor;
43-
import org.apache.hc.core5.http.protocol.RequestHandlerRegistry;
4447
import org.apache.hc.core5.http.protocol.RequestValidateHost;
4548
import org.slf4j.Logger;
4649
import org.slf4j.LoggerFactory;
@@ -98,8 +101,22 @@ class RequestListenerThread extends Thread {
98101

99102
private final ServerSocket serverSocket;
100103
private final HttpService httpService;
101-
private final RequestHandlerRegistry registry;
102-
private final HttpServerRequestHandler handler;
104+
private final Map<String, HttpRequestHandler> routeMap = new LinkedHashMap<>();
105+
private volatile HttpServerRequestHandler currentHandler;
106+
107+
/**
108+
* Delegating handler that always forwards to the current handler. This allows us to update the routing
109+
* configuration dynamically.
110+
*/
111+
private class DelegatingRequestHandler implements HttpServerRequestHandler {
112+
@Override
113+
public void handle(
114+
ClassicHttpRequest request, HttpServerRequestHandler.ResponseTrigger responseTrigger,
115+
HttpContext context)
116+
throws HttpException, IOException {
117+
currentHandler.handle(request, responseTrigger, context);
118+
}
119+
}
103120

104121
public RequestListenerThread(int port, SSLContext sslContext) throws IOException {
105122
setName(REQUEST_LISTENER_THREAD_NAME_PREFIX + port);
@@ -110,9 +127,20 @@ public RequestListenerThread(int port, SSLContext sslContext) throws IOException
110127
serverSocket = factory.createServerSocket(port);
111128
}
112129
HttpProcessor httpProcessor = new DefaultHttpProcessor(new RequestValidateHost());
113-
registry = new RequestHandlerRegistry<>();
114-
handler = new BasicHttpServerRequestHandler(registry);
115-
httpService = new HttpService(httpProcessor, handler);
130+
// Create initial empty router
131+
currentHandler = createHandler();
132+
// Set up the HTTP service with delegating handler
133+
httpService = new HttpService(httpProcessor, new DelegatingRequestHandler());
134+
}
135+
136+
private HttpServerRequestHandler createHandler() {
137+
RequestRouter.Builder<HttpRequestHandler> builder = RequestRouter.builder();
138+
// Use LOCAL_AUTHORITY_RESOLVER to match any host (like the old RequestHandlerRegistry behavior)
139+
builder.resolveAuthority(RequestRouter.LOCAL_AUTHORITY_RESOLVER);
140+
for (Map.Entry<String, HttpRequestHandler> entry : routeMap.entrySet()) {
141+
builder.addRoute(RequestRouter.LOCAL_AUTHORITY, entry.getKey(), entry.getValue());
142+
}
143+
return new BasicHttpServerRequestHandler(builder.build());
116144
}
117145

118146
@Override
@@ -136,7 +164,8 @@ public void run() {
136164
}
137165

138166
void registerHandler(String requestUriPattern, HttpRequestHandler httpRequestHandler) {
139-
registry.register(null, requestUriPattern, httpRequestHandler);
167+
routeMap.put(requestUriPattern, httpRequestHandler);
168+
currentHandler = createHandler();
140169
}
141170
}
142171

@@ -162,7 +191,7 @@ public RequestHandlerThread(HttpService httpService, Socket inSocket) throws IOE
162191

163192
@Override
164193
public void run() {
165-
final HttpContext context = new BasicHttpContext(null);
194+
final HttpContext context = HttpCoreContext.create();
166195
try {
167196
while (!Thread.interrupted()) {
168197
this.httpService.handleRequest(this.serverConnection, context);

components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/AS2AsynchronousMDNManager.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,18 @@ public class AS2AsynchronousMDNManager {
6060

6161
/**
6262
* The HTTP Context Attribute containing the HTTP request message transporting the EDI message
63+
*
64+
* @deprecated Use getter method from HttpContext implementation.
6365
*/
66+
@Deprecated
6467
public static final String HTTP_REQUEST = HttpCoreContext.HTTP_REQUEST;
6568

6669
/**
6770
* The HTTP Context Attribute containing the HTTP response message transporting the EDI message
71+
*
72+
* @deprecated Use getter method from HttpContext implementation.
6873
*/
74+
@Deprecated
6975
public static final String HTTP_RESPONSE = HttpCoreContext.HTTP_RESPONSE;
7076

7177
/**
@@ -141,7 +147,7 @@ public HttpCoreContext send(
141147
ClassicHttpRequest request = new BasicClassicHttpRequest("POST", uri);
142148
request.setHeader(AS2Header.CONTENT_TYPE, contentType);
143149
AS2HeaderUtils.addAuthorizationHeader(request, userName, password, accessToken);
144-
httpContext.setAttribute(HttpCoreContext.HTTP_REQUEST, request);
150+
httpContext.setRequest(request);
145151
multipartMimeEntity.setMainBody(true);
146152
EntityUtils.setMessageEntity(request, multipartMimeEntity);
147153

@@ -152,7 +158,7 @@ public HttpCoreContext send(
152158
} catch (IOException e) {
153159
throw new HttpException("Failed to send http request message", e);
154160
}
155-
httpContext.setAttribute(HTTP_RESPONSE, response);
161+
httpContext.setResponse(response);
156162

157163
return httpContext;
158164
} catch (Exception e) {

components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/AS2ClientConnection.java

Lines changed: 19 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -41,17 +41,10 @@
4141
import org.apache.hc.client5.http.io.ConnectionEndpoint;
4242
import org.apache.hc.client5.http.io.LeaseRequest;
4343
import org.apache.hc.client5.http.io.ManagedHttpClientConnection;
44-
import org.apache.hc.client5.http.socket.ConnectionSocketFactory;
45-
import org.apache.hc.client5.http.socket.PlainConnectionSocketFactory;
46-
import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory;
44+
import org.apache.hc.client5.http.ssl.DefaultClientTlsStrategy;
45+
import org.apache.hc.client5.http.ssl.TlsSocketStrategy;
4746
import org.apache.hc.core5.http.*;
48-
import org.apache.hc.core5.http.ClassicHttpRequest;
49-
import org.apache.hc.core5.http.ClassicHttpResponse;
50-
import org.apache.hc.core5.http.Header;
51-
import org.apache.hc.core5.http.HttpHost;
5247
import org.apache.hc.core5.http.config.Http1Config;
53-
import org.apache.hc.core5.http.config.Registry;
54-
import org.apache.hc.core5.http.config.RegistryBuilder;
5548
import org.apache.hc.core5.http.impl.io.HttpRequestExecutor;
5649
import org.apache.hc.core5.http.io.HttpClientConnection;
5750
import org.apache.hc.core5.http.io.HttpConnectionFactory;
@@ -121,22 +114,20 @@ public ManagedHttpClientConnection createConnection(final Socket socket) throws
121114
}
122115
};
123116

124-
if (sslContext == null) {
125-
connectionPoolManager = PoolingHttpClientConnectionManagerBuilder.create()
126-
.setConnectionFactory(connFactory).build();
127-
} else {
128-
SSLConnectionSocketFactory sslConnectionSocketFactory;
117+
PoolingHttpClientConnectionManagerBuilder builder = PoolingHttpClientConnectionManagerBuilder.create()
118+
.setConnectionFactory(connFactory);
119+
120+
if (sslContext != null) {
121+
TlsSocketStrategy tlsStrategy;
129122
if (hostnameVerifier == null) {
130-
sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext);
123+
tlsStrategy = new DefaultClientTlsStrategy(sslContext);
131124
} else {
132-
sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext, hostnameVerifier);
125+
tlsStrategy = new DefaultClientTlsStrategy(sslContext, hostnameVerifier);
133126
}
134-
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory> create()
135-
.register("http", PlainConnectionSocketFactory.getSocketFactory())
136-
.register("https", sslConnectionSocketFactory)
137-
.build();
138-
connectionPoolManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry, connFactory);
127+
builder.setTlsSocketStrategy(tlsStrategy);
139128
}
129+
130+
connectionPoolManager = builder.build();
140131
connectionPoolManager.setMaxTotal(connectionPoolMaxSize);
141132
connectionPoolManager.setDefaultSocketConfig(
142133
SocketConfig.copy(SocketConfig.DEFAULT)
@@ -156,7 +147,7 @@ public ManagedHttpClientConnection createConnection(final Socket socket) throws
156147
}
157148
}
158149
if (AS2Header.KEEP_ALIVE.equalsIgnoreCase(h.getName())) {
159-
HeaderElement headerElement = MessageSupport.parse(h)[0];
150+
HeaderElement headerElement = MessageSupport.parseElements(h).get(0);
160151
if (headerElement.getValue() != null && "timeout".equalsIgnoreCase(headerElement.getName())) {
161152
ttl = TimeValue.ofSeconds(Long.parseLong(headerElement.getValue()));
162153
}
@@ -197,17 +188,18 @@ public HttpResponse send(ClassicHttpRequest request, HttpCoreContext httpContext
197188
connectionPoolManager.connect(endpoint, TimeValue.ofMilliseconds(connectionTimeoutMilliseconds), httpContext);
198189
}
199190
// Execute Request
200-
HttpRequestExecutor httpExecutor = new HttpRequestExecutor() {
191+
ConnectionEndpoint.RequestExecutor requestExecutor = new ConnectionEndpoint.RequestExecutor() {
201192
@Override
202193
public ClassicHttpResponse execute(ClassicHttpRequest request, HttpClientConnection conn, HttpContext context)
203194
throws IOException, HttpException {
204-
super.preProcess(request, httpProcessor, context);
205-
ClassicHttpResponse response = super.execute(request, conn, context);
206-
super.postProcess(response, httpProcessor, context);
195+
HttpRequestExecutor executor = new HttpRequestExecutor();
196+
executor.preProcess(request, httpProcessor, context);
197+
ClassicHttpResponse response = executor.execute(request, conn, context);
198+
executor.postProcess(response, httpProcessor, context);
207199
return response;
208200
}
209201
};
210-
response = endpoint.execute(UUID.randomUUID().toString(), request, httpExecutor, httpContext);
202+
response = endpoint.execute(UUID.randomUUID().toString(), request, requestExecutor, httpContext);
211203
} finally {
212204
if (endpoint != null) {
213205
TimeValue keepAlive = null;

components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/AS2ClientManager.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,12 +86,18 @@ public class AS2ClientManager {
8686

8787
/**
8888
* The HTTP Context Attribute containing the HTTP request message transporting the EDI message
89+
*
90+
* @deprecated Use getter method from HttpContext implementation.
8991
*/
92+
@Deprecated
9093
public static final String HTTP_REQUEST = HttpCoreContext.HTTP_REQUEST;
9194

9295
/**
9396
* The HTTP Context Attribute containing the HTTP response message transporting the EDI message
97+
*
98+
* @deprecated Use getter method from HttpContext implementation.
9499
*/
100+
@Deprecated
95101
public static final String HTTP_RESPONSE = HttpCoreContext.HTTP_RESPONSE;
96102

97103
/**
@@ -272,7 +278,7 @@ public HttpCoreContext send(
272278

273279
BasicClassicHttpRequest request = new BasicClassicHttpRequest("POST", requestUri);
274280
request.setVersion(new ProtocolVersion("HTTP", 1, 1));
275-
httpContext.setAttribute(HTTP_REQUEST, request);
281+
httpContext.setRequest(request);
276282

277283
// Create Message Body
278284
ApplicationEntity applicationEntity;
@@ -346,7 +352,7 @@ public HttpCoreContext send(
346352
}
347353

348354
final HttpResponse response = sendRequest(httpContext, request);
349-
httpContext.setAttribute(HTTP_RESPONSE, response);
355+
httpContext.setResponse(response);
350356
return httpContext;
351357
}
352358

components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/AS2Constants.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,10 @@ public interface AS2Constants {
4949

5050
/**
5151
* HTTP Context Attribute Name for HTTP Client Connection object stored in context.
52+
*
53+
* @deprecated Use getter method from HttpContext implementation.
5254
*/
55+
@Deprecated
5356
String HTTP_CLIENT_CONNECTION = HttpCoreContext.CONNECTION_ENDPOINT;
5457

5558
/**

components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/AS2ServerConnection.java

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -49,16 +49,15 @@
4949
import org.apache.hc.core5.http.HttpRequestInterceptor;
5050
import org.apache.hc.core5.http.config.Http1Config;
5151
import org.apache.hc.core5.http.impl.io.HttpService;
52+
import org.apache.hc.core5.http.impl.routing.RequestRouter;
5253
import org.apache.hc.core5.http.io.HttpRequestHandler;
5354
import org.apache.hc.core5.http.io.HttpServerConnection;
5455
import org.apache.hc.core5.http.io.HttpServerRequestHandler;
5556
import org.apache.hc.core5.http.io.support.BasicHttpServerRequestHandler;
56-
import org.apache.hc.core5.http.protocol.BasicHttpContext;
5757
import org.apache.hc.core5.http.protocol.HttpContext;
5858
import org.apache.hc.core5.http.protocol.HttpCoreContext;
5959
import org.apache.hc.core5.http.protocol.HttpProcessor;
6060
import org.apache.hc.core5.http.protocol.HttpProcessorBuilder;
61-
import org.apache.hc.core5.http.protocol.RequestHandlerRegistry;
6261
import org.apache.hc.core5.http.protocol.ResponseConnControl;
6362
import org.apache.hc.core5.http.protocol.ResponseContent;
6463
import org.apache.hc.core5.http.protocol.ResponseDate;
@@ -371,7 +370,22 @@ public void process(HttpRequest request, EntityDetails entityDetails, HttpContex
371370
class RequestListenerService {
372371

373372
private final HttpService httpService;
374-
private final RequestHandlerRegistry registry;
373+
private final Map<String, HttpRequestHandler> routeMap = new LinkedHashMap<>();
374+
private volatile HttpServerRequestHandler currentHandler;
375+
376+
/**
377+
* Delegating handler that always forwards to the current handler. This allows us to update the routing
378+
* configuration dynamically.
379+
*/
380+
private class DelegatingRequestHandler implements HttpServerRequestHandler {
381+
@Override
382+
public void handle(
383+
ClassicHttpRequest request, HttpServerRequestHandler.ResponseTrigger responseTrigger,
384+
HttpContext context)
385+
throws HttpException, IOException {
386+
currentHandler.handle(request, responseTrigger, context);
387+
}
388+
}
375389

376390
public RequestListenerService(String as2Version,
377391
String originServer,
@@ -384,20 +398,32 @@ public RequestListenerService(String as2Version,
384398
as2Version, originServer, serverFqdn,
385399
mdnMessageTemplate);
386400

387-
registry = new RequestHandlerRegistry<>();
388-
HttpServerRequestHandler handler = new BasicHttpServerRequestHandler(registry);
401+
// Create initial empty router
402+
currentHandler = createHandler();
403+
404+
// Set up the HTTP service with delegating handler
405+
httpService = new HttpService(inhttpproc, new DelegatingRequestHandler());
406+
}
389407

390-
// Set up the HTTP service
391-
httpService = new HttpService(inhttpproc, handler);
408+
private HttpServerRequestHandler createHandler() {
409+
RequestRouter.Builder<HttpRequestHandler> builder = RequestRouter.builder();
410+
// Use LOCAL_AUTHORITY_RESOLVER to match any host
411+
builder.resolveAuthority(RequestRouter.LOCAL_AUTHORITY_RESOLVER);
412+
for (Map.Entry<String, HttpRequestHandler> entry : routeMap.entrySet()) {
413+
builder.addRoute(RequestRouter.LOCAL_AUTHORITY, entry.getKey(), entry.getValue());
414+
}
415+
return new BasicHttpServerRequestHandler(builder.build());
392416
}
393417

394418
void registerHandler(String requestUriPattern, HttpRequestHandler httpRequestHandler) {
395-
registry.register(null, requestUriPattern, httpRequestHandler);
419+
routeMap.put(requestUriPattern, httpRequestHandler);
420+
currentHandler = createHandler();
396421
}
397422

398423
void unregisterHandler(String requestUriPattern) {
399424
// we cannot remove from http registry, but we can replace with a not found to simulate 404
400-
registry.register(null, requestUriPattern, new NotFoundHttpRequestHandler());
425+
routeMap.put(requestUriPattern, new NotFoundHttpRequestHandler());
426+
currentHandler = createHandler();
401427
}
402428
}
403429

@@ -465,14 +491,14 @@ public RequestHandlerThread(HttpService httpService, Socket inSocket) throws IOE
465491
@Override
466492
public void run() {
467493
LOG.info("Processing new AS2 request");
468-
final HttpContext context = new BasicHttpContext(null);
494+
final HttpContext context = HttpCoreContext.create();
469495

470496
try {
471497
while (!Thread.interrupted()) {
472498

473499
this.httpService.handleRequest(this.serverConnection, context);
474500

475-
HttpCoreContext coreContext = HttpCoreContext.adapt(context);
501+
HttpCoreContext coreContext = HttpCoreContext.castOrCreate(context);
476502

477503
// Safely retrieve the AS2 consumer configuration and path from ThreadLocal storage.
478504
AS2ConsumerConfiguration config = Optional.ofNullable(CURRENT_CONSUMER_CONFIG.get())
@@ -498,13 +524,12 @@ public void run() {
498524
AS2ServerConnection.this.password,
499525
AS2ServerConnection.this.accessToken);
500526

501-
HttpRequest request = coreContext.getAttribute(HttpCoreContext.HTTP_REQUEST, HttpRequest.class);
527+
HttpRequest request = coreContext.getRequest();
502528
AS2SignedDataGenerator gen = ResponseMDN.createSigningGenerator(
503529
request,
504530
config.getSigningAlgorithm(),
505531
config.getSigningCertificateChain(),
506532
config.getSigningPrivateKey());
507-
508533
if (gen != null) {
509534
// send a signed MDN
510535
MultipartSignedEntity multipartSignedEntity = null;

components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/protocol/RequestAS2.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public RequestAS2(String as2Version, String clientFQDN) {
4444
@Override
4545
public void process(HttpRequest request, EntityDetails entity, HttpContext context) throws HttpException, IOException {
4646

47-
HttpCoreContext coreContext = HttpCoreContext.adapt(context);
47+
HttpCoreContext coreContext = HttpCoreContext.castOrCreate(context);
4848

4949
/* MIME header */
5050
request.addHeader(AS2Header.MIME_VERSION, AS2Constants.MIME_VERSION);

0 commit comments

Comments
 (0)