You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2024/12/31 15:06:15 UTC
(camel) branch mllp2 created (now 3d3db6aed51)
This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a change to branch mllp2
in repository https://gitbox.apache.org/repos/asf/camel.git
at 3d3db6aed51 CAMEL-17881: camel-mllp - Add TLS support
This branch includes the following new commits:
new 3d3db6aed51 CAMEL-17881: camel-mllp - Add TLS support
The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
(camel) 01/01: CAMEL-17881: camel-mllp - Add TLS support
Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch mllp2
in repository https://gitbox.apache.org/repos/asf/camel.git
commit 3d3db6aed51252f9bb9c3839f42de78055e38cc1
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Tue Dec 31 16:05:41 2024 +0100
CAMEL-17881: camel-mllp - Add TLS support
updated mllp config with sslcontextparameters
Added ssl compatibility to mllpendpoint class and mllptcpclientproducer class
updated serverconsumer and tcpserverbinthread for ssl
Added aoutogenerated configfiles. Fixed rebaseconflict in tcpserverbindthread and mllpconfiguration
fixed portbind issue in tcpserverbinthread class
Added endpoint test with sslcontextparemeters
removed old sslContext testclasses and added new one
added test for sslcontextparemeters and added testcert
removed throws declaration that was not needed
fixed some checkstyle issues
committing autogenerated files
added useglobalsslcontextparameters as an option for component and added a test for it. Also removed outcommented version in pom
---
.../org/apache/camel/catalog/components/mllp.json | 7 +-
components/camel-mllp/LIMITATIONS.md | 28 +-
components/camel-mllp/README.md | 128 +-
components/camel-mllp/pom.xml | 3 +-
.../component/mllp/MllpComponentConfigurer.java | 12 +
.../component/mllp/MllpEndpointConfigurer.java | 6 +
.../component/mllp/MllpEndpointUriFactory.java | 3 +-
.../org/apache/camel/component/mllp/mllp.json | 7 +-
.../camel-mllp/src/main/docs/mllp-component.adoc | 1 -
.../apache/camel/component/mllp/MllpComponent.java | 22 +-
.../camel/component/mllp/MllpConfiguration.java | 59 +-
.../apache/camel/component/mllp/MllpConstants.java | 52 +-
.../apache/camel/component/mllp/MllpEndpoint.java | 25 +-
.../component/mllp/MllpTcpClientProducer.java | 1234 ++++++++++----------
.../component/mllp/MllpTcpServerConsumer.java | 2 +-
.../camel/component/mllp/internal/Hl7Util.java | 18 +-
.../mllp/internal/TcpServerBindThread.java | 23 +-
.../MllpAcknowledgementDeliveryExceptionTest.java | 4 -
.../mllp/MllpAcknowledgementExceptionTest.java | 6 -
.../MllpAcknowledgementReceiveExceptionTest.java | 8 -
.../MllpAcknowledgementTimeoutExceptionTest.java | 9 -
...plicationErrorAcknowledgementExceptionTest.java | 3 -
...licationRejectAcknowledgementExceptionTest.java | 3 -
...llpCommitErrorAcknowledgementExceptionTest.java | 3 -
...lpCommitRejectAcknowledgementExceptionTest.java | 3 -
.../camel/component/mllp/MllpEndpointTest.java | 29 +
...pGlobalAndExplicitSSLContextParametersTest.java | 126 ++
.../MllpInvalidAcknowledgementExceptionTest.java | 2 -
.../mllp/MllpInvalidMessageExceptionTest.java | 2 -
.../MllpNegativeAcknowledgementExceptionTest.java | 3 -
.../component/mllp/MllpReceiveExceptionTest.java | 6 -
.../mllp/MllpSSLContextParametersTest.java | 107 ++
.../component/mllp/MllpSocketExceptionTest.java | 2 -
.../component/mllp/MllpWriteExceptionTest.java | 4 -
...tProducerEndOfDataAndValidationTestSupport.java | 1 -
.../camel/component/mllp/internal/Hl7UtilTest.java | 11 -
.../mllp/internal/MllpSocketBufferTest.java | 8 -
.../mllp/internal/MllpSocketBufferWriteTest.java | 13 -
.../test/junit/rule/mllp/MllpClientResource.java | 2 +-
.../test/junit/rule/mllp/MllpServerResource.java | 9 +-
.../camel/test/mllp/PassthroughProcessor.java | 2 +-
.../camel/test/tcp/JavaSocketManualTests.java | 4 +-
.../camel-mllp/src/test/resources/keystore.jks | Bin 0 -> 2762 bytes
.../src/test/resources/log4j2-test.properties | 30 +-
.../template/generated/SSPTParserConstants.java | 134 +--
.../template/generated/SSPTParserTokenManager.java | 126 +-
.../component/dsl/MllpComponentBuilderFactory.java | 39 +
.../endpoint/dsl/MllpEndpointBuilderFactory.java | 114 ++
48 files changed, 1471 insertions(+), 972 deletions(-)
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/mllp.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/mllp.json
index f37df77b40d..88404f1838e 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/mllp.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/mllp.json
@@ -55,7 +55,9 @@
"receiveBufferSize": { "index": 28, "kind": "property", "displayName": "Receive Buffer Size", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "8192", "configurationClass": "org.apache.camel.component.mllp.MllpConfiguration", "configurationField": "configuration", "description": "Sets the SO_RCVBUF option to the specified value (in bytes)" },
"receiveTimeout": { "index": 29, "kind": "property", "displayName": "Receive Timeout", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 15000, "configurationClass": "org.apache.camel.component.mllp.MllpConfiguration", "configurationField": "configuration", "description": "The SO_TIMEOUT value (in milliseconds) used when waiting for the start of an MLLP frame" },
"sendBufferSize": { "index": 30, "kind": "property", "displayName": "Send Buffer Size", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "8192", "configurationClass": "org.apache.camel.component.mllp.MllpConfiguration", "configurationField": "configuration", "description": "Sets the SO_SNDBUF option to the specified value (in bytes)" },
- "idleTimeout": { "index": 31, "kind": "property", "displayName": "Idle Timeout", "group": "tcp", "label": "advanced,tcp", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.mllp.MllpConfiguration", "configurationField": "configuration", "description": "The approximate idle time allowed before the Client TCP Connection will be reset. A null value or a value l [...]
+ "sslContextParameters": { "index": 31, "kind": "property", "displayName": "Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "object", "javaType": "org.apache.camel.support.jsse.SSLContextParameters", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.mllp.MllpConfiguration", "configurationField": "configuration", "description": "Sets the SSLContextParameters for securing TCP connecti [...]
+ "useGlobalSslContextParameters": { "index": 32, "kind": "property", "displayName": "Use Global Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable usage of global SSL context parameters." },
+ "idleTimeout": { "index": 33, "kind": "property", "displayName": "Idle Timeout", "group": "tcp", "label": "advanced,tcp", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.mllp.MllpConfiguration", "configurationField": "configuration", "description": "The approximate idle time allowed before the Client TCP Connection will be reset. A null value or a value l [...]
},
"headers": {
"CamelMllpLocalAddress": { "index": 0, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The local TCP Address of the Socket", "constantName": "org.apache.camel.component.mllp.MllpConstants#MLLP_LOCAL_ADDRESS" },
@@ -107,6 +109,7 @@
"receiveBufferSize": { "index": 26, "kind": "parameter", "displayName": "Receive Buffer Size", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "8192", "configurationClass": "org.apache.camel.component.mllp.MllpConfiguration", "configurationField": "configuration", "description": "Sets the SO_RCVBUF option to the specified value (in bytes)" },
"receiveTimeout": { "index": 27, "kind": "parameter", "displayName": "Receive Timeout", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 15000, "configurationClass": "org.apache.camel.component.mllp.MllpConfiguration", "configurationField": "configuration", "description": "The SO_TIMEOUT value (in milliseconds) used when waiting for the start of an MLLP frame" },
"sendBufferSize": { "index": 28, "kind": "parameter", "displayName": "Send Buffer Size", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "8192", "configurationClass": "org.apache.camel.component.mllp.MllpConfiguration", "configurationField": "configuration", "description": "Sets the SO_SNDBUF option to the specified value (in bytes)" },
- "idleTimeout": { "index": 29, "kind": "parameter", "displayName": "Idle Timeout", "group": "tcp", "label": "advanced,tcp", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.mllp.MllpConfiguration", "configurationField": "configuration", "description": "The approximate idle time allowed before the Client TCP Connection will be reset. A null value or a value [...]
+ "sslContextParameters": { "index": 29, "kind": "parameter", "displayName": "Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "object", "javaType": "org.apache.camel.support.jsse.SSLContextParameters", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.mllp.MllpConfiguration", "configurationField": "configuration", "description": "Sets the SSLContextParameters for securing TCP connect [...]
+ "idleTimeout": { "index": 30, "kind": "parameter", "displayName": "Idle Timeout", "group": "tcp", "label": "advanced,tcp", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.mllp.MllpConfiguration", "configurationField": "configuration", "description": "The approximate idle time allowed before the Client TCP Connection will be reset. A null value or a value [...]
}
}
diff --git a/components/camel-mllp/LIMITATIONS.md b/components/camel-mllp/LIMITATIONS.md
index b7d906ec7f2..b2e52f866c3 100644
--- a/components/camel-mllp/LIMITATIONS.md
+++ b/components/camel-mllp/LIMITATIONS.md
@@ -13,19 +13,21 @@ maxConnections are not enforced yet - an unlimited number of connections are all
Suspending a MLLP Consumer is not yet implemented
JMX Instrumentation is not yet implemented
- - Manually reset connection
- - Suspend a consumer
+
+- Manually reset connection
+- Suspend a consumer
MLLP Statistics are not yet implemented
- TCP Server
- - last message received time
- - last AA sent time
- - last AE sent time
- - last AR sent time
+TCP Server
+- last message received time
+- last AA sent time
+- last AE sent time
+- last AR sent time
+- AA, AE & AR counts
+
+- last message sent time
+ - last message sent time
+ - last AA received time
+ - last AE received time
+ - last AR received time
- AA, AE & AR counts
- - last message sent time
- - last message sent time
- - last AA received time
- - last AE received time
- - last AR received time
- - AA, AE & AR counts
diff --git a/components/camel-mllp/README.md b/components/camel-mllp/README.md
index 9983e634308..99068d92566 100644
--- a/components/camel-mllp/README.md
+++ b/components/camel-mllp/README.md
@@ -1,123 +1,141 @@
# camel-mllp
+
Camel MLLP Component
See MLLP Specification here:
http://www.hl7.org/documentcenter/public_temp_E7494E36-1C23-BA17-0C5E72EF77542E1F/wg/inm/mllp_transport_specification.PDF
# Description
+
The camel-mllp component is specifically designed to handle the nuances of the MLLP protocol and provide
the functionality required by Healthcare providers to communicate with other systems using the MLLP protocol.
The component uses byte[] payloads, and relies on the Camel type conversion system for converting other payload
-types to/from byte[]. This allows using other HL7 Libraries (i.e. HAPI) to parse the messages. The component
+types to/from byte[]. This allows using other HL7 Libraries (i.e. HAPI) to parse the messages. The component
provides a 'charset' URI option that will cause the endpoint to set the CamelCharsetName property on the exchange
which allows the proper conversion of byte[] to String payloads for Consumers.
The component provides a simple URI for configuring MLLP endpoints:
MLLP-Producers:
- to( "mllp://<host or ip>:<port>" )
+to( "mllp://<host or ip>:<port>" )
MLLP-Consumers:
- from("mllp://<host or ip>:<listening port>) to listen on a specific address
- from("mllp://port") to listen on all local addresses
+from("mllp://<host or ip>:<listening port>) to listen on a specific address
+from("mllp://port") to listen on all local addresses
-MLLP-Producers also interrogate the HL7 Acknowledgment received from the external system and if a negative acknowledgment
+MLLP-Producers also interrogate the HL7 Acknowledgment received from the external system and if a negative
+acknowledgment
is received, the producer sets an exception on the exchange indicating the type of negative acknowledgement that was
-received (i.e. a HL7 Application Reject Acknowledgement, Application Error Acknowledgement,
-Commit Reject Acknowledgement and Commit Error Acknowledgement). This enables the use of Camel Redelivery
+received (i.e. a HL7 Application Reject Acknowledgement, Application Error Acknowledgement,
+Commit Reject Acknowledgement and Commit Error Acknowledgement). This enables the use of Camel Redelivery
Policies to configure redelivery attempts and routing erroneous messages to alternate endpoints for analysis.
-MLLP-Consumers will, by default, automatically generate an acknowledgement. A HL7 Application Accept Acknowledgment
-will be generated for successfully processed messages, or a HL7 Application Error Acknowledgement for messages where an
-exception is raised during the processing of the exchange. The HL7 acknowledgement can also be specified by setting the
+MLLP-Consumers will, by default, automatically generate an acknowledgement. A HL7 Application Accept Acknowledgment
+will be generated for successfully processed messages, or a HL7 Application Error Acknowledgement for messages where an
+exception is raised during the processing of the exchange. The HL7 acknowledgement can also be specified by setting the
CamelMllpAcknowledgement property on the exchange - if present, the value of this property will be used for the HL7
-acknowledgment. The automatic generation of an HL7 acknowledgment can be completely disabled by setting the autoAck
-URI parameter to false. If autoAck=false and the CamelMllpAcknowledgment property is not set on the exchange, and
+acknowledgment. The automatic generation of an HL7 acknowledgment can be completely disabled by setting the autoAck
+URI parameter to false. If autoAck=false and the CamelMllpAcknowledgment property is not set on the exchange, and
exception will be raised.
-The component also provides a Camel Processor that is capable of generating HL7 Acknowledgements. Therefore, the HAPI
+The component also provides a Camel Processor that is capable of generating HL7 Acknowledgements. Therefore, the HAPI
is not required to generate HL7 Acknowledgements - however, it can be used if desired.
-By default, the processor will generate a HL7 Application Accept Acknowledgement if there is not an exception on the
-Camel Exchange - otherwise it will generate a HL7 Application Error Acknowledgement. The generated acknowledgement
+By default, the processor will generate a HL7 Application Accept Acknowledgement if there is not an exception on the
+Camel Exchange - otherwise it will generate a HL7 Application Error Acknowledgement. The generated acknowledgement
is placed in the CamelMllpAcknowledgment property on the Exchange.
-Regardless of whether the HL7 Acknowledgment is generated or specified using the CamelMllpAcknowledgement Exchange property,
-the MLLP-Consumer will set the CamelHllpAcknowledgement and CamelHllpAcknowledgementCode headers on the Message after the
-acknowledgment is successfully transmitted to the external system.
+Regardless of whether the HL7 Acknowledgment is generated or specified using the CamelMllpAcknowledgement Exchange
+property,
+the MLLP-Consumer will set the CamelHllpAcknowledgement and CamelHllpAcknowledgementCode headers on the Message after
+the
+acknowledgment is successfully transmitted to the external system.
Since the MLLP protocol does not typically use a large number of concurrent connections, the camel-mllp component uses
-a simple thread-per-connection model based an standard Java Sockets. This keeps the implementation simple, and also
+a simple thread-per-connection model based an standard Java Sockets. This keeps the implementation simple, and also
eliminates the dependencies on other camel components.
-
+
# Rationalization
+
While Camel already includes some of this functionality in the camel-hl7 component, the implementation does not
provide all of the functionality required to effectively handle the MLLP protocol - especially under adverse conditions.
-
+
The camel-hl7 Mina codec and Netty decoder do not handle MLLP Framing errors very well - the component will hang waiting
for frames to complete in some instances.
-While both camel-mina and camel-netty provide a "timeout" function, it is only applied to Producers. MLLP Consumers
-also need to be able to timeout to recover from MLLP framing errors. Additionally, the timeout functionality of the
+While both camel-mina and camel-netty provide a "timeout" function, it is only applied to Producers. MLLP Consumers
+also need to be able to timeout to recover from MLLP framing errors. Additionally, the timeout functionality of the
camel-netty component is disable after any data is received on the connection, making in ineffective for detecting
timeouts after the first messages is received.
-Also, neither the Mina codec nor the Netty decoder interrogate HL7 Acknowledgments. Therefore, it is much more
+Also, neither the Mina codec nor the Netty decoder interrogate HL7 Acknowledgments. Therefore, it is much more
difficult to use the redelivery and error handling features Camel provides.
The above issues may be addressable by updating/patching the existing components, but there is one more that is not.
-Both camel-netty and camel-mina are designed to handle a large number of concurrent connections, rapid connect/disconnect
-rates, and asynchronous communication. Forcing, these components to deal with the small number of stateful connections
+Both camel-netty and camel-mina are designed to handle a large number of concurrent connections, rapid
+connect/disconnect
+rates, and asynchronous communication. Forcing, these components to deal with the small number of stateful connections
inherent to the MLLP protocol seems inappropriate.
-An attempt was made to update the camel-netty decoder provided by the camel-hl7 component to deal with the nuances of
-the MLLP protocol, but it quickly became very complicated. The decoder was updated to correctly deal with the MLLP
-frame. The current implementation is based on the Netty DelimiterBasedFrameDecoder, but this decoder only looks for a
-single byte terminator and MLLP uses two bytes to terminate it's frame. Additionally, the second terminating byte of the
+An attempt was made to update the camel-netty decoder provided by the camel-hl7 component to deal with the nuances of
+the MLLP protocol, but it quickly became very complicated. The decoder was updated to correctly deal with the MLLP
+frame. The current implementation is based on the Netty DelimiterBasedFrameDecoder, but this decoder only looks for a
+single byte terminator and MLLP uses two bytes to terminate it's frame. Additionally, the second terminating byte of the
MLLP frame can't be used alone because that byte is also contained in HL7 messages (it is the HL7 Segment Delimiter).
-An implementation resembling the Netty LineBasedFrameDecoder was written at it correctly handled the MLLP framing issues,
+An implementation resembling the Netty LineBasedFrameDecoder was written at it correctly handled the MLLP framing
+issues,
but the timout issues were never addressed.
-For MLLP Consumers, the decoder needs to dynamically install a timeout handler whenver a partial MLLP frame is received,
-and then remove it when the frame is completed. For MLLP Producers, the decoder would need to install a timeout handler
-at some point to enable detecting a missing acknowledgement in addition to the timeout handler to deal with the
+For MLLP Consumers, the decoder needs to dynamically install a timeout handler whenver a partial MLLP frame is received,
+and then remove it when the frame is completed. For MLLP Producers, the decoder would need to install a timeout handler
+at some point to enable detecting a missing acknowledgement in addition to the timeout handler to deal with the
partial/incomplete acknowledgement.
# MLLP Background
+
The MLLP protocol is inherently synchronous because external systems almost always require the order of messages to be
maintained (i.e. FIFO delivery).
-When a MLLP-Producer sends a message to an external system, it is required to wait for
-an HL7 Acknowledgement before sending the next message. Additionally, the content of the acknowlegement must be examined
-to determine the specific type of the acknowlegement before the next message can be transmitted. If the acknowledgement
-is a HL7 Application Error Acknowledgement, the MLLP-Producer should retransmit the message a few times (the number of
-redelivery attempts is application specific). If the acknowledgment is a HL7 Application Reject Acknowledgement, there
-is something wrong with the message and redelivery will never succeed. The HL7 Messages acknowledged with an HL7 Application
+When a MLLP-Producer sends a message to an external system, it is required to wait for
+an HL7 Acknowledgement before sending the next message. Additionally, the content of the acknowlegement must be examined
+to determine the specific type of the acknowlegement before the next message can be transmitted. If the acknowledgement
+is a HL7 Application Error Acknowledgement, the MLLP-Producer should retransmit the message a few times (the number of
+redelivery attempts is application specific). If the acknowledgment is a HL7 Application Reject Acknowledgement, there
+is something wrong with the message and redelivery will never succeed. The HL7 Messages acknowledged with an HL7
+Application
Reject Acknowledgement must be routed to an alternate destination to allow users to investigate the nature of the error
so it can be corrected.
-When a MLLP-Consumer receives a message from an external system, the sending system is required to wait for an HL7 Acknowledgement
-before transmitting the next message. The MLLP-Consumer normally persists the message in a durable store and then replies
-to the sending system with a HL7 Application Accept Acknowledgement. If a transient error occurs while persisting the
-message, the MLLP-Consumer should reply with a HL7 Application Error Acknowledgment and allow the external system to resend
-the message. If the MLLP-Consumer detects the that the received message is invalid for some reason and the message could
+When a MLLP-Consumer receives a message from an external system, the sending system is required to wait for an HL7
+Acknowledgement
+before transmitting the next message. The MLLP-Consumer normally persists the message in a durable store and then
+replies
+to the sending system with a HL7 Application Accept Acknowledgement. If a transient error occurs while persisting the
+message, the MLLP-Consumer should reply with a HL7 Application Error Acknowledgment and allow the external system to
+resend
+the message. If the MLLP-Consumer detects the that the received message is invalid for some reason and the message could
never be processed, it should reply with an HL7 Application Reject Acknowledgement and the sending system should not
attempt to resend the message.
NOTE: Some external systems do not handle HL7 NACKS ( HL7 Application Reject Acknowledgments and HL7 Application Error
-Acknowledgements) - they do not interrogate the HL7 Acknowledgment to determine if it is a negative acknowledgement and
-assume any acknowledgement received is an HL7 ACK (HL7 Application Accept Acknowledgement). In order to prevent message
-loss when dealing with external systems that behave in this fashion, the MLLP-Consumer must be capable of closing the
-TCP connection in lew of sending and HL7 NACK, which will force the external system to resend the message. Additionally,
-the MLLP-Consumer may be required to behave differently for each type of HL7 NACK - it may need to close the TCP connection
-instead of sending HL7 Application Error Acknowledgements, and route the messages that would be normally not be persisted
+Acknowledgements) - they do not interrogate the HL7 Acknowledgment to determine if it is a negative acknowledgement and
+assume any acknowledgement received is an HL7 ACK (HL7 Application Accept Acknowledgement). In order to prevent message
+loss when dealing with external systems that behave in this fashion, the MLLP-Consumer must be capable of closing the
+TCP connection in lew of sending and HL7 NACK, which will force the external system to resend the message. Additionally,
+the MLLP-Consumer may be required to behave differently for each type of HL7 NACK - it may need to close the TCP
+connection
+instead of sending HL7 Application Error Acknowledgements, and route the messages that would be normally not be
+persisted
to an alternate durable store before sending the HL7 Application Reject acknowledgement.
-Systems using the MLLP protocol normally use stateful TCP connections - the connections are established and left open
+Systems using the MLLP protocol normally use stateful TCP connections - the connections are established and left open
for extended periods of time.
-A MLLP-Consumer endpoint may have more than one TCP connection at a given time, but this is not the typical case. Normally
+A MLLP-Consumer endpoint may have more than one TCP connection at a given time, but this is not the typical case.
+Normally
there is a single active TCP connection to a MLLP-Consumer.
-A MLLP-Producer endpoint should only have a single TCP connection at any given time. If the producer attempts to open more
-than one connection to an external system, it oftentimes causes issues with the external system. Additionally, since FIFO
+A MLLP-Producer endpoint should only have a single TCP connection at any given time. If the producer attempts to open
+more
+than one connection to an external system, it oftentimes causes issues with the external system. Additionally, since
+FIFO
must be maintained, only
diff --git a/components/camel-mllp/pom.xml b/components/camel-mllp/pom.xml
index eeef3f66a9e..ff52f0fd96c 100644
--- a/components/camel-mllp/pom.xml
+++ b/components/camel-mllp/pom.xml
@@ -17,7 +17,8 @@
limitations under the License.
-->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
diff --git a/components/camel-mllp/src/generated/java/org/apache/camel/component/mllp/MllpComponentConfigurer.java b/components/camel-mllp/src/generated/java/org/apache/camel/component/mllp/MllpComponentConfigurer.java
index 5205b93d71c..e65d211696a 100644
--- a/components/camel-mllp/src/generated/java/org/apache/camel/component/mllp/MllpComponentConfigurer.java
+++ b/components/camel-mllp/src/generated/java/org/apache/camel/component/mllp/MllpComponentConfigurer.java
@@ -86,10 +86,14 @@ public class MllpComponentConfigurer extends PropertyConfigurerSupport implement
case "reuseAddress": getOrCreateConfiguration(target).setReuseAddress(property(camelContext, java.lang.Boolean.class, value)); return true;
case "sendbuffersize":
case "sendBufferSize": getOrCreateConfiguration(target).setSendBufferSize(property(camelContext, java.lang.Integer.class, value)); return true;
+ case "sslcontextparameters":
+ case "sslContextParameters": getOrCreateConfiguration(target).setSslContextParameters(property(camelContext, org.apache.camel.support.jsse.SSLContextParameters.class, value)); return true;
case "stringpayload":
case "stringPayload": getOrCreateConfiguration(target).setStringPayload(property(camelContext, boolean.class, value)); return true;
case "tcpnodelay":
case "tcpNoDelay": getOrCreateConfiguration(target).setTcpNoDelay(property(camelContext, java.lang.Boolean.class, value)); return true;
+ case "useglobalsslcontextparameters":
+ case "useGlobalSslContextParameters": target.setUseGlobalSslContextParameters(property(camelContext, boolean.class, value)); return true;
case "validatepayload":
case "validatePayload": getOrCreateConfiguration(target).setValidatePayload(property(camelContext, boolean.class, value)); return true;
default: return false;
@@ -155,10 +159,14 @@ public class MllpComponentConfigurer extends PropertyConfigurerSupport implement
case "reuseAddress": return java.lang.Boolean.class;
case "sendbuffersize":
case "sendBufferSize": return java.lang.Integer.class;
+ case "sslcontextparameters":
+ case "sslContextParameters": return org.apache.camel.support.jsse.SSLContextParameters.class;
case "stringpayload":
case "stringPayload": return boolean.class;
case "tcpnodelay":
case "tcpNoDelay": return java.lang.Boolean.class;
+ case "useglobalsslcontextparameters":
+ case "useGlobalSslContextParameters": return boolean.class;
case "validatepayload":
case "validatePayload": return boolean.class;
default: return null;
@@ -225,10 +233,14 @@ public class MllpComponentConfigurer extends PropertyConfigurerSupport implement
case "reuseAddress": return getOrCreateConfiguration(target).getReuseAddress();
case "sendbuffersize":
case "sendBufferSize": return getOrCreateConfiguration(target).getSendBufferSize();
+ case "sslcontextparameters":
+ case "sslContextParameters": return getOrCreateConfiguration(target).getSslContextParameters();
case "stringpayload":
case "stringPayload": return getOrCreateConfiguration(target).isStringPayload();
case "tcpnodelay":
case "tcpNoDelay": return getOrCreateConfiguration(target).getTcpNoDelay();
+ case "useglobalsslcontextparameters":
+ case "useGlobalSslContextParameters": return target.isUseGlobalSslContextParameters();
case "validatepayload":
case "validatePayload": return getOrCreateConfiguration(target).isValidatePayload();
default: return null;
diff --git a/components/camel-mllp/src/generated/java/org/apache/camel/component/mllp/MllpEndpointConfigurer.java b/components/camel-mllp/src/generated/java/org/apache/camel/component/mllp/MllpEndpointConfigurer.java
index 5e538db3ede..f4a0418d52e 100644
--- a/components/camel-mllp/src/generated/java/org/apache/camel/component/mllp/MllpEndpointConfigurer.java
+++ b/components/camel-mllp/src/generated/java/org/apache/camel/component/mllp/MllpEndpointConfigurer.java
@@ -72,6 +72,8 @@ public class MllpEndpointConfigurer extends PropertyConfigurerSupport implements
case "reuseAddress": target.getConfiguration().setReuseAddress(property(camelContext, java.lang.Boolean.class, value)); return true;
case "sendbuffersize":
case "sendBufferSize": target.getConfiguration().setSendBufferSize(property(camelContext, java.lang.Integer.class, value)); return true;
+ case "sslcontextparameters":
+ case "sslContextParameters": target.getConfiguration().setSslContextParameters(property(camelContext, org.apache.camel.support.jsse.SSLContextParameters.class, value)); return true;
case "stringpayload":
case "stringPayload": target.getConfiguration().setStringPayload(property(camelContext, boolean.class, value)); return true;
case "tcpnodelay":
@@ -134,6 +136,8 @@ public class MllpEndpointConfigurer extends PropertyConfigurerSupport implements
case "reuseAddress": return java.lang.Boolean.class;
case "sendbuffersize":
case "sendBufferSize": return java.lang.Integer.class;
+ case "sslcontextparameters":
+ case "sslContextParameters": return org.apache.camel.support.jsse.SSLContextParameters.class;
case "stringpayload":
case "stringPayload": return boolean.class;
case "tcpnodelay":
@@ -197,6 +201,8 @@ public class MllpEndpointConfigurer extends PropertyConfigurerSupport implements
case "reuseAddress": return target.getConfiguration().getReuseAddress();
case "sendbuffersize":
case "sendBufferSize": return target.getConfiguration().getSendBufferSize();
+ case "sslcontextparameters":
+ case "sslContextParameters": return target.getConfiguration().getSslContextParameters();
case "stringpayload":
case "stringPayload": return target.getConfiguration().isStringPayload();
case "tcpnodelay":
diff --git a/components/camel-mllp/src/generated/java/org/apache/camel/component/mllp/MllpEndpointUriFactory.java b/components/camel-mllp/src/generated/java/org/apache/camel/component/mllp/MllpEndpointUriFactory.java
index fe8958ccf95..d3c63226888 100644
--- a/components/camel-mllp/src/generated/java/org/apache/camel/component/mllp/MllpEndpointUriFactory.java
+++ b/components/camel-mllp/src/generated/java/org/apache/camel/component/mllp/MllpEndpointUriFactory.java
@@ -23,7 +23,7 @@ public class MllpEndpointUriFactory extends org.apache.camel.support.component.E
private static final Set<String> SECRET_PROPERTY_NAMES;
private static final Set<String> MULTI_VALUE_PREFIXES;
static {
- Set<String> props = new HashSet<>(30);
+ Set<String> props = new HashSet<>(31);
props.add("acceptTimeout");
props.add("autoAck");
props.add("backlog");
@@ -51,6 +51,7 @@ public class MllpEndpointUriFactory extends org.apache.camel.support.component.E
props.add("requireEndOfData");
props.add("reuseAddress");
props.add("sendBufferSize");
+ props.add("sslContextParameters");
props.add("stringPayload");
props.add("tcpNoDelay");
props.add("validatePayload");
diff --git a/components/camel-mllp/src/generated/resources/META-INF/org/apache/camel/component/mllp/mllp.json b/components/camel-mllp/src/generated/resources/META-INF/org/apache/camel/component/mllp/mllp.json
index f37df77b40d..88404f1838e 100644
--- a/components/camel-mllp/src/generated/resources/META-INF/org/apache/camel/component/mllp/mllp.json
+++ b/components/camel-mllp/src/generated/resources/META-INF/org/apache/camel/component/mllp/mllp.json
@@ -55,7 +55,9 @@
"receiveBufferSize": { "index": 28, "kind": "property", "displayName": "Receive Buffer Size", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "8192", "configurationClass": "org.apache.camel.component.mllp.MllpConfiguration", "configurationField": "configuration", "description": "Sets the SO_RCVBUF option to the specified value (in bytes)" },
"receiveTimeout": { "index": 29, "kind": "property", "displayName": "Receive Timeout", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 15000, "configurationClass": "org.apache.camel.component.mllp.MllpConfiguration", "configurationField": "configuration", "description": "The SO_TIMEOUT value (in milliseconds) used when waiting for the start of an MLLP frame" },
"sendBufferSize": { "index": 30, "kind": "property", "displayName": "Send Buffer Size", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "8192", "configurationClass": "org.apache.camel.component.mllp.MllpConfiguration", "configurationField": "configuration", "description": "Sets the SO_SNDBUF option to the specified value (in bytes)" },
- "idleTimeout": { "index": 31, "kind": "property", "displayName": "Idle Timeout", "group": "tcp", "label": "advanced,tcp", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.mllp.MllpConfiguration", "configurationField": "configuration", "description": "The approximate idle time allowed before the Client TCP Connection will be reset. A null value or a value l [...]
+ "sslContextParameters": { "index": 31, "kind": "property", "displayName": "Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "object", "javaType": "org.apache.camel.support.jsse.SSLContextParameters", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.mllp.MllpConfiguration", "configurationField": "configuration", "description": "Sets the SSLContextParameters for securing TCP connecti [...]
+ "useGlobalSslContextParameters": { "index": 32, "kind": "property", "displayName": "Use Global Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable usage of global SSL context parameters." },
+ "idleTimeout": { "index": 33, "kind": "property", "displayName": "Idle Timeout", "group": "tcp", "label": "advanced,tcp", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.mllp.MllpConfiguration", "configurationField": "configuration", "description": "The approximate idle time allowed before the Client TCP Connection will be reset. A null value or a value l [...]
},
"headers": {
"CamelMllpLocalAddress": { "index": 0, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The local TCP Address of the Socket", "constantName": "org.apache.camel.component.mllp.MllpConstants#MLLP_LOCAL_ADDRESS" },
@@ -107,6 +109,7 @@
"receiveBufferSize": { "index": 26, "kind": "parameter", "displayName": "Receive Buffer Size", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "8192", "configurationClass": "org.apache.camel.component.mllp.MllpConfiguration", "configurationField": "configuration", "description": "Sets the SO_RCVBUF option to the specified value (in bytes)" },
"receiveTimeout": { "index": 27, "kind": "parameter", "displayName": "Receive Timeout", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 15000, "configurationClass": "org.apache.camel.component.mllp.MllpConfiguration", "configurationField": "configuration", "description": "The SO_TIMEOUT value (in milliseconds) used when waiting for the start of an MLLP frame" },
"sendBufferSize": { "index": 28, "kind": "parameter", "displayName": "Send Buffer Size", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "8192", "configurationClass": "org.apache.camel.component.mllp.MllpConfiguration", "configurationField": "configuration", "description": "Sets the SO_SNDBUF option to the specified value (in bytes)" },
- "idleTimeout": { "index": 29, "kind": "parameter", "displayName": "Idle Timeout", "group": "tcp", "label": "advanced,tcp", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.mllp.MllpConfiguration", "configurationField": "configuration", "description": "The approximate idle time allowed before the Client TCP Connection will be reset. A null value or a value [...]
+ "sslContextParameters": { "index": 29, "kind": "parameter", "displayName": "Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "object", "javaType": "org.apache.camel.support.jsse.SSLContextParameters", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.mllp.MllpConfiguration", "configurationField": "configuration", "description": "Sets the SSLContextParameters for securing TCP connect [...]
+ "idleTimeout": { "index": 30, "kind": "parameter", "displayName": "Idle Timeout", "group": "tcp", "label": "advanced,tcp", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.mllp.MllpConfiguration", "configurationField": "configuration", "description": "The approximate idle time allowed before the Client TCP Connection will be reset. A null value or a value [...]
}
}
diff --git a/components/camel-mllp/src/main/docs/mllp-component.adoc b/components/camel-mllp/src/main/docs/mllp-component.adoc
index c895179754c..c181cc68744 100644
--- a/components/camel-mllp/src/main/docs/mllp-component.adoc
+++ b/components/camel-mllp/src/main/docs/mllp-component.adoc
@@ -121,5 +121,4 @@ The state of the TCP Socket can be controlled by these properties on the Camel e
|`CamelMllpResetConnectionAfterSend` | `Boolean` | If true, the Socket will be reset immediately after sending any data
|====================================
-
include::spring-boot:partial$starter.adoc[]
diff --git a/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpComponent.java b/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpComponent.java
index 45a145d242d..bffd141c42e 100644
--- a/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpComponent.java
+++ b/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpComponent.java
@@ -20,13 +20,14 @@ import java.util.Map;
import org.apache.camel.CamelContext;
import org.apache.camel.Endpoint;
+import org.apache.camel.SSLContextParametersAware;
import org.apache.camel.spi.Metadata;
import org.apache.camel.spi.annotations.Component;
import org.apache.camel.support.CamelContextHelper;
import org.apache.camel.support.DefaultComponent;
@Component("mllp")
-public class MllpComponent extends DefaultComponent {
+public class MllpComponent extends DefaultComponent implements SSLContextParametersAware {
@Metadata(label = "advanced", defaultValue = "true")
private boolean logPhi = true;
@@ -36,6 +37,8 @@ public class MllpComponent extends DefaultComponent {
private String defaultCharset = "ISO_8859_1";
@Metadata
private MllpConfiguration configuration;
+ @Metadata(label = "security", defaultValue = "false")
+ private boolean useGlobalSslContextParameters;
public MllpComponent() {
// bridge error handler by default
@@ -53,6 +56,10 @@ public class MllpComponent extends DefaultComponent {
MllpEndpoint endpoint
= new MllpEndpoint(uriString, this, hasConfiguration() ? configuration.copy() : new MllpConfiguration());
+ if (endpoint.getConfiguration().getSslContextParameters() == null) {
+ endpoint.getConfiguration().setSslContextParameters(retrieveGlobalSslContextParameters());
+ }
+
endpoint.setCharsetName(getDefaultCharset());
// Make sure it has a host - may just be a port
@@ -116,4 +123,17 @@ public class MllpComponent extends DefaultComponent {
public void setConfiguration(MllpConfiguration configuration) {
this.configuration = configuration;
}
+
+ @Override
+ public boolean isUseGlobalSslContextParameters() {
+ return this.useGlobalSslContextParameters;
+ }
+
+ /**
+ * Enable usage of global SSL context parameters.
+ */
+ @Override
+ public void setUseGlobalSslContextParameters(boolean useGlobalSslContextParameters) {
+ this.useGlobalSslContextParameters = useGlobalSslContextParameters;
+ }
}
diff --git a/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpConfiguration.java b/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpConfiguration.java
index 09727227fd3..26c35a3f3d0 100644
--- a/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpConfiguration.java
+++ b/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpConfiguration.java
@@ -21,6 +21,7 @@ import java.util.Objects;
import org.apache.camel.ExchangePattern;
import org.apache.camel.spi.UriParam;
import org.apache.camel.spi.UriParams;
+import org.apache.camel.support.jsse.SSLContextParameters;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -110,6 +111,9 @@ public class MllpConfiguration implements Cloneable {
@UriParam(label = "advanced", defaultValue = "" + 0x40000000)
int maxBufferSize = 0x40000000;
+ @UriParam(label = "security")
+ private SSLContextParameters sslContextParameters;
+
public MllpConfiguration() {
}
@@ -145,6 +149,7 @@ public class MllpConfiguration implements Cloneable {
target.validatePayload = source.validatePayload;
target.charsetName = source.charsetName;
target.maxConcurrentConsumers = source.maxConcurrentConsumers;
+ target.sslContextParameters = source.sslContextParameters;
}
}
@@ -168,7 +173,7 @@ public class MllpConfiguration implements Cloneable {
* Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions occurred while the
* consumer is trying to receive incoming messages, or the likes, will now be processed as a message and handled by
* the routing Error Handler.
- *
+ * <p>
* If disabled, the consumer will use the org.apache.camel.spi.ExceptionHandler to deal with exceptions by logging
* them at WARN or ERROR level and ignored.
*/
@@ -250,7 +255,7 @@ public class MllpConfiguration implements Cloneable {
/**
* TCP Server Only - Allow the endpoint to start before the TCP ServerSocket is bound.
- *
+ * <p>
* In some environments, it may be desirable to allow the endpoint to start before the TCP ServerSocket is bound.
*
* @param lenientBind if true, the ServerSocket will be bound asynchronously; otherwise the ServerSocket will be
@@ -323,7 +328,7 @@ public class MllpConfiguration implements Cloneable {
/**
* The approximate idle time allowed before the Client TCP Connection will be reset.
- *
+ * <p>
* A null value or a value less than or equal to zero will disable the idle timeout.
*
* @param idleTimeout timeout in milliseconds
@@ -436,7 +441,7 @@ public class MllpConfiguration implements Cloneable {
/**
* Enable/Disable the automatic generation of a MLLP Acknowledgement
- *
+ * <p>
* MLLP Consumers only
*
* @param autoAck enabled if true, otherwise disabled
@@ -455,7 +460,7 @@ public class MllpConfiguration implements Cloneable {
/**
* Enable/Disable the automatic generation of message headers from the HL7 Message
- *
+ * <p>
* MLLP Consumers only
*
* @param hl7Headers enabled if true, otherwise disabled
@@ -470,7 +475,7 @@ public class MllpConfiguration implements Cloneable {
/**
* Enable/Disable strict compliance to the MLLP standard.
- *
+ * <p>
* The MLLP standard specifies [START_OF_BLOCK]hl7 payload[END_OF_BLOCK][END_OF_DATA], however, some systems do not
* send the final END_OF_DATA byte. This setting controls whether or not the final END_OF_DATA byte is required or
* optional.
@@ -487,9 +492,9 @@ public class MllpConfiguration implements Cloneable {
/**
* Enable/Disable converting the payload to a String.
- *
+ * <p>
* If enabled, HL7 Payloads received from external systems will be validated converted to a String.
- *
+ * <p>
* If the charsetName property is set, that character set will be used for the conversion. If the charsetName
* property is not set, the value of MSH-18 will be used to determine th appropriate character set. If MSH-18 is not
* set, then the default ISO-8859-1 character set will be use.
@@ -506,7 +511,7 @@ public class MllpConfiguration implements Cloneable {
/**
* Enable/Disable the validation of HL7 Payloads
- *
+ * <p>
* If enabled, HL7 Payloads received from external systems will be validated (see
* Hl7Util.generateInvalidPayloadExceptionMessage for details on the validation). If and invalid payload is
* detected, a MllpInvalidMessageException (for consumers) or a MllpInvalidAcknowledgementException will be thrown.
@@ -523,9 +528,9 @@ public class MllpConfiguration implements Cloneable {
/**
* decide what action to take when idle timeout occurs. Possible values are :
- *
+ * <p>
* RESET: set SO_LINGER to 0 and reset the socket CLOSE: close the socket gracefully
- *
+ * <p>
* default is RESET.
*
* @param idleTimeoutStrategy the strategy to take if idle timeout occurs
@@ -556,6 +561,31 @@ public class MllpConfiguration implements Cloneable {
this.maxBufferSize = maxBufferSize;
}
+ /**
+ * Gets the SSLContextParameters for securing TCP connections.
+ * <p>
+ * Returns the SSLContextParameters that configure SSL/TLS settings for the MLLP component. If null, plain TCP
+ * communication will be used.
+ *
+ * @return the configured SSLContextParameters, or null if not set.
+ */
+ public SSLContextParameters getSslContextParameters() {
+ return sslContextParameters;
+ }
+
+ /**
+ * Sets the SSLContextParameters for securing TCP connections.
+ * <p>
+ * If set, the MLLP component will use SSL/TLS for securing both producer and consumer TCP connections. This allows
+ * the configuration of trust stores, key stores, protocols, and other SSL/TLS settings. If not set, the MLLP
+ * component will use plain TCP communication.
+ *
+ * @param sslContextParameters the SSLContextParameters to use for secure connections.
+ */
+ public void setSslContextParameters(SSLContextParameters sslContextParameters) {
+ this.sslContextParameters = sslContextParameters;
+ }
+
@Override
public int hashCode() {
return Objects.hash(bridgeErrorHandler,
@@ -582,7 +612,8 @@ public class MllpConfiguration implements Cloneable {
validatePayload,
charsetName,
minBufferSize,
- maxBufferSize);
+ maxBufferSize,
+ sslContextParameters);
}
@Override
@@ -621,7 +652,8 @@ public class MllpConfiguration implements Cloneable {
&& Objects.equals(reuseAddress, rhs.reuseAddress)
&& Objects.equals(receiveBufferSize, rhs.receiveBufferSize)
&& Objects.equals(sendBufferSize, rhs.sendBufferSize)
- && Objects.equals(charsetName, rhs.charsetName);
+ && Objects.equals(charsetName, rhs.charsetName)
+ && Objects.equals(sslContextParameters, rhs.sslContextParameters);
}
@Override
@@ -652,6 +684,7 @@ public class MllpConfiguration implements Cloneable {
+ ", minBufferSize=" + minBufferSize
+ ", maxBufferSize=" + maxBufferSize
+ ", charsetName='" + charsetName + '\''
+ + ", sslContextParameters=" + sslContextParameters
+ '}';
}
}
diff --git a/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpConstants.java b/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpConstants.java
index 00eede06d2c..271910b8d14 100644
--- a/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpConstants.java
+++ b/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpConstants.java
@@ -46,43 +46,69 @@ public final class MllpConstants {
public static final String MLLP_CLOSE_CONNECTION_AFTER_SEND = "CamelMllpCloseConnectionAfterSend";
public static final String MLLP_RESET_CONNECTION_AFTER_SEND = "CamelMllpResetConnectionAfterSend";
- /** MSH-3 value */
+ /**
+ * MSH-3 value
+ */
@Metadata(label = "consumer", javaType = "String")
public static final String MLLP_SENDING_APPLICATION = "CamelMllpSendingApplication";
- /** MSH-4 value */
+ /**
+ * MSH-4 value
+ */
@Metadata(label = "consumer", javaType = "String")
public static final String MLLP_SENDING_FACILITY = "CamelMllpSendingFacility";
- /** MSH-5 value */
+ /**
+ * MSH-5 value
+ */
@Metadata(label = "consumer", javaType = "String")
public static final String MLLP_RECEIVING_APPLICATION = "CamelMllpReceivingApplication";
- /** MSH-6 value */
+ /**
+ * MSH-6 value
+ */
@Metadata(label = "consumer", javaType = "String")
public static final String MLLP_RECEIVING_FACILITY = "CamelMllpReceivingFacility";
- /** MSH-7 value */
+ /**
+ * MSH-7 value
+ */
@Metadata(label = "consumer", javaType = "String")
public static final String MLLP_TIMESTAMP = "CamelMllpTimestamp";
- /** MSH-8 value */
+ /**
+ * MSH-8 value
+ */
@Metadata(label = "consumer", javaType = "String")
public static final String MLLP_SECURITY = "CamelMllpSecurity";
- /** MSH-9 value */
+ /**
+ * MSH-9 value
+ */
@Metadata(label = "consumer", javaType = "String")
public static final String MLLP_MESSAGE_TYPE = "CamelMllpMessageType";
- /** MSH-9.1 value */
+ /**
+ * MSH-9.1 value
+ */
@Metadata(label = "consumer", javaType = "String")
public static final String MLLP_EVENT_TYPE = "CamelMllpEventType";
- /** MSH-9.2 value */
+ /**
+ * MSH-9.2 value
+ */
@Metadata(label = "consumer", javaType = "String")
public static final String MLLP_TRIGGER_EVENT = "CamelMllpTriggerEvent";
- /** MSH-10 value */
+ /**
+ * MSH-10 value
+ */
@Metadata(label = "consumer", javaType = "String")
public static final String MLLP_MESSAGE_CONTROL = "CamelMllpMessageControlId";
- /** MSH-11 value */
+ /**
+ * MSH-11 value
+ */
@Metadata(label = "consumer", javaType = "String")
public static final String MLLP_PROCESSING_ID = "CamelMllpProcessingId";
- /** MSH-12 value */
+ /**
+ * MSH-12 value
+ */
@Metadata(label = "consumer", javaType = "String")
public static final String MLLP_VERSION_ID = "CamelMllpVersionId";
- /** MSH-18 value */
+ /**
+ * MSH-18 value
+ */
@Metadata(label = "consumer", javaType = "String")
public static final String MLLP_CHARSET = "CamelMllpCharset";
diff --git a/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpEndpoint.java b/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpEndpoint.java
index c9e02812ece..7b3f0e851d6 100644
--- a/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpEndpoint.java
+++ b/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpEndpoint.java
@@ -36,11 +36,12 @@ import org.apache.camel.spi.UriEndpoint;
import org.apache.camel.spi.UriParam;
import org.apache.camel.spi.UriPath;
import org.apache.camel.support.DefaultEndpoint;
+import org.apache.camel.support.jsse.SSLContextParameters;
import org.slf4j.Logger;
/**
* Communicate with external systems using the MLLP protocol.
- *
+ * <p>
* <p/>
* NOTE: MLLP payloads are not logged unless the logging level is set to DEBUG or TRACE to avoid introducing PHI into
* the log files. Logging of PHI can be globally disabled by setting the org.apache.camel.mllp.logPHI system property to
@@ -118,6 +119,7 @@ public class MllpEndpoint extends DefaultEndpoint implements EndpointServiceLoca
@Override
public Producer createProducer() throws Exception {
+
return new MllpTcpClientProducer(this);
}
@@ -181,7 +183,7 @@ public class MllpEndpoint extends DefaultEndpoint implements EndpointServiceLoca
/**
* Hostname or IP for connection for the TCP connection.
- *
+ * <p>
* The default value is null, which means any local IP address
*
* @param hostname Hostname or IP
@@ -312,6 +314,25 @@ public class MllpEndpoint extends DefaultEndpoint implements EndpointServiceLoca
configuration.setIdleTimeoutStrategy(strategy);
}
+ /**
+ * Sets the SSLContextParameters for the endpoint. Subclasses overriding this method should ensure that the
+ * configuration's SSLContextParameters are appropriately updated and validated.
+ *
+ * @param sslContextParameters the SSLContextParameters to use
+ */
+ public void setSslContextParameters(SSLContextParameters sslContextParameters) {
+ configuration.setSslContextParameters(sslContextParameters);
+ }
+
+ /**
+ * Retrieves the SSLContextParameters for the endpoint. Subclasses overriding this method should ensure the returned
+ * SSLContextParameters are consistent with the endpoint's configuration.
+ *
+ * @return the current SSLContextParameters
+ */
+ public SSLContextParameters getSslContextParameters() {
+ return configuration.getSslContextParameters();
+ }
// Utility methods for producers and consumers
public boolean checkBeforeSendProperties(Exchange exchange, Socket socket, Logger log) {
diff --git a/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpTcpClientProducer.java b/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpTcpClientProducer.java
index cf377835847..cda14ee6626 100644
--- a/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpTcpClientProducer.java
+++ b/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpTcpClientProducer.java
@@ -1,604 +1,630 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.component.mllp;
-
-import java.io.IOException;
-import java.net.InetSocketAddress;
-import java.net.Socket;
-import java.net.SocketAddress;
-import java.net.SocketException;
-import java.net.SocketTimeoutException;
-import java.nio.charset.Charset;
-import java.util.Date;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.ThreadFactory;
-import java.util.concurrent.TimeUnit;
-
-import org.apache.camel.Exchange;
-import org.apache.camel.ExchangePattern;
-import org.apache.camel.ExchangePropertyKey;
-import org.apache.camel.Message;
-import org.apache.camel.api.management.ManagedAttribute;
-import org.apache.camel.api.management.ManagedOperation;
-import org.apache.camel.api.management.ManagedResource;
-import org.apache.camel.component.mllp.internal.Hl7Util;
-import org.apache.camel.component.mllp.internal.MllpSocketBuffer;
-import org.apache.camel.support.DefaultProducer;
-import org.apache.camel.util.StringHelper;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * The MLLP producer.
- */
-@ManagedResource(description = "MLLP Producer")
-public class MllpTcpClientProducer extends DefaultProducer implements Runnable {
- final Logger log;
- final MllpSocketBuffer mllpBuffer;
-
- Socket socket;
-
- ScheduledExecutorService idleTimeoutExecutor;
-
- private String cachedLocalAddress;
- private String cachedRemoteAddress;
- private String cachedCombinedAddress;
- private final Charset charset;
- private final Hl7Util hl7Util;
- private final boolean logPhi;
-
- public MllpTcpClientProducer(MllpEndpoint endpoint) {
- super(endpoint);
-
- log = LoggerFactory
- .getLogger(String.format("%s.%s.%d", this.getClass().getName(), endpoint.getHostname(), endpoint.getPort()));
-
- log.trace("Constructing MllpTcpClientProducer for endpoint URI {}", endpoint.getEndpointUri());
-
- mllpBuffer = new MllpSocketBuffer(endpoint);
- charset = Charset.forName(endpoint.getConfiguration().getCharsetName());
- MllpComponent component = endpoint.getComponent();
- this.logPhi = component.getLogPhi();
- hl7Util = new Hl7Util(component.getLogPhiMaxBytes(), logPhi);
- }
-
- @ManagedAttribute(description = "Last activity time")
- public Date getLastActivityTime() {
- return getEndpoint().getLastConnectionActivityTime();
- }
-
- @ManagedAttribute(description = "Connection")
- public String getConnectionAddress() {
- if (cachedCombinedAddress != null) {
- return cachedCombinedAddress;
- }
-
- return MllpSocketBuffer.formatAddressString(null, null);
- }
-
- @ManagedOperation(description = "Close Connection")
- public void closeConnection() {
- log.info("Close Connection for address {} called via JMX", getConnectionAddress());
-
- mllpBuffer.closeSocket(socket);
- }
-
- @ManagedOperation(description = "Reset Connection")
- public void resetConnection() {
- log.info("Reset Connection for address {} requested via JMX", getConnectionAddress());
-
- mllpBuffer.resetSocket(socket);
- }
-
- @Override
- protected void doStart() throws Exception {
- if (getConfiguration().hasIdleTimeout()) {
- // Get the URI without options
- String fullEndpointKey = getEndpoint().getEndpointKey();
- String endpointKey = StringHelper.before(fullEndpointKey, "?", fullEndpointKey);
-
- idleTimeoutExecutor = Executors.newSingleThreadScheduledExecutor(new IdleTimeoutThreadFactory(endpointKey));
- }
-
- super.doStart();
- }
-
- @Override
- protected void doStop() throws Exception {
- if (idleTimeoutExecutor != null) {
- idleTimeoutExecutor.shutdown();
- idleTimeoutExecutor = null;
- }
-
- mllpBuffer.resetSocket(socket);
-
- super.doStop();
- }
-
- @Override
- public void process(Exchange exchange) throws MllpException {
- lock.lock();
- try {
- log.trace("process({}) [{}] - entering", exchange.getExchangeId(), socket);
- getEndpoint().updateLastConnectionActivityTicks();
-
- Message message = exchange.getMessage();
-
- getEndpoint().checkBeforeSendProperties(exchange, socket, log);
-
- // Establish a connection if needed
- try {
- checkConnection();
-
- if (cachedLocalAddress != null) {
- message.setHeader(MllpConstants.MLLP_LOCAL_ADDRESS, cachedLocalAddress);
- }
-
- if (cachedRemoteAddress != null) {
- message.setHeader(MllpConstants.MLLP_REMOTE_ADDRESS, cachedRemoteAddress);
- }
-
- // Send the message to the external system
- byte[] hl7MessageBytes = null;
- Object messageBody = message.getBody();
- if (messageBody == null) {
- String exceptionMessage
- = String.format("process(%s) [%s] - message body is null", exchange.getExchangeId(), socket);
- exchange.setException(new MllpInvalidMessageException(exceptionMessage, hl7MessageBytes, logPhi));
- return;
- } else if (messageBody instanceof byte[]) {
- hl7MessageBytes = (byte[]) messageBody;
- } else if (messageBody instanceof String) {
- String stringBody = (String) messageBody;
- hl7MessageBytes = stringBody.getBytes(MllpCharsetHelper.getCharset(exchange, charset));
- if (getConfiguration().hasCharsetName()) {
- exchange.setProperty(ExchangePropertyKey.CHARSET_NAME, getConfiguration().getCharsetName());
- }
- }
-
- log.debug("process({}) [{}] - sending message to external system", exchange.getExchangeId(), socket);
-
- try {
- mllpBuffer.setEnvelopedMessage(hl7MessageBytes);
- mllpBuffer.writeTo(socket);
- } catch (MllpSocketException writeEx) {
- // Connection may have been reset - try one more time
- log.debug("process({}) [{}] - exception encountered writing payload - attempting reconnect",
- exchange.getExchangeId(), socket, writeEx);
- try {
- checkConnection();
- log.trace("process({}) [{}] - reconnected succeeded - resending payload", exchange.getExchangeId(),
- socket);
- try {
- mllpBuffer.writeTo(socket);
- } catch (MllpSocketException retryWriteEx) {
- String exceptionMessage = String.format(
- "process(%s) [%s] - exception encountered attempting to write payload after reconnect",
- exchange.getExchangeId(), socket);
- log.warn(exceptionMessage, retryWriteEx);
- exchange.setException(
- new MllpWriteException(
- exceptionMessage, mllpBuffer.toByteArrayAndReset(), retryWriteEx, logPhi));
- }
- } catch (IOException reconnectEx) {
- String exceptionMessage
- = String.format("process(%s) [%s] - exception encountered attempting to reconnect",
- exchange.getExchangeId(), socket);
- log.warn(exceptionMessage, reconnectEx);
- exchange.setException(
- new MllpWriteException(exceptionMessage, mllpBuffer.toByteArrayAndReset(), writeEx, logPhi));
- mllpBuffer.resetSocket(socket);
- }
- }
- if (getConfiguration().getExchangePattern() == ExchangePattern.InOnly) {
- log.debug("process({}) [{}] - not checking acknowledgement from external system",
- exchange.getExchangeId(), socket);
- return;
- }
- if (exchange.getException() == null) {
- log.debug("process({}) [{}] - reading acknowledgement from external system", exchange.getExchangeId(),
- socket);
- try {
- mllpBuffer.reset();
- mllpBuffer.readFrom(socket);
- } catch (MllpSocketException receiveAckEx) {
- // Connection may have been reset - try one more time
- log.debug("process({}) [{}] - exception encountered reading acknowledgement - attempting reconnect",
- exchange.getExchangeId(), socket, receiveAckEx);
- try {
- checkConnection();
- } catch (IOException reconnectEx) {
- String exceptionMessage = String.format(
- "process(%s) [%s] - exception encountered attempting to reconnect after acknowledgement read failure",
- exchange.getExchangeId(), socket);
- log.warn(exceptionMessage, reconnectEx);
- exchange.setException(
- new MllpAcknowledgementReceiveException(
- exceptionMessage, hl7MessageBytes, receiveAckEx, logPhi));
- mllpBuffer.resetSocket(socket);
- }
-
- if (exchange.getException() == null) {
- log.trace("process({}) [{}] - resending payload after successful reconnect",
- exchange.getExchangeId(),
- socket);
- try {
- mllpBuffer.setEnvelopedMessage(hl7MessageBytes);
- mllpBuffer.writeTo(socket);
- } catch (MllpSocketException writeRetryEx) {
- String exceptionMessage = String.format(
- "process(%s) [%s] - exception encountered attempting to write payload after read failure and successful reconnect",
- exchange.getExchangeId(), socket);
- log.warn(exceptionMessage, writeRetryEx);
- exchange.setException(
- new MllpWriteException(exceptionMessage, hl7MessageBytes, receiveAckEx, logPhi));
- }
-
- if (exchange.getException() == null) {
- log.trace("process({}) [{}] - resend succeeded - reading acknowledgement from external system",
- exchange.getExchangeId(), socket);
- try {
- mllpBuffer.reset();
- mllpBuffer.readFrom(socket);
- } catch (MllpSocketException secondReceiveEx) {
- String exceptionMessageFormat = mllpBuffer.isEmpty()
- ? "process(%s) [%s] - exception encountered reading MLLP Acknowledgement after successful reconnect and resend"
- : "process(%s) [%s] - exception encountered reading complete MLLP Acknowledgement after successful reconnect and resend";
- String exceptionMessage
- = String.format(exceptionMessageFormat, exchange.getExchangeId(), socket);
- log.warn(exceptionMessage, secondReceiveEx);
- // Send the original exception to the exchange
- exchange.setException(new MllpAcknowledgementReceiveException(
- exceptionMessage, hl7MessageBytes, mllpBuffer.toByteArrayAndReset(), receiveAckEx,
- logPhi));
- } catch (SocketTimeoutException secondReadTimeoutEx) {
- String exceptionMessageFormat = mllpBuffer.isEmpty()
- ? "process(%s) [%s] - timeout receiving MLLP Acknowledgment after successful reconnect and resend"
- : "process(%s) [%s] - timeout receiving complete MLLP Acknowledgment after successful reconnect and resend";
- String exceptionMessage
- = String.format(exceptionMessageFormat, exchange.getExchangeId(), socket);
- log.warn(exceptionMessage, secondReadTimeoutEx);
- // Send the original exception to the exchange
- exchange.setException(new MllpAcknowledgementTimeoutException(
- exceptionMessage, hl7MessageBytes, mllpBuffer.toByteArrayAndReset(), receiveAckEx,
- logPhi));
- mllpBuffer.resetSocket(socket);
- }
- }
- }
- } catch (SocketTimeoutException timeoutEx) {
- String exceptionMessageFormat = mllpBuffer.isEmpty()
- ? "process(%s) [%s] - timeout receiving MLLP Acknowledgment"
- : "process(%s) [%s] - timeout receiving complete MLLP Acknowledgment";
- String exceptionMessage = String.format(exceptionMessageFormat, exchange.getExchangeId(), socket);
- log.warn(exceptionMessage, timeoutEx);
- exchange.setException(new MllpAcknowledgementTimeoutException(
- exceptionMessage, hl7MessageBytes, mllpBuffer.toByteArrayAndReset(), timeoutEx, logPhi));
- mllpBuffer.resetSocket(socket);
- }
-
- if (exchange.getException() == null) {
- if (mllpBuffer.hasCompleteEnvelope()) {
- byte[] acknowledgementBytes = mllpBuffer.toMllpPayload();
-
- log.debug(
- "process({}) [{}] - populating message headers with the acknowledgement from the external system",
- exchange.getExchangeId(), socket);
- message.setHeader(MllpConstants.MLLP_ACKNOWLEDGEMENT, acknowledgementBytes);
- if (acknowledgementBytes != null && acknowledgementBytes.length > 0) {
- message.setHeader(MllpConstants.MLLP_ACKNOWLEDGEMENT_STRING, new String(
- acknowledgementBytes,
- MllpCharsetHelper.getCharset(exchange, acknowledgementBytes, hl7Util, charset)));
- } else {
- message.setHeader(MllpConstants.MLLP_ACKNOWLEDGEMENT_STRING, "");
- }
-
- if (getConfiguration().isValidatePayload()) {
- String exceptionMessage = hl7Util.generateInvalidPayloadExceptionMessage(acknowledgementBytes);
- if (exceptionMessage != null) {
- exchange.setException(new MllpInvalidAcknowledgementException(
- exceptionMessage, hl7MessageBytes, acknowledgementBytes, logPhi));
- }
- }
-
- if (exchange.getException() == null) {
- log.debug("process({}) [{}] - processing the acknowledgement from the external system",
- exchange.getExchangeId(), socket);
- try {
- message.setHeader(MllpConstants.MLLP_ACKNOWLEDGEMENT_TYPE,
- processAcknowledgment(hl7MessageBytes, acknowledgementBytes));
- } catch (MllpNegativeAcknowledgementException nackEx) {
- message.setHeader(MllpConstants.MLLP_ACKNOWLEDGEMENT_TYPE, nackEx.getAcknowledgmentType());
- exchange.setException(nackEx);
- }
-
- getEndpoint().checkAfterSendProperties(exchange, socket, log);
- }
- } else {
- String exceptionMessage = String.format("process(%s) [%s] - invalid acknowledgement received",
- exchange.getExchangeId(), socket);
- exchange.setException(new MllpInvalidAcknowledgementException(
- exceptionMessage, hl7MessageBytes, mllpBuffer.toByteArrayAndReset(), logPhi));
- }
- }
- }
-
- } catch (IOException ioEx) {
- log.debug("process({}) [{}] - IOException encountered checking connection", exchange.getExchangeId(), socket,
- ioEx);
- exchange.setException(ioEx);
- mllpBuffer.resetSocket(socket);
- } finally {
- mllpBuffer.reset();
- }
-
- log.trace("process({}) [{}] - exiting", exchange.getExchangeId(), socket);
- } finally {
- lock.unlock();
- }
- }
-
- private String processAcknowledgment(byte[] hl7MessageBytes, byte[] hl7AcknowledgementBytes) throws MllpException {
- String acknowledgementType = "";
-
- if (hl7AcknowledgementBytes != null && hl7AcknowledgementBytes.length > 3) {
- // Extract the acknowledgement type and check for a NACK
- byte fieldDelim = hl7AcknowledgementBytes[3];
- // First, find the beginning of the MSA segment - should be the second segment
- int msaStartIndex = -1;
- for (int i = 0; i < hl7AcknowledgementBytes.length; ++i) {
- if (MllpProtocolConstants.SEGMENT_DELIMITER == hl7AcknowledgementBytes[i]) {
- final byte bM = 77;
- final byte bS = 83;
- final byte bC = 67;
- final byte bA = 65;
- final byte bE = 69;
- final byte bR = 82;
- /* We've found the start of a new segment - make sure peeking ahead
- won't run off the end of the array - we need at least 7 more bytes
- */
- if (hl7AcknowledgementBytes.length > i + 7) {
- // We can safely peek ahead
- if (bM == hl7AcknowledgementBytes[i + 1] && bS == hl7AcknowledgementBytes[i + 2]
- && bA == hl7AcknowledgementBytes[i + 3] && fieldDelim == hl7AcknowledgementBytes[i + 4]) {
- // Found the beginning of the MSA - the next two bytes should be our acknowledgement code
- msaStartIndex = i + 1;
- if (bA != hl7AcknowledgementBytes[i + 5] && bC != hl7AcknowledgementBytes[i + 5]) {
- String errorMessage = String.format(
- "processAcknowledgment(hl7MessageBytes[%d], hl7AcknowledgementBytes[%d]) - unsupported acknowledgement type: '%s'",
- hl7MessageBytes == null ? -1 : hl7MessageBytes.length, hl7AcknowledgementBytes.length,
- new String(hl7AcknowledgementBytes, i + 5, 2));
- throw new MllpInvalidAcknowledgementException(
- errorMessage, hl7MessageBytes, hl7AcknowledgementBytes, logPhi);
- } else {
- switch (hl7AcknowledgementBytes[i + 6]) {
- case bA:
- // We have an AA or CA
- if (bA == hl7AcknowledgementBytes[i + 5]) {
- acknowledgementType = "AA";
- } else {
- acknowledgementType = "CA";
- }
- break;
- case bE:
- // We have an AE or CE
- if (bA == hl7AcknowledgementBytes[i + 5]) {
- throw new MllpApplicationErrorAcknowledgementException(
- hl7MessageBytes, hl7AcknowledgementBytes, logPhi);
- } else {
- throw new MllpCommitErrorAcknowledgementException(
- hl7MessageBytes, hl7AcknowledgementBytes, logPhi);
- }
- case bR:
- // We have an AR or CR
- if (bA == hl7AcknowledgementBytes[i + 5]) {
- throw new MllpApplicationRejectAcknowledgementException(
- hl7MessageBytes, hl7AcknowledgementBytes, logPhi);
- } else {
- throw new MllpCommitRejectAcknowledgementException(
- hl7MessageBytes, hl7AcknowledgementBytes, logPhi);
- }
- default:
- String errorMessage = "Unsupported acknowledgement type: "
- + new String(hl7AcknowledgementBytes, i + 5, 2);
- throw new MllpInvalidAcknowledgementException(
- errorMessage, hl7MessageBytes, hl7AcknowledgementBytes, logPhi);
- }
- }
-
- break;
- }
- }
- }
-
- }
- if (-1 == msaStartIndex && getConfiguration().isValidatePayload()) {
- // Didn't find an MSA
- throw new MllpInvalidAcknowledgementException(
- "MSA Not found in acknowledgement", hl7MessageBytes, hl7AcknowledgementBytes, logPhi);
- }
- }
-
- return acknowledgementType;
- }
-
- /**
- * Validate the TCP Connection
- *
- * @return null if the connection is valid, otherwise the Exception encounted checking the connection
- */
- void checkConnection() throws IOException {
- if (null == socket || socket.isClosed() || !socket.isConnected()) {
- logCurrentSocketState();
-
- // The socket will be closed by close connection, resetConnection, etc
- Socket newSocket = createNewSocket();
-
- InetSocketAddress socketAddress = configureSocketAddress();
-
- newSocket.connect(socketAddress, getConfiguration().getConnectTimeout());
- log.info("checkConnection() - established new connection {}", newSocket);
- getEndpoint().updateLastConnectionEstablishedTicks();
-
- socket = newSocket;
-
- cacheAddresses();
-
- if (getConfiguration().hasIdleTimeout()) {
- log.debug("Scheduling initial idle producer connection check of {} in {} milliseconds", getConnectionAddress(),
- getConfiguration().getIdleTimeout());
- idleTimeoutExecutor.schedule(this, getConfiguration().getIdleTimeout(), TimeUnit.MILLISECONDS);
- }
- } else {
- log.debug("checkConnection() - Connection {} is still valid - no new connection required", socket);
- }
- }
-
- private void logCurrentSocketState() {
- if (socket == null) {
- log.debug("checkConnection() - Socket is null - attempting to establish connection");
- } else if (socket.isClosed()) {
- log.info("checkConnection() - Socket {} is closed - attempting to establish new connection", socket);
- } else if (!socket.isConnected()) {
- log.info("checkConnection() - Socket {} is not connected - attempting to establish new connection", socket);
- }
- }
-
- private void cacheAddresses() {
- SocketAddress localSocketAddress = socket.getLocalSocketAddress();
- if (localSocketAddress != null) {
- cachedLocalAddress = localSocketAddress.toString();
- }
- SocketAddress remoteSocketAddress = socket.getRemoteSocketAddress();
- if (remoteSocketAddress != null) {
- cachedRemoteAddress = remoteSocketAddress.toString();
- }
- cachedCombinedAddress = MllpSocketBuffer.formatAddressString(localSocketAddress, remoteSocketAddress);
- }
-
- private InetSocketAddress configureSocketAddress() {
- InetSocketAddress socketAddress;
- if (null == getEndpoint().getHostname()) {
- socketAddress = new InetSocketAddress(getEndpoint().getPort());
- } else {
- socketAddress = new InetSocketAddress(getEndpoint().getHostname(), getEndpoint().getPort());
- }
- return socketAddress;
- }
-
- private Socket createNewSocket() throws SocketException {
- Socket newSocket = new Socket();
-
- if (getConfiguration().hasKeepAlive()) {
- newSocket.setKeepAlive(getConfiguration().getKeepAlive());
- }
- if (getConfiguration().hasTcpNoDelay()) {
- newSocket.setTcpNoDelay(getConfiguration().getTcpNoDelay());
- }
-
- if (getConfiguration().hasReceiveBufferSize()) {
- newSocket.setReceiveBufferSize(getConfiguration().getReceiveBufferSize());
- }
- if (getConfiguration().hasSendBufferSize()) {
- newSocket.setSendBufferSize(getConfiguration().getSendBufferSize());
- }
- if (getConfiguration().hasReuseAddress()) {
- newSocket.setReuseAddress(getConfiguration().getReuseAddress());
- }
-
- newSocket.setSoLinger(false, -1);
- return newSocket;
- }
-
- /**
- * Check for idle connection
- */
- @Override
- public void run() {
- lock.lock();
- try {
- if (getConfiguration().hasIdleTimeout()) {
- if (null != socket && !socket.isClosed() && socket.isConnected()) {
- if (getEndpoint().hasLastConnectionActivityTicks()) {
- long idleTime = System.currentTimeMillis() - getEndpoint().getLastConnectionActivityTicks();
- if (log.isDebugEnabled()) {
- log.debug("Checking {} for idle connection: {} - {}", getConnectionAddress(), idleTime,
- getConfiguration().getIdleTimeout());
- }
- if (idleTime >= getConfiguration().getIdleTimeout()) {
- if (MllpIdleTimeoutStrategy.CLOSE == getConfiguration().getIdleTimeoutStrategy()) {
- log.info(
- "MLLP Connection idle time of '{}' milliseconds met or exceeded the idle producer timeout of '{}' milliseconds - closing connection",
- idleTime, getConfiguration().getIdleTimeout());
- mllpBuffer.closeSocket(socket);
- } else {
- log.info(
- "MLLP Connection idle time of '{}' milliseconds met or exceeded the idle producer timeout of '{}' milliseconds - resetting connection",
- idleTime, getConfiguration().getIdleTimeout());
- mllpBuffer.resetSocket(socket);
- }
- } else {
- long minDelay = 100;
- long delay = Long.min(Long.max(minDelay, getConfiguration().getIdleTimeout() - idleTime),
- getConfiguration().getIdleTimeout());
- if (log.isDebugEnabled()) {
- log.debug("Scheduling idle producer connection check of {} in {} milliseconds",
- getConnectionAddress(), delay);
- }
- idleTimeoutExecutor.schedule(this, delay, TimeUnit.MILLISECONDS);
- }
- } else {
- log.debug(
- "No activity detected since initial connection - scheduling idle producer connection check in {} milliseconds",
- getConfiguration().getIdleTimeout());
- idleTimeoutExecutor.schedule(this, getConfiguration().getIdleTimeout(), TimeUnit.MILLISECONDS);
- }
- }
- }
- } finally {
- lock.unlock();
- }
- }
-
- static class IdleTimeoutThreadFactory implements ThreadFactory {
- final String endpointKey;
-
- IdleTimeoutThreadFactory(String endpointKey) {
- this.endpointKey = endpointKey;
- }
-
- @Override
- public Thread newThread(Runnable r) {
- Thread timeoutThread = Executors.defaultThreadFactory().newThread(r);
-
- timeoutThread.setName(
- String.format("%s[%s]-idle-timeout-thread", MllpTcpClientProducer.class.getSimpleName(), endpointKey));
-
- return timeoutThread;
- }
- }
-
- @Override
- public MllpEndpoint getEndpoint() {
- return (MllpEndpoint) super.getEndpoint();
- }
-
- public MllpConfiguration getConfiguration() {
- return this.getEndpoint().getConfiguration();
- }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.mllp;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.net.SocketTimeoutException;
+import java.nio.charset.Charset;
+import java.util.Date;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.TimeUnit;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocketFactory;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.ExchangePattern;
+import org.apache.camel.ExchangePropertyKey;
+import org.apache.camel.Message;
+import org.apache.camel.api.management.ManagedAttribute;
+import org.apache.camel.api.management.ManagedOperation;
+import org.apache.camel.api.management.ManagedResource;
+import org.apache.camel.component.mllp.internal.Hl7Util;
+import org.apache.camel.component.mllp.internal.MllpSocketBuffer;
+import org.apache.camel.support.DefaultProducer;
+import org.apache.camel.support.jsse.SSLContextParameters;
+import org.apache.camel.util.StringHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The MLLP producer.
+ */
+@ManagedResource(description = "MLLP Producer")
+public class MllpTcpClientProducer extends DefaultProducer implements Runnable {
+ final Logger log;
+ final MllpSocketBuffer mllpBuffer;
+
+ Socket socket;
+
+ ScheduledExecutorService idleTimeoutExecutor;
+ private String cachedLocalAddress;
+ private String cachedRemoteAddress;
+ private String cachedCombinedAddress;
+ private final Charset charset;
+ private final Hl7Util hl7Util;
+ private final boolean logPhi;
+
+ public MllpTcpClientProducer(MllpEndpoint endpoint) {
+ super(endpoint);
+
+ log = LoggerFactory
+ .getLogger(String.format("%s.%s.%d", this.getClass().getName(), endpoint.getHostname(), endpoint.getPort()));
+
+ log.trace("Constructing MllpTcpClientProducer for endpoint URI {}", endpoint.getEndpointUri());
+
+ mllpBuffer = new MllpSocketBuffer(endpoint);
+ charset = Charset.forName(endpoint.getConfiguration().getCharsetName());
+ MllpComponent component = endpoint.getComponent();
+ this.logPhi = component.getLogPhi();
+ hl7Util = new Hl7Util(component.getLogPhiMaxBytes(), logPhi);
+ }
+
+ @ManagedAttribute(description = "Last activity time")
+ public Date getLastActivityTime() {
+ return getEndpoint().getLastConnectionActivityTime();
+ }
+
+ @ManagedAttribute(description = "Connection")
+ public String getConnectionAddress() {
+ if (cachedCombinedAddress != null) {
+ return cachedCombinedAddress;
+ }
+
+ return MllpSocketBuffer.formatAddressString(null, null);
+ }
+
+ @ManagedOperation(description = "Close Connection")
+ public void closeConnection() {
+ log.info("Close Connection for address {} called via JMX", getConnectionAddress());
+
+ mllpBuffer.closeSocket(socket);
+ }
+
+ @ManagedOperation(description = "Reset Connection")
+ public void resetConnection() {
+ log.info("Reset Connection for address {} requested via JMX", getConnectionAddress());
+
+ mllpBuffer.resetSocket(socket);
+ }
+
+ @Override
+ protected void doStart() throws Exception {
+ if (getConfiguration().hasIdleTimeout()) {
+ // Get the URI without options
+ String fullEndpointKey = getEndpoint().getEndpointKey();
+ String endpointKey = StringHelper.before(fullEndpointKey, "?", fullEndpointKey);
+
+ idleTimeoutExecutor = Executors.newSingleThreadScheduledExecutor(new IdleTimeoutThreadFactory(endpointKey));
+ }
+
+ super.doStart();
+ }
+
+ @Override
+ protected void doStop() throws Exception {
+ if (idleTimeoutExecutor != null) {
+ idleTimeoutExecutor.shutdown();
+ idleTimeoutExecutor = null;
+ }
+
+ mllpBuffer.resetSocket(socket);
+
+ super.doStop();
+ }
+
+ @Override
+ public void process(Exchange exchange) throws MllpException {
+ lock.lock();
+ try {
+ log.trace("process({}) [{}] - entering", exchange.getExchangeId(), socket);
+ getEndpoint().updateLastConnectionActivityTicks();
+
+ Message message = exchange.getMessage();
+
+ getEndpoint().checkBeforeSendProperties(exchange, socket, log);
+
+ // Establish a connection if needed
+ try {
+ checkConnection();
+
+ if (cachedLocalAddress != null) {
+ message.setHeader(MllpConstants.MLLP_LOCAL_ADDRESS, cachedLocalAddress);
+ }
+
+ if (cachedRemoteAddress != null) {
+ message.setHeader(MllpConstants.MLLP_REMOTE_ADDRESS, cachedRemoteAddress);
+ }
+
+ // Send the message to the external system
+ byte[] hl7MessageBytes = null;
+ Object messageBody = message.getBody();
+ if (messageBody == null) {
+ String exceptionMessage
+ = String.format("process(%s) [%s] - message body is null", exchange.getExchangeId(), socket);
+ exchange.setException(new MllpInvalidMessageException(exceptionMessage, hl7MessageBytes, logPhi));
+ return;
+ } else if (messageBody instanceof byte[]) {
+ hl7MessageBytes = (byte[]) messageBody;
+ } else if (messageBody instanceof String) {
+ String stringBody = (String) messageBody;
+ hl7MessageBytes = stringBody.getBytes(MllpCharsetHelper.getCharset(exchange, charset));
+ if (getConfiguration().hasCharsetName()) {
+ exchange.setProperty(ExchangePropertyKey.CHARSET_NAME, getConfiguration().getCharsetName());
+ }
+ }
+
+ log.debug("process({}) [{}] - sending message to external system", exchange.getExchangeId(), socket);
+
+ try {
+ mllpBuffer.setEnvelopedMessage(hl7MessageBytes);
+ mllpBuffer.writeTo(socket);
+ } catch (MllpSocketException writeEx) {
+ // Connection may have been reset - try one more time
+ log.debug("process({}) [{}] - exception encountered writing payload - attempting reconnect",
+ exchange.getExchangeId(), socket, writeEx);
+ try {
+ checkConnection();
+ log.trace("process({}) [{}] - reconnected succeeded - resending payload", exchange.getExchangeId(),
+ socket);
+ try {
+ mllpBuffer.writeTo(socket);
+ } catch (MllpSocketException retryWriteEx) {
+ String exceptionMessage = String.format(
+ "process(%s) [%s] - exception encountered attempting to write payload after reconnect",
+ exchange.getExchangeId(), socket);
+ log.warn(exceptionMessage, retryWriteEx);
+ exchange.setException(
+ new MllpWriteException(
+ exceptionMessage, mllpBuffer.toByteArrayAndReset(), retryWriteEx, logPhi));
+ }
+ } catch (IOException reconnectEx) {
+ String exceptionMessage
+ = String.format("process(%s) [%s] - exception encountered attempting to reconnect",
+ exchange.getExchangeId(), socket);
+ log.warn(exceptionMessage, reconnectEx);
+ exchange.setException(
+ new MllpWriteException(exceptionMessage, mllpBuffer.toByteArrayAndReset(), writeEx, logPhi));
+ mllpBuffer.resetSocket(socket);
+ }
+ }
+ if (getConfiguration().getExchangePattern() == ExchangePattern.InOnly) {
+ log.debug("process({}) [{}] - not checking acknowledgement from external system",
+ exchange.getExchangeId(), socket);
+ return;
+ }
+ if (exchange.getException() == null) {
+ log.debug("process({}) [{}] - reading acknowledgement from external system", exchange.getExchangeId(),
+ socket);
+ try {
+ mllpBuffer.reset();
+ mllpBuffer.readFrom(socket);
+ } catch (MllpSocketException receiveAckEx) {
+ // Connection may have been reset - try one more time
+ log.debug("process({}) [{}] - exception encountered reading acknowledgement - attempting reconnect",
+ exchange.getExchangeId(), socket, receiveAckEx);
+ try {
+ checkConnection();
+ } catch (IOException reconnectEx) {
+ String exceptionMessage = String.format(
+ "process(%s) [%s] - exception encountered attempting to reconnect after acknowledgement read failure",
+ exchange.getExchangeId(), socket);
+ log.warn(exceptionMessage, reconnectEx);
+ exchange.setException(
+ new MllpAcknowledgementReceiveException(
+ exceptionMessage, hl7MessageBytes, receiveAckEx, logPhi));
+ mllpBuffer.resetSocket(socket);
+ }
+
+ if (exchange.getException() == null) {
+ log.trace("process({}) [{}] - resending payload after successful reconnect",
+ exchange.getExchangeId(),
+ socket);
+ try {
+ mllpBuffer.setEnvelopedMessage(hl7MessageBytes);
+ mllpBuffer.writeTo(socket);
+ } catch (MllpSocketException writeRetryEx) {
+ String exceptionMessage = String.format(
+ "process(%s) [%s] - exception encountered attempting to write payload after read failure and successful reconnect",
+ exchange.getExchangeId(), socket);
+ log.warn(exceptionMessage, writeRetryEx);
+ exchange.setException(
+ new MllpWriteException(exceptionMessage, hl7MessageBytes, receiveAckEx, logPhi));
+ }
+
+ if (exchange.getException() == null) {
+ log.trace("process({}) [{}] - resend succeeded - reading acknowledgement from external system",
+ exchange.getExchangeId(), socket);
+ try {
+ mllpBuffer.reset();
+ mllpBuffer.readFrom(socket);
+ } catch (MllpSocketException secondReceiveEx) {
+ String exceptionMessageFormat = mllpBuffer.isEmpty()
+ ? "process(%s) [%s] - exception encountered reading MLLP Acknowledgement after successful reconnect and resend"
+ : "process(%s) [%s] - exception encountered reading complete MLLP Acknowledgement after successful reconnect and resend";
+ String exceptionMessage
+ = String.format(exceptionMessageFormat, exchange.getExchangeId(), socket);
+ log.warn(exceptionMessage, secondReceiveEx);
+ // Send the original exception to the exchange
+ exchange.setException(new MllpAcknowledgementReceiveException(
+ exceptionMessage, hl7MessageBytes, mllpBuffer.toByteArrayAndReset(), receiveAckEx,
+ logPhi));
+ } catch (SocketTimeoutException secondReadTimeoutEx) {
+ String exceptionMessageFormat = mllpBuffer.isEmpty()
+ ? "process(%s) [%s] - timeout receiving MLLP Acknowledgment after successful reconnect and resend"
+ : "process(%s) [%s] - timeout receiving complete MLLP Acknowledgment after successful reconnect and resend";
+ String exceptionMessage
+ = String.format(exceptionMessageFormat, exchange.getExchangeId(), socket);
+ log.warn(exceptionMessage, secondReadTimeoutEx);
+ // Send the original exception to the exchange
+ exchange.setException(new MllpAcknowledgementTimeoutException(
+ exceptionMessage, hl7MessageBytes, mllpBuffer.toByteArrayAndReset(), receiveAckEx,
+ logPhi));
+ mllpBuffer.resetSocket(socket);
+ }
+ }
+ }
+ } catch (SocketTimeoutException timeoutEx) {
+ String exceptionMessageFormat = mllpBuffer.isEmpty()
+ ? "process(%s) [%s] - timeout receiving MLLP Acknowledgment"
+ : "process(%s) [%s] - timeout receiving complete MLLP Acknowledgment";
+ String exceptionMessage = String.format(exceptionMessageFormat, exchange.getExchangeId(), socket);
+ log.warn(exceptionMessage, timeoutEx);
+ exchange.setException(new MllpAcknowledgementTimeoutException(
+ exceptionMessage, hl7MessageBytes, mllpBuffer.toByteArrayAndReset(), timeoutEx, logPhi));
+ mllpBuffer.resetSocket(socket);
+ }
+
+ if (exchange.getException() == null) {
+ if (mllpBuffer.hasCompleteEnvelope()) {
+ byte[] acknowledgementBytes = mllpBuffer.toMllpPayload();
+
+ log.debug(
+ "process({}) [{}] - populating message headers with the acknowledgement from the external system",
+ exchange.getExchangeId(), socket);
+ message.setHeader(MllpConstants.MLLP_ACKNOWLEDGEMENT, acknowledgementBytes);
+ if (acknowledgementBytes != null && acknowledgementBytes.length > 0) {
+ message.setHeader(MllpConstants.MLLP_ACKNOWLEDGEMENT_STRING, new String(
+ acknowledgementBytes,
+ MllpCharsetHelper.getCharset(exchange, acknowledgementBytes, hl7Util, charset)));
+ } else {
+ message.setHeader(MllpConstants.MLLP_ACKNOWLEDGEMENT_STRING, "");
+ }
+
+ if (getConfiguration().isValidatePayload()) {
+ String exceptionMessage = hl7Util.generateInvalidPayloadExceptionMessage(acknowledgementBytes);
+ if (exceptionMessage != null) {
+ exchange.setException(new MllpInvalidAcknowledgementException(
+ exceptionMessage, hl7MessageBytes, acknowledgementBytes, logPhi));
+ }
+ }
+
+ if (exchange.getException() == null) {
+ log.debug("process({}) [{}] - processing the acknowledgement from the external system",
+ exchange.getExchangeId(), socket);
+ try {
+ message.setHeader(MllpConstants.MLLP_ACKNOWLEDGEMENT_TYPE,
+ processAcknowledgment(hl7MessageBytes, acknowledgementBytes));
+ } catch (MllpNegativeAcknowledgementException nackEx) {
+ message.setHeader(MllpConstants.MLLP_ACKNOWLEDGEMENT_TYPE, nackEx.getAcknowledgmentType());
+ exchange.setException(nackEx);
+ }
+
+ getEndpoint().checkAfterSendProperties(exchange, socket, log);
+ }
+ } else {
+ String exceptionMessage = String.format("process(%s) [%s] - invalid acknowledgement received",
+ exchange.getExchangeId(), socket);
+ exchange.setException(new MllpInvalidAcknowledgementException(
+ exceptionMessage, hl7MessageBytes, mllpBuffer.toByteArrayAndReset(), logPhi));
+ }
+ }
+ }
+
+ } catch (IOException ioEx) {
+ log.debug("process({}) [{}] - IOException encountered checking connection", exchange.getExchangeId(), socket,
+ ioEx);
+ exchange.setException(ioEx);
+ mllpBuffer.resetSocket(socket);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ } finally {
+ mllpBuffer.reset();
+ }
+
+ log.trace("process({}) [{}] - exiting", exchange.getExchangeId(), socket);
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ private String processAcknowledgment(byte[] hl7MessageBytes, byte[] hl7AcknowledgementBytes) throws MllpException {
+ String acknowledgementType = "";
+
+ if (hl7AcknowledgementBytes != null && hl7AcknowledgementBytes.length > 3) {
+ // Extract the acknowledgement type and check for a NACK
+ byte fieldDelim = hl7AcknowledgementBytes[3];
+ // First, find the beginning of the MSA segment - should be the second segment
+ int msaStartIndex = -1;
+ for (int i = 0; i < hl7AcknowledgementBytes.length; ++i) {
+ if (MllpProtocolConstants.SEGMENT_DELIMITER == hl7AcknowledgementBytes[i]) {
+ final byte bM = 77;
+ final byte bS = 83;
+ final byte bC = 67;
+ final byte bA = 65;
+ final byte bE = 69;
+ final byte bR = 82;
+ /* We've found the start of a new segment - make sure peeking ahead
+ won't run off the end of the array - we need at least 7 more bytes
+ */
+ if (hl7AcknowledgementBytes.length > i + 7) {
+ // We can safely peek ahead
+ if (bM == hl7AcknowledgementBytes[i + 1] && bS == hl7AcknowledgementBytes[i + 2]
+ && bA == hl7AcknowledgementBytes[i + 3] && fieldDelim == hl7AcknowledgementBytes[i + 4]) {
+ // Found the beginning of the MSA - the next two bytes should be our acknowledgement code
+ msaStartIndex = i + 1;
+ if (bA != hl7AcknowledgementBytes[i + 5] && bC != hl7AcknowledgementBytes[i + 5]) {
+ String errorMessage = String.format(
+ "processAcknowledgment(hl7MessageBytes[%d], hl7AcknowledgementBytes[%d]) - unsupported acknowledgement type: '%s'",
+ hl7MessageBytes == null ? -1 : hl7MessageBytes.length, hl7AcknowledgementBytes.length,
+ new String(hl7AcknowledgementBytes, i + 5, 2));
+ throw new MllpInvalidAcknowledgementException(
+ errorMessage, hl7MessageBytes, hl7AcknowledgementBytes, logPhi);
+ } else {
+ switch (hl7AcknowledgementBytes[i + 6]) {
+ case bA:
+ // We have an AA or CA
+ if (bA == hl7AcknowledgementBytes[i + 5]) {
+ acknowledgementType = "AA";
+ } else {
+ acknowledgementType = "CA";
+ }
+ break;
+ case bE:
+ // We have an AE or CE
+ if (bA == hl7AcknowledgementBytes[i + 5]) {
+ throw new MllpApplicationErrorAcknowledgementException(
+ hl7MessageBytes, hl7AcknowledgementBytes, logPhi);
+ } else {
+ throw new MllpCommitErrorAcknowledgementException(
+ hl7MessageBytes, hl7AcknowledgementBytes, logPhi);
+ }
+ case bR:
+ // We have an AR or CR
+ if (bA == hl7AcknowledgementBytes[i + 5]) {
+ throw new MllpApplicationRejectAcknowledgementException(
+ hl7MessageBytes, hl7AcknowledgementBytes, logPhi);
+ } else {
+ throw new MllpCommitRejectAcknowledgementException(
+ hl7MessageBytes, hl7AcknowledgementBytes, logPhi);
+ }
+ default:
+ String errorMessage = "Unsupported acknowledgement type: "
+ + new String(hl7AcknowledgementBytes, i + 5, 2);
+ throw new MllpInvalidAcknowledgementException(
+ errorMessage, hl7MessageBytes, hl7AcknowledgementBytes, logPhi);
+ }
+ }
+
+ break;
+ }
+ }
+ }
+
+ }
+ if (-1 == msaStartIndex && getConfiguration().isValidatePayload()) {
+ // Didn't find an MSA
+ throw new MllpInvalidAcknowledgementException(
+ "MSA Not found in acknowledgement", hl7MessageBytes, hl7AcknowledgementBytes, logPhi);
+ }
+ }
+
+ return acknowledgementType;
+ }
+
+ /**
+ * Validate the TCP Connection
+ *
+ * @return null if the connection is valid, otherwise the Exception encounted checking the connection
+ */
+ void checkConnection() throws Exception {
+
+ SSLContextParameters sslContextParameters = getEndpoint().getSslContextParameters();
+
+ if (null == socket || socket.isClosed() || !socket.isConnected()) {
+ logCurrentSocketState();
+
+ log.info("checkConnection() - Attempting to establish a new {} connection",
+ sslContextParameters != null ? "secure (SSL/TLS)" : "plain");
+
+ // The socket will be closed by close connection, resetConnection, etc
+ Socket newSocket = createNewSocket(sslContextParameters);
+
+ InetSocketAddress socketAddress = configureSocketAddress();
+
+ log.debug("checkConnection() - Connecting to {}", socketAddress);
+
+ newSocket.connect(socketAddress, getConfiguration().getConnectTimeout());
+ log.info("checkConnection() - Successfully established new {} connection to {}",
+ sslContextParameters != null ? "secure (SSL/TLS)" : "plain",
+ newSocket);
+ getEndpoint().updateLastConnectionEstablishedTicks();
+
+ socket = newSocket;
+
+ cacheAddresses();
+
+ if (getConfiguration().hasIdleTimeout()) {
+ log.debug("Scheduling initial idle producer connection check of {} in {} milliseconds", getConnectionAddress(),
+ getConfiguration().getIdleTimeout());
+ idleTimeoutExecutor.schedule(this, getConfiguration().getIdleTimeout(), TimeUnit.MILLISECONDS);
+ }
+ } else {
+ log.debug("checkConnection() - Connection {} is still valid - no new connection required", socket);
+ }
+ }
+
+ private void logCurrentSocketState() {
+ if (socket == null) {
+ log.debug("checkConnection() - Socket is null - attempting to establish connection");
+ } else if (socket.isClosed()) {
+ log.info("checkConnection() - Socket {} is closed - attempting to establish new connection", socket);
+ } else if (!socket.isConnected()) {
+ log.info("checkConnection() - Socket {} is not connected - attempting to establish new connection", socket);
+ }
+ }
+
+ private void cacheAddresses() {
+ SocketAddress localSocketAddress = socket.getLocalSocketAddress();
+ if (localSocketAddress != null) {
+ cachedLocalAddress = localSocketAddress.toString();
+ }
+ SocketAddress remoteSocketAddress = socket.getRemoteSocketAddress();
+ if (remoteSocketAddress != null) {
+ cachedRemoteAddress = remoteSocketAddress.toString();
+ }
+ cachedCombinedAddress = MllpSocketBuffer.formatAddressString(localSocketAddress, remoteSocketAddress);
+ }
+
+ private InetSocketAddress configureSocketAddress() {
+ InetSocketAddress socketAddress;
+ if (null == getEndpoint().getHostname()) {
+ socketAddress = new InetSocketAddress(getEndpoint().getPort());
+ } else {
+ socketAddress = new InetSocketAddress(getEndpoint().getHostname(), getEndpoint().getPort());
+ }
+ return socketAddress;
+ }
+
+ private Socket createNewSocket(final SSLContextParameters sslContextParameters) throws Exception {
+
+ Socket newSocket;
+
+ if (sslContextParameters != null) {
+ log.debug("Creating secure socket with SSLContextParameters");
+ // Create SSLContext from SSLContextParameters
+ SSLContext sslContext = sslContextParameters.createSSLContext(getEndpoint().getCamelContext());
+ SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
+ newSocket = sslSocketFactory.createSocket();
+ } else {
+ log.debug("Creating plain socket without SSLContextParameters");
+ newSocket = new Socket();
+ }
+
+ if (getConfiguration().hasKeepAlive()) {
+ newSocket.setKeepAlive(getConfiguration().getKeepAlive());
+ }
+ if (getConfiguration().hasTcpNoDelay()) {
+ newSocket.setTcpNoDelay(getConfiguration().getTcpNoDelay());
+ }
+
+ if (getConfiguration().hasReceiveBufferSize()) {
+ newSocket.setReceiveBufferSize(getConfiguration().getReceiveBufferSize());
+ }
+ if (getConfiguration().hasSendBufferSize()) {
+ newSocket.setSendBufferSize(getConfiguration().getSendBufferSize());
+ }
+ if (getConfiguration().hasReuseAddress()) {
+ newSocket.setReuseAddress(getConfiguration().getReuseAddress());
+ }
+
+ newSocket.setSoLinger(false, -1);
+ return newSocket;
+ }
+
+ /**
+ * Check for idle connection
+ */
+ @Override
+ public void run() {
+ lock.lock();
+ try {
+ if (getConfiguration().hasIdleTimeout()) {
+ if (null != socket && !socket.isClosed() && socket.isConnected()) {
+ if (getEndpoint().hasLastConnectionActivityTicks()) {
+ long idleTime = System.currentTimeMillis() - getEndpoint().getLastConnectionActivityTicks();
+ if (log.isDebugEnabled()) {
+ log.debug("Checking {} for idle connection: {} - {}", getConnectionAddress(), idleTime,
+ getConfiguration().getIdleTimeout());
+ }
+ if (idleTime >= getConfiguration().getIdleTimeout()) {
+ if (MllpIdleTimeoutStrategy.CLOSE == getConfiguration().getIdleTimeoutStrategy()) {
+ log.info(
+ "MLLP Connection idle time of '{}' milliseconds met or exceeded the idle producer timeout of '{}' milliseconds - closing connection",
+ idleTime, getConfiguration().getIdleTimeout());
+ mllpBuffer.closeSocket(socket);
+ } else {
+ log.info(
+ "MLLP Connection idle time of '{}' milliseconds met or exceeded the idle producer timeout of '{}' milliseconds - resetting connection",
+ idleTime, getConfiguration().getIdleTimeout());
+ mllpBuffer.resetSocket(socket);
+ }
+ } else {
+ long minDelay = 100;
+ long delay = Long.min(Long.max(minDelay, getConfiguration().getIdleTimeout() - idleTime),
+ getConfiguration().getIdleTimeout());
+ if (log.isDebugEnabled()) {
+ log.debug("Scheduling idle producer connection check of {} in {} milliseconds",
+ getConnectionAddress(), delay);
+ }
+ idleTimeoutExecutor.schedule(this, delay, TimeUnit.MILLISECONDS);
+ }
+ } else {
+ log.debug(
+ "No activity detected since initial connection - scheduling idle producer connection check in {} milliseconds",
+ getConfiguration().getIdleTimeout());
+ idleTimeoutExecutor.schedule(this, getConfiguration().getIdleTimeout(), TimeUnit.MILLISECONDS);
+ }
+ }
+ }
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ static class IdleTimeoutThreadFactory implements ThreadFactory {
+ final String endpointKey;
+
+ IdleTimeoutThreadFactory(String endpointKey) {
+ this.endpointKey = endpointKey;
+ }
+
+ @Override
+ public Thread newThread(Runnable r) {
+ Thread timeoutThread = Executors.defaultThreadFactory().newThread(r);
+
+ timeoutThread.setName(
+ String.format("%s[%s]-idle-timeout-thread", MllpTcpClientProducer.class.getSimpleName(), endpointKey));
+
+ return timeoutThread;
+ }
+ }
+
+ @Override
+ public MllpEndpoint getEndpoint() {
+ return (MllpEndpoint) super.getEndpoint();
+ }
+
+ public MllpConfiguration getConfiguration() {
+ return this.getEndpoint().getConfiguration();
+ }
+}
diff --git a/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpTcpServerConsumer.java b/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpTcpServerConsumer.java
index e97ffdda008..037b8e66be2 100644
--- a/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpTcpServerConsumer.java
+++ b/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/MllpTcpServerConsumer.java
@@ -155,7 +155,7 @@ public class MllpTcpServerConsumer extends DefaultConsumer {
@Override
protected void doStart() throws Exception {
if (bindThread == null || !bindThread.isAlive()) {
- bindThread = new TcpServerBindThread(this);
+ bindThread = new TcpServerBindThread(this, getEndpoint().getSslContextParameters());
if (getConfiguration().isLenientBind()) {
log.debug("doStart() - starting bind thread");
diff --git a/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/internal/Hl7Util.java b/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/internal/Hl7Util.java
index 355c42357ef..f60ef8c8dd6 100644
--- a/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/internal/Hl7Util.java
+++ b/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/internal/Hl7Util.java
@@ -106,7 +106,6 @@ public final class Hl7Util {
* allowed (and expected) because it is also the segment delimiter for an HL7 message
*
* @param hl7Bytes the HL7 payload to validate
- *
* @return If the payload is invalid, an error message suitable for inclusion in an exception is returned.
* If the payload is valid, null is returned;
*/
@@ -156,12 +155,11 @@ public final class Hl7Util {
/**
* Find the field separator indices in the Segment.
- *
+ * <p>
* NOTE: The last element of the list will be the index of the end of the segment.
*
* @param hl7MessageBytes the HL7 binary message
* @param startingIndex index of the beginning of the HL7 Segment
- *
* @return List of the field separator indices, which may be empty.
*/
public static List<Integer> findFieldSeparatorIndicesInSegment(byte[] hl7MessageBytes, int startingIndex) {
@@ -187,7 +185,6 @@ public final class Hl7Util {
* Find the String value of MSH-18 (Character set).
*
* @param hl7Message the HL7 binary data to search
- *
* @return the String value of MSH-18, or an empty String if not found.
*/
public String findMsh18(byte[] hl7Message, Charset charset) {
@@ -332,13 +329,12 @@ public final class Hl7Util {
/**
* Convert a PHI byte[] to a String, replacing specific non-printable characters with readable strings.
- *
+ * <p>
* NOTE: this conversion uses the default character set, so not all characters my convert correctly.
*
* @param phiBytes the PHI byte[] to log
* @param startPosition the starting position/index of the data
* @param endPosition the ending position/index of the data - will not be included in String
- *
* @return a String representation of the byte[]
*/
public String convertToPrintFriendlyString(byte[] phiBytes, int startPosition, int endPosition) {
@@ -347,11 +343,10 @@ public final class Hl7Util {
/**
* Convert a PHI byte[] to a StringBuilder, replacing specific non-printable characters with readable strings.
- *
+ * <p>
* NOTE: this conversion uses the default character set, so not all characters my convert correctly.
*
* @param phiBytes the PHI byte[] to log
- *
* @return
*/
public StringBuilder bytesToPrintFriendlyStringBuilder(byte[] phiBytes) {
@@ -360,13 +355,12 @@ public final class Hl7Util {
/**
* Convert a PHI byte[] to a StringBuilder, replacing specific non-printable characters with readable strings.
- *
+ * <p>
* NOTE: this conversion uses the default character set, so not all characters my convert correctly.
*
* @param phiBytes the PHI byte[] to log
* @param startPosition the starting position/index of the data
* @param endPosition the ending position/index of the data - will not be included in StringBuilder
- *
* @return a String representation of the byte[]
*/
public StringBuilder bytesToPrintFriendlyStringBuilder(
@@ -384,7 +378,7 @@ public final class Hl7Util {
/**
* Append a PHI byte[] to a StringBuilder, replacing specific non-printable characters with readable strings.
- *
+ * <p>
* NOTE: this conversion uses the default character set, so not all characters my convert correctly.
*
* @param phiBytes the PHI byte[] to log
@@ -445,7 +439,7 @@ public final class Hl7Util {
/**
* Copy a field from the HL7 Message Bytes to the supplied MllpSocketBuffer.
- *
+ * <p>
* NOTE: Internal function - no error checking
*
* @param mllpSocketBuffer the destination for the field
diff --git a/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/internal/TcpServerBindThread.java b/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/internal/TcpServerBindThread.java
index ca3e24d3cbd..27a25e043cf 100644
--- a/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/internal/TcpServerBindThread.java
+++ b/components/camel-mllp/src/main/java/org/apache/camel/component/mllp/internal/TcpServerBindThread.java
@@ -20,11 +20,16 @@ import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.SocketException;
+import java.security.GeneralSecurityException;
import java.time.Duration;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLServerSocketFactory;
+
import org.apache.camel.Route;
import org.apache.camel.component.mllp.MllpTcpServerConsumer;
import org.apache.camel.spi.UnitOfWork;
+import org.apache.camel.support.jsse.SSLContextParameters;
import org.apache.camel.support.task.BlockingTask;
import org.apache.camel.support.task.Tasks;
import org.apache.camel.support.task.budget.Budgets;
@@ -39,9 +44,12 @@ import org.slf4j.MDC;
public class TcpServerBindThread extends Thread {
private final Logger log = LoggerFactory.getLogger(this.getClass());
private final MllpTcpServerConsumer consumer;
+ private final SSLContextParameters sslContextParameters;
+
+ public TcpServerBindThread(MllpTcpServerConsumer consumer, final SSLContextParameters sslParams) {
- public TcpServerBindThread(MllpTcpServerConsumer consumer) {
this.consumer = consumer;
+ this.sslContextParameters = sslParams;
// Get the URI without options
String fullEndpointKey = consumer.getEndpoint().getEndpointKey();
@@ -68,7 +76,15 @@ public class TcpServerBindThread extends Thread {
try {
// Note: this socket is going to be closed in the TcpServerAcceptThread instance
// launched by the consumer
- ServerSocket serverSocket = new ServerSocket();
+ ServerSocket serverSocket;
+ if (sslContextParameters != null) {
+ log.debug("Initializing SSLContextParameters");
+ SSLContext sslContext = sslContextParameters.createSSLContext(consumer.getEndpoint().getCamelContext());
+ SSLServerSocketFactory sslServerSocketFactory = sslContext.getServerSocketFactory();
+ serverSocket = sslServerSocketFactory.createServerSocket();
+ } else {
+ serverSocket = new ServerSocket();
+ }
InetSocketAddress socketAddress = setupSocket(serverSocket);
log.debug("Attempting to bind to {}", socketAddress);
@@ -76,6 +92,9 @@ public class TcpServerBindThread extends Thread {
doAccept(serverSocket, socketAddress);
} catch (IOException ioEx) {
log.error("Unexpected exception encountered initializing ServerSocket before attempting to bind", ioEx);
+ } catch (GeneralSecurityException e) {
+ log.error("Error creating SSLContext for secure server socket", e);
+ throw new RuntimeException("SSLContext initialization failed", e);
}
}
diff --git a/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpAcknowledgementDeliveryExceptionTest.java b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpAcknowledgementDeliveryExceptionTest.java
index b2e52bb0fee..9b52ed6aa48 100644
--- a/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpAcknowledgementDeliveryExceptionTest.java
+++ b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpAcknowledgementDeliveryExceptionTest.java
@@ -32,7 +32,6 @@ public class MllpAcknowledgementDeliveryExceptionTest extends MllpExceptionTestS
/**
* Description of test.
- *
*/
@Test
public void testConstructorOne() {
@@ -45,7 +44,6 @@ public class MllpAcknowledgementDeliveryExceptionTest extends MllpExceptionTestS
/**
* Description of test.
- *
*/
@Test
public void testConstructorTwo() {
@@ -59,7 +57,6 @@ public class MllpAcknowledgementDeliveryExceptionTest extends MllpExceptionTestS
/**
* Description of test.
- *
*/
@Test
public void testConstructorThree() {
@@ -75,7 +72,6 @@ public class MllpAcknowledgementDeliveryExceptionTest extends MllpExceptionTestS
/**
* Description of test.
- *
*/
@Test
public void testConstructorFour() {
diff --git a/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpAcknowledgementExceptionTest.java b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpAcknowledgementExceptionTest.java
index 12e4eaaf0ff..a65cc595578 100644
--- a/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpAcknowledgementExceptionTest.java
+++ b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpAcknowledgementExceptionTest.java
@@ -33,7 +33,6 @@ public class MllpAcknowledgementExceptionTest extends MllpExceptionTestSupport {
/**
* Description of test.
- *
*/
@Test
public void testConstructorOne() {
@@ -47,7 +46,6 @@ public class MllpAcknowledgementExceptionTest extends MllpExceptionTestSupport {
/**
* Description of test.
- *
*/
@Test
public void testConstructorTwo() {
@@ -61,7 +59,6 @@ public class MllpAcknowledgementExceptionTest extends MllpExceptionTestSupport {
/**
* Description of test.
- *
*/
@Test
public void testConstructorThree() {
@@ -75,7 +72,6 @@ public class MllpAcknowledgementExceptionTest extends MllpExceptionTestSupport {
/**
* Description of test.
- *
*/
@Test
public void testConstructorFour() {
@@ -90,7 +86,6 @@ public class MllpAcknowledgementExceptionTest extends MllpExceptionTestSupport {
/**
* Description of test.
- *
*/
@Test
public void testConstructorFive() {
@@ -104,7 +99,6 @@ public class MllpAcknowledgementExceptionTest extends MllpExceptionTestSupport {
/**
* Description of test.
- *
*/
@Test
public void testConstructorSix() {
diff --git a/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpAcknowledgementReceiveExceptionTest.java b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpAcknowledgementReceiveExceptionTest.java
index 76a9722ad06..ac9f54d9d3b 100644
--- a/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpAcknowledgementReceiveExceptionTest.java
+++ b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpAcknowledgementReceiveExceptionTest.java
@@ -33,7 +33,6 @@ public class MllpAcknowledgementReceiveExceptionTest extends MllpExceptionTestSu
/**
* Description of test.
- *
*/
@Test
public void testConstructorOne() {
@@ -47,7 +46,6 @@ public class MllpAcknowledgementReceiveExceptionTest extends MllpExceptionTestSu
/**
* Description of test.
- *
*/
@Test
public void testConstructorTwo() {
@@ -61,7 +59,6 @@ public class MllpAcknowledgementReceiveExceptionTest extends MllpExceptionTestSu
/**
* Description of test.
- *
*/
@Test
public void testConstructorThree() {
@@ -75,7 +72,6 @@ public class MllpAcknowledgementReceiveExceptionTest extends MllpExceptionTestSu
/**
* Description of test.
- *
*/
@Test
public void testConstructorFour() {
@@ -89,7 +85,6 @@ public class MllpAcknowledgementReceiveExceptionTest extends MllpExceptionTestSu
/**
* Description of test.
- *
*/
@Test
public void testConstructorFive() {
@@ -103,7 +98,6 @@ public class MllpAcknowledgementReceiveExceptionTest extends MllpExceptionTestSu
/**
* Description of test.
- *
*/
@Test
public void testConstructorSix() {
@@ -118,7 +112,6 @@ public class MllpAcknowledgementReceiveExceptionTest extends MllpExceptionTestSu
/**
* Description of test.
- *
*/
@Test
public void testConstructorSeven() {
@@ -132,7 +125,6 @@ public class MllpAcknowledgementReceiveExceptionTest extends MllpExceptionTestSu
/**
* Description of test.
- *
*/
@Test
public void testConstructorEight() {
diff --git a/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpAcknowledgementTimeoutExceptionTest.java b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpAcknowledgementTimeoutExceptionTest.java
index dadbd11c7bf..fd14268f484 100644
--- a/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpAcknowledgementTimeoutExceptionTest.java
+++ b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpAcknowledgementTimeoutExceptionTest.java
@@ -33,7 +33,6 @@ public class MllpAcknowledgementTimeoutExceptionTest extends MllpExceptionTestSu
/**
* Description of test.
- *
*/
@Test
public void testConstructorOne() {
@@ -47,7 +46,6 @@ public class MllpAcknowledgementTimeoutExceptionTest extends MllpExceptionTestSu
/**
* Description of test.
- *
*/
@Test
public void testConstructorTwo() {
@@ -61,7 +59,6 @@ public class MllpAcknowledgementTimeoutExceptionTest extends MllpExceptionTestSu
/**
* Description of test.
- *
*/
@Test
public void testConstructorThree() {
@@ -75,7 +72,6 @@ public class MllpAcknowledgementTimeoutExceptionTest extends MllpExceptionTestSu
/**
* Description of test.
- *
*/
@Test
public void testConstructorFour() {
@@ -89,7 +85,6 @@ public class MllpAcknowledgementTimeoutExceptionTest extends MllpExceptionTestSu
/**
* Description of test.
- *
*/
@Test
public void testConstructorFive() {
@@ -103,7 +98,6 @@ public class MllpAcknowledgementTimeoutExceptionTest extends MllpExceptionTestSu
/**
* Description of test.
- *
*/
@Test
public void testConstructorSix() {
@@ -118,7 +112,6 @@ public class MllpAcknowledgementTimeoutExceptionTest extends MllpExceptionTestSu
/**
* Description of test.
- *
*/
@Test
public void testConstructorSeven() {
@@ -132,7 +125,6 @@ public class MllpAcknowledgementTimeoutExceptionTest extends MllpExceptionTestSu
/**
* Description of test.
- *
*/
@Test
public void testConstructorEight() {
@@ -147,7 +139,6 @@ public class MllpAcknowledgementTimeoutExceptionTest extends MllpExceptionTestSu
/**
* Description of test.
- *
*/
@Test
public void testGetHl7Acknowledgement() {
diff --git a/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpApplicationErrorAcknowledgementExceptionTest.java b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpApplicationErrorAcknowledgementExceptionTest.java
index 88cb4efbd50..af631398bc6 100644
--- a/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpApplicationErrorAcknowledgementExceptionTest.java
+++ b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpApplicationErrorAcknowledgementExceptionTest.java
@@ -32,7 +32,6 @@ public class MllpApplicationErrorAcknowledgementExceptionTest extends MllpExcept
/**
* Description of test.
- *
*/
@Test
public void testConstructorOne() {
@@ -46,7 +45,6 @@ public class MllpApplicationErrorAcknowledgementExceptionTest extends MllpExcept
/**
* Description of test.
- *
*/
@Test
public void testConstructorTwo() {
@@ -61,7 +59,6 @@ public class MllpApplicationErrorAcknowledgementExceptionTest extends MllpExcept
/**
* Description of test.
- *
*/
@Test
public void testGetAcknowledgmentType() {
diff --git a/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpApplicationRejectAcknowledgementExceptionTest.java b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpApplicationRejectAcknowledgementExceptionTest.java
index dd373110c21..91b49b6a6c6 100644
--- a/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpApplicationRejectAcknowledgementExceptionTest.java
+++ b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpApplicationRejectAcknowledgementExceptionTest.java
@@ -32,7 +32,6 @@ public class MllpApplicationRejectAcknowledgementExceptionTest extends MllpExcep
/**
* Description of test.
- *
*/
@Test
public void testConstructorOne() {
@@ -47,7 +46,6 @@ public class MllpApplicationRejectAcknowledgementExceptionTest extends MllpExcep
/**
* Description of test.
- *
*/
@Test
public void testConstructorTwo() {
@@ -62,7 +60,6 @@ public class MllpApplicationRejectAcknowledgementExceptionTest extends MllpExcep
/**
* Description of test.
- *
*/
@Test
public void testGetAcknowledgmentType() {
diff --git a/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpCommitErrorAcknowledgementExceptionTest.java b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpCommitErrorAcknowledgementExceptionTest.java
index 6c493d07fa6..9edd6cb6cf4 100644
--- a/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpCommitErrorAcknowledgementExceptionTest.java
+++ b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpCommitErrorAcknowledgementExceptionTest.java
@@ -32,7 +32,6 @@ public class MllpCommitErrorAcknowledgementExceptionTest extends MllpExceptionTe
/**
* Description of test.
- *
*/
@Test
public void testConstructorOne() {
@@ -46,7 +45,6 @@ public class MllpCommitErrorAcknowledgementExceptionTest extends MllpExceptionTe
/**
* Description of test.
- *
*/
@Test
public void testConstructorTwo() {
@@ -61,7 +59,6 @@ public class MllpCommitErrorAcknowledgementExceptionTest extends MllpExceptionTe
/**
* Description of test.
- *
*/
@Test
public void testGetAcknowledgmentType() {
diff --git a/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpCommitRejectAcknowledgementExceptionTest.java b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpCommitRejectAcknowledgementExceptionTest.java
index f386bd561e3..0700f906e5a 100644
--- a/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpCommitRejectAcknowledgementExceptionTest.java
+++ b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpCommitRejectAcknowledgementExceptionTest.java
@@ -32,7 +32,6 @@ public class MllpCommitRejectAcknowledgementExceptionTest extends MllpExceptionT
/**
* Description of test.
- *
*/
@Test
public void testConstructorOne() {
@@ -46,7 +45,6 @@ public class MllpCommitRejectAcknowledgementExceptionTest extends MllpExceptionT
/**
* Description of test.
- *
*/
@Test
public void testConstructorTwo() {
@@ -61,7 +59,6 @@ public class MllpCommitRejectAcknowledgementExceptionTest extends MllpExceptionT
/**
* Description of test.
- *
*/
@Test
public void testGetAcknowledgmentType() {
diff --git a/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpEndpointTest.java b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpEndpointTest.java
index e6eb5fb7a39..78b8b2b0981 100644
--- a/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpEndpointTest.java
+++ b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpEndpointTest.java
@@ -16,6 +16,9 @@
*/
package org.apache.camel.component.mllp;
+import org.apache.camel.support.jsse.KeyManagersParameters;
+import org.apache.camel.support.jsse.KeyStoreParameters;
+import org.apache.camel.support.jsse.SSLContextParameters;
import org.apache.camel.test.junit5.CamelTestSupport;
import org.junit.jupiter.api.Test;
@@ -82,4 +85,30 @@ public class MllpEndpointTest extends CamelTestSupport {
assertEquals(resetStrategy, upperCaseResetStrategyEndpoint.getConfiguration().getIdleTimeoutStrategy());
}
+ /**
+ * Assert that an endpoint with SSLContextParameters can be created successfully.
+ */
+ @Test
+ public void testCreateEndpointWithSslContextParameters() throws Exception {
+ // Create a dummy SSLContextParameters object with minimal setup
+ SSLContextParameters sslContextParameters = new SSLContextParameters();
+ KeyManagersParameters keyManagers = new KeyManagersParameters();
+ KeyStoreParameters keyStore = new KeyStoreParameters();
+ keyStore.setResource("dummy.keystore"); // Dummy placeholder, won't be used
+ keyStore.setPassword("dummyPassword");
+ keyManagers.setKeyPassword("dummyKeyPassword");
+ keyManagers.setKeyStore(keyStore);
+ sslContextParameters.setKeyManagers(keyManagers);
+
+ // Bind the SSLContextParameters to the Camel registry
+ context.getRegistry().bind("mySslContext", sslContextParameters);
+
+ // Create the endpoint using SSLContextParameters
+ MllpComponent mllpComponent = context.getComponent("mllp", MllpComponent.class);
+ MllpEndpoint sslEndpoint
+ = (MllpEndpoint) mllpComponent.createEndpoint("mllp://dummy:1234?sslContextParameters=#mySslContext");
+
+ // Verify that the SSLContextParameters were set correctly
+ assertEquals(sslContextParameters, sslEndpoint.getConfiguration().getSslContextParameters());
+ }
}
diff --git a/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpGlobalAndExplicitSSLContextParametersTest.java b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpGlobalAndExplicitSSLContextParametersTest.java
new file mode 100644
index 00000000000..c99133773e4
--- /dev/null
+++ b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpGlobalAndExplicitSSLContextParametersTest.java
@@ -0,0 +1,126 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.mllp;
+
+import org.apache.camel.*;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.support.jsse.KeyManagersParameters;
+import org.apache.camel.support.jsse.KeyStoreParameters;
+import org.apache.camel.support.jsse.SSLContextParameters;
+import org.apache.camel.support.jsse.TrustManagersParameters;
+import org.apache.camel.test.AvailablePortFinder;
+import org.apache.camel.test.junit.rule.mllp.MllpClientResource;
+import org.apache.camel.test.junit5.CamelTestSupport;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+public class MllpGlobalAndExplicitSSLContextParametersTest extends CamelTestSupport {
+
+ @RegisterExtension
+ public MllpClientResource mllpClient = new MllpClientResource();
+
+ @EndpointInject("mock:result")
+ MockEndpoint result;
+
+ private SSLContextParameters createGlobalSslContextParameters() {
+ KeyStoreParameters ksp = new KeyStoreParameters();
+ ksp.setResource(this.getClass().getClassLoader().getResource("keystore.jks").toString());
+ ksp.setPassword("password");
+
+ KeyManagersParameters kmp = new KeyManagersParameters();
+ kmp.setKeyPassword("password");
+ kmp.setKeyStore(ksp);
+
+ TrustManagersParameters tmp = new TrustManagersParameters();
+ tmp.setKeyStore(ksp);
+
+ SSLContextParameters sslContextParameters = new SSLContextParameters();
+ sslContextParameters.setKeyManagers(kmp);
+ sslContextParameters.setTrustManagers(tmp);
+
+ return sslContextParameters;
+ }
+
+ private SSLContextParameters createExplicitSslContextParameters() {
+ KeyStoreParameters ksp = new KeyStoreParameters();
+ ksp.setResource(this.getClass().getClassLoader().getResource("keystore.jks").toString());
+ ksp.setPassword("password");
+
+ KeyManagersParameters kmp = new KeyManagersParameters();
+ kmp.setKeyPassword("password");
+ kmp.setKeyStore(ksp);
+
+ TrustManagersParameters tmp = new TrustManagersParameters();
+ tmp.setKeyStore(ksp);
+
+ SSLContextParameters sslContextParameters = new SSLContextParameters();
+ sslContextParameters.setKeyManagers(kmp);
+ sslContextParameters.setTrustManagers(tmp);
+
+ return sslContextParameters;
+ }
+
+ @Override
+ protected CamelContext createCamelContext() throws Exception {
+ DefaultCamelContext context = (DefaultCamelContext) super.createCamelContext();
+ mllpClient.setMllpHost("localhost");
+ mllpClient.setMllpPort(AvailablePortFinder.getNextAvailable());
+
+ // Set global SSLContextParameters
+ SSLContextParameters globalSslContextParameters = createGlobalSslContextParameters();
+ context.setSSLContextParameters(globalSslContextParameters);
+
+ // Bind explicit SSLContextParameters for the receiving endpoint
+ SSLContextParameters explicitSslContextParameters = createExplicitSslContextParameters();
+ context.getRegistry().bind("explicitSslContextParameters", explicitSslContextParameters);
+ ((SSLContextParametersAware) context.getComponent("mllp")).setUseGlobalSslContextParameters(true);
+ return context;
+ }
+
+ @Override
+ protected RouteBuilder createRouteBuilder() {
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ // Receiving endpoint explicitly defines SSLContextParameters
+ fromF("mllp://%s:%d?sslContextParameters=#explicitSslContextParameters", mllpClient.getMllpHost(),
+ mllpClient.getMllpPort())
+ .log(LoggingLevel.INFO, "Received Message: ${body}")
+ .to("mock:result");
+ }
+ };
+ }
+
+ @Test
+ public void testGlobalAndExplicitSslContextParameters() throws Exception {
+ String hl7Message = "MSH|^~\\&|CLIENT|TEST|SERVER|ACK|20231118120000||ADT^A01|123456|T|2.6\r" +
+ "EVN|A01|20231118120000\r" +
+ "PID|1|12345|67890||DOE^JOHN||19800101|M|||123 Main St^^Springfield^IL^62704||(555)555-5555|||||S\r"
+ +
+ "PV1|1|O\r";
+
+ result.expectedBodiesReceived(hl7Message);
+
+ String endpointUri = String.format("mllp://%s:%d", mllpClient.getMllpHost(), mllpClient.getMllpPort());
+ template.sendBody(endpointUri, hl7Message);
+ // template.sendBody("direct:start", hl7Message);
+
+ result.assertIsSatisfied();
+ }
+}
diff --git a/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpInvalidAcknowledgementExceptionTest.java b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpInvalidAcknowledgementExceptionTest.java
index 42777e2d22b..c94ec9848ae 100644
--- a/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpInvalidAcknowledgementExceptionTest.java
+++ b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpInvalidAcknowledgementExceptionTest.java
@@ -33,7 +33,6 @@ public class MllpInvalidAcknowledgementExceptionTest extends MllpExceptionTestSu
/**
* Description of test.
- *
*/
@Test
public void testConstructorOne() {
@@ -48,7 +47,6 @@ public class MllpInvalidAcknowledgementExceptionTest extends MllpExceptionTestSu
/**
* Description of test.
- *
*/
@Test
public void testConstructorTwo() {
diff --git a/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpInvalidMessageExceptionTest.java b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpInvalidMessageExceptionTest.java
index 955a107c267..abec3fede70 100644
--- a/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpInvalidMessageExceptionTest.java
+++ b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpInvalidMessageExceptionTest.java
@@ -33,7 +33,6 @@ public class MllpInvalidMessageExceptionTest extends MllpExceptionTestSupport {
/**
* Description of test.
- *
*/
@Test
public void testConstructorOne() {
@@ -47,7 +46,6 @@ public class MllpInvalidMessageExceptionTest extends MllpExceptionTestSupport {
/**
* Description of test.
- *
*/
@Test
public void testConstructorTwo() {
diff --git a/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpNegativeAcknowledgementExceptionTest.java b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpNegativeAcknowledgementExceptionTest.java
index 2edab4415bf..73b008bfeaf 100644
--- a/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpNegativeAcknowledgementExceptionTest.java
+++ b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpNegativeAcknowledgementExceptionTest.java
@@ -33,7 +33,6 @@ public class MllpNegativeAcknowledgementExceptionTest extends MllpExceptionTestS
/**
* Description of test.
- *
*/
@Test
public void testConstructorOne() {
@@ -48,7 +47,6 @@ public class MllpNegativeAcknowledgementExceptionTest extends MllpExceptionTestS
/**
* Description of test.
- *
*/
@Test
public void testConstructorTwo() {
@@ -63,7 +61,6 @@ public class MllpNegativeAcknowledgementExceptionTest extends MllpExceptionTestS
/**
* Description of test.
- *
*/
@Test
public void testGetAcknowledgmentType() {
diff --git a/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpReceiveExceptionTest.java b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpReceiveExceptionTest.java
index 78c75c91096..b4c460579a9 100644
--- a/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpReceiveExceptionTest.java
+++ b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpReceiveExceptionTest.java
@@ -33,7 +33,6 @@ public class MllpReceiveExceptionTest extends MllpExceptionTestSupport {
/**
* Description of test.
- *
*/
@Test
public void testConstructorOne() {
@@ -47,7 +46,6 @@ public class MllpReceiveExceptionTest extends MllpExceptionTestSupport {
/**
* Description of test.
- *
*/
@Test
public void testConstructorTwo() {
@@ -61,7 +59,6 @@ public class MllpReceiveExceptionTest extends MllpExceptionTestSupport {
/**
* Description of test.
- *
*/
@Test
public void testConstructorThree() {
@@ -75,7 +72,6 @@ public class MllpReceiveExceptionTest extends MllpExceptionTestSupport {
/**
* Description of test.
- *
*/
@Test
public void testConstructorFour() {
@@ -89,7 +85,6 @@ public class MllpReceiveExceptionTest extends MllpExceptionTestSupport {
/**
* Description of test.
- *
*/
@Test
public void testConstructorFive() {
@@ -103,7 +98,6 @@ public class MllpReceiveExceptionTest extends MllpExceptionTestSupport {
/**
* Description of test.
- *
*/
@Test
public void testConstructorSix() {
diff --git a/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpSSLContextParametersTest.java b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpSSLContextParametersTest.java
new file mode 100644
index 00000000000..2285fc9f6a7
--- /dev/null
+++ b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpSSLContextParametersTest.java
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.mllp;
+
+import org.apache.camel.*;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.support.jsse.KeyManagersParameters;
+import org.apache.camel.support.jsse.KeyStoreParameters;
+import org.apache.camel.support.jsse.SSLContextParameters;
+import org.apache.camel.support.jsse.TrustManagersParameters;
+import org.apache.camel.test.AvailablePortFinder;
+import org.apache.camel.test.junit.rule.mllp.MllpClientResource;
+import org.apache.camel.test.junit5.CamelTestSupport;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+public class MllpSSLContextParametersTest extends CamelTestSupport {
+
+ @RegisterExtension
+ public MllpClientResource mllpClient = new MllpClientResource();
+
+ @EndpointInject("mock://result")
+ MockEndpoint result;
+
+ public SSLContextParameters createSslContextParameters() {
+ KeyStoreParameters ksp = new KeyStoreParameters();
+ ksp.setResource(this.getClass().getClassLoader().getResource("keystore.jks").toString());
+ ksp.setPassword("password");
+
+ KeyManagersParameters kmp = new KeyManagersParameters();
+ kmp.setKeyPassword("password");
+ kmp.setKeyStore(ksp);
+
+ TrustManagersParameters tmp = new TrustManagersParameters();
+ tmp.setKeyStore(ksp);
+
+ SSLContextParameters sslContextParameters = new SSLContextParameters();
+ sslContextParameters.setKeyManagers(kmp);
+ sslContextParameters.setTrustManagers(tmp);
+
+ return sslContextParameters;
+ }
+
+ @Override
+ protected CamelContext createCamelContext() throws Exception {
+ mllpClient.setMllpHost("localhost");
+ mllpClient.setMllpPort(AvailablePortFinder.getNextAvailable());
+
+ DefaultCamelContext context = (DefaultCamelContext) super.createCamelContext();
+
+ context.setUseMDCLogging(true);
+ context.getCamelContextExtension().setName(this.getClass().getSimpleName());
+
+ SSLContextParameters sslContextParameters = createSslContextParameters();
+ context.getRegistry().bind("sslContextParameters", sslContextParameters);
+
+ return context;
+ }
+
+ @Override
+ protected RouteBuilder createRouteBuilder() {
+ return new RouteBuilder() {
+ String routeId = "mllp-ssl-sender";
+
+ public void configure() {
+ fromF("mllp://%d?sslContextParameters=#sslContextParameters", mllpClient.getMllpPort())
+ .log(LoggingLevel.INFO, routeId, "Received Message: ${body}")
+ .to(result);
+ }
+ };
+ }
+
+ @Test
+ public void testSSLInOutWithMllpConsumer() throws Exception {
+
+ String hl7Message = "MSH|^~\\&|CLIENT|TEST|SERVER|ACK|20231118120000||ADT^A01|123456|T|2.6\r" +
+ "EVN|A01|20231118120000\r" +
+ "PID|1|12345|67890||DOE^JOHN||19800101|M|||123 Main St^^Springfield^IL^62704||(555)555-5555|||||S\r"
+ +
+ "PV1|1|O\r";
+
+ result.expectedBodiesReceived(hl7Message);
+
+ String endpointUri = String.format("mllp://%s:%d?sslContextParameters=#sslContextParameters",
+ mllpClient.getMllpHost(), mllpClient.getMllpPort());
+ template.sendBody(endpointUri, hl7Message);
+ result.assertIsSatisfied();
+
+ }
+
+}
diff --git a/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpSocketExceptionTest.java b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpSocketExceptionTest.java
index 92ccb892aa5..56680db78d3 100644
--- a/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpSocketExceptionTest.java
+++ b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpSocketExceptionTest.java
@@ -32,7 +32,6 @@ public class MllpSocketExceptionTest extends MllpExceptionTestSupport {
/**
* Description of test.
- *
*/
@Test
public void testConstructorOne() {
@@ -44,7 +43,6 @@ public class MllpSocketExceptionTest extends MllpExceptionTestSupport {
/**
* Description of test.
- *
*/
@Test
public void testConstructorTwo() {
diff --git a/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpWriteExceptionTest.java b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpWriteExceptionTest.java
index c34fac5f278..20ca0340f94 100644
--- a/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpWriteExceptionTest.java
+++ b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/MllpWriteExceptionTest.java
@@ -33,7 +33,6 @@ public class MllpWriteExceptionTest extends MllpExceptionTestSupport {
/**
* Description of test.
- *
*/
@Test
public void testConstructorOne() {
@@ -47,7 +46,6 @@ public class MllpWriteExceptionTest extends MllpExceptionTestSupport {
/**
* Description of test.
- *
*/
@Test
public void testConstructorTwo() {
@@ -61,7 +59,6 @@ public class MllpWriteExceptionTest extends MllpExceptionTestSupport {
/**
* Description of test.
- *
*/
@Test
public void testConstructorThree() {
@@ -75,7 +72,6 @@ public class MllpWriteExceptionTest extends MllpExceptionTestSupport {
/**
* Description of test.
- *
*/
@Test
public void testConstructorFour() {
diff --git a/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/TcpClientProducerEndOfDataAndValidationTestSupport.java b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/TcpClientProducerEndOfDataAndValidationTestSupport.java
index be9db9cc26a..81ccbaf29ee 100644
--- a/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/TcpClientProducerEndOfDataAndValidationTestSupport.java
+++ b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/TcpClientProducerEndOfDataAndValidationTestSupport.java
@@ -487,7 +487,6 @@ public abstract class TcpClientProducerEndOfDataAndValidationTestSupport extends
/**
* NOTE: Set expectation variables BEFORE calling this method.
- *
*/
protected void runInvalidAcknowledgementContainingEmbeddedEndOfBlockByte() {
final String badAcknowledgement = EXPECTED_AA.replaceFirst("RISTECH", "RISTECH" + MllpProtocolConstants.END_OF_BLOCK);
diff --git a/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/internal/Hl7UtilTest.java b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/internal/Hl7UtilTest.java
index f4b17f64d01..d729b4ccdb4 100644
--- a/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/internal/Hl7UtilTest.java
+++ b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/internal/Hl7UtilTest.java
@@ -221,7 +221,6 @@ public class Hl7UtilTest {
/**
* Description of test.
- *
*/
@Test
public void testGenerateAcknowledgementPayloadFromNullMessage() {
@@ -232,7 +231,6 @@ public class Hl7UtilTest {
/**
* Description of test.
- *
*/
@Test
public void testGenerateAcknowledgementPayloadFromEmptyMessage() {
@@ -243,7 +241,6 @@ public class Hl7UtilTest {
/**
* Description of test.
- *
*/
@Test
public void testGenerateAcknowledgementPayloadWithoutEnoughFields() {
@@ -278,7 +275,6 @@ public class Hl7UtilTest {
/**
* Description of test.
- *
*/
@Test
public void testConvertStringToPrintFriendlyString() {
@@ -289,7 +285,6 @@ public class Hl7UtilTest {
/**
* Description of test.
- *
*/
@Test
public void testConvertBytesToPrintFriendlyString() {
@@ -300,7 +295,6 @@ public class Hl7UtilTest {
/**
* Description of test.
- *
*/
@Test
public void testConvertBytesToPrintFriendlyStringWithStartAndEndPositions() {
@@ -351,7 +345,6 @@ public class Hl7UtilTest {
/**
* Description of test.
- *
*/
@Test
public void testBytesToPrintFriendlyStringBuilder() {
@@ -362,7 +355,6 @@ public class Hl7UtilTest {
/**
* Description of test.
- *
*/
@Test
public void testBytesToPrintFriendlyStringBuilderWithStartAndEndPositions() {
@@ -432,7 +424,6 @@ public class Hl7UtilTest {
/**
* Description of test.
- *
*/
@Test
public void testAppendBytesAsPrintFriendlyString() {
@@ -460,7 +451,6 @@ public class Hl7UtilTest {
/**
* Description of test.
- *
*/
@Test
public void testAppendBytesAsPrintFriendlyStringWithStartAndEndPositions() {
@@ -600,7 +590,6 @@ public class Hl7UtilTest {
/**
* Description of test.
- *
*/
@Test
public void testAppendCharacterAsPrintFriendlyString() {
diff --git a/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/internal/MllpSocketBufferTest.java b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/internal/MllpSocketBufferTest.java
index 52cbeff91d2..b755bf5cf2c 100644
--- a/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/internal/MllpSocketBufferTest.java
+++ b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/internal/MllpSocketBufferTest.java
@@ -32,7 +32,6 @@ import static org.junit.jupiter.api.Assertions.fail;
public class MllpSocketBufferTest extends SocketBufferTestSupport {
/**
* Description of test.
- *
*/
@Test
public void testConstructorWithNullEndpoing() {
@@ -287,7 +286,6 @@ public class MllpSocketBufferTest extends SocketBufferTestSupport {
/**
* Description of test.
- *
*/
@Test
public void testGetStartOfBlockIndex() {
@@ -305,7 +303,6 @@ public class MllpSocketBufferTest extends SocketBufferTestSupport {
/**
* Description of test.
- *
*/
@Test
public void tesGgetEndOfBlockIndex() {
@@ -323,7 +320,6 @@ public class MllpSocketBufferTest extends SocketBufferTestSupport {
/**
* Description of test.
- *
*/
@Test
public void testHasCompleteEnvelopeWithRequiredEndOfData() {
@@ -348,7 +344,6 @@ public class MllpSocketBufferTest extends SocketBufferTestSupport {
/**
* Description of test.
- *
*/
@Test
public void testHasCompleteEnvelopeWithOptionalEndOfData() {
@@ -373,7 +368,6 @@ public class MllpSocketBufferTest extends SocketBufferTestSupport {
/**
* Description of test.
- *
*/
@Test
public void testHasStartOfBlock() {
@@ -397,7 +391,6 @@ public class MllpSocketBufferTest extends SocketBufferTestSupport {
/**
* Description of test.
- *
*/
@Test
public void testHasEndOfBlock() {
@@ -439,7 +432,6 @@ public class MllpSocketBufferTest extends SocketBufferTestSupport {
/**
* Description of test.
- *
*/
@Test
public void testHasEndOfData() {
diff --git a/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/internal/MllpSocketBufferWriteTest.java b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/internal/MllpSocketBufferWriteTest.java
index ab4100f03de..8876083b488 100644
--- a/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/internal/MllpSocketBufferWriteTest.java
+++ b/components/camel-mllp/src/test/java/org/apache/camel/component/mllp/internal/MllpSocketBufferWriteTest.java
@@ -38,7 +38,6 @@ public class MllpSocketBufferWriteTest extends SocketBufferTestSupport {
/**
* Description of test.
- *
*/
@Test
public void testWriteIntWithStartOfBlock() {
@@ -51,7 +50,6 @@ public class MllpSocketBufferWriteTest extends SocketBufferTestSupport {
/**
* Description of test.
- *
*/
@Test
public void testWriteIntWithEndOfBlock() {
@@ -64,7 +62,6 @@ public class MllpSocketBufferWriteTest extends SocketBufferTestSupport {
/**
* Description of test.
- *
*/
@Test
public void testWriteIntWithEndOfData() {
@@ -77,7 +74,6 @@ public class MllpSocketBufferWriteTest extends SocketBufferTestSupport {
/**
* Description of test.
- *
*/
@Test
public void testWriteBytesWithNullArray() {
@@ -90,7 +86,6 @@ public class MllpSocketBufferWriteTest extends SocketBufferTestSupport {
/**
* Description of test.
- *
*/
@Test
public void testWriteBytesWithEmptyArray() {
@@ -117,7 +112,6 @@ public class MllpSocketBufferWriteTest extends SocketBufferTestSupport {
/**
* Description of test.
- *
*/
@Test
public void testWriteBytesWithoutEnvelope() {
@@ -186,7 +180,6 @@ public class MllpSocketBufferWriteTest extends SocketBufferTestSupport {
/**
* Description of test.
- *
*/
@Test
public void testWriteByteArraySliceWithNullArray() {
@@ -199,7 +192,6 @@ public class MllpSocketBufferWriteTest extends SocketBufferTestSupport {
/**
* Description of test.
- *
*/
@Test
public void testWriteByteArraySliceWithEmptyArray() {
@@ -212,7 +204,6 @@ public class MllpSocketBufferWriteTest extends SocketBufferTestSupport {
/**
* Description of test.
- *
*/
@Test
public void testWriteByteArraySliceWithNegativeOffset() {
@@ -228,7 +219,6 @@ public class MllpSocketBufferWriteTest extends SocketBufferTestSupport {
/**
* Description of test.
- *
*/
@Test
public void testWriteByteArraySliceWithOffsetGreaterThanLength() {
@@ -290,7 +280,6 @@ public class MllpSocketBufferWriteTest extends SocketBufferTestSupport {
/**
* Description of test.
- *
*/
@Test
public void testEnsureCapacityWithNegativeRequiredAvailability() {
@@ -303,7 +292,6 @@ public class MllpSocketBufferWriteTest extends SocketBufferTestSupport {
/**
* Description of test.
- *
*/
@Test
public void testEnsureCapacityWithOutOfRangeRequiredAvailability() {
@@ -340,7 +328,6 @@ public class MllpSocketBufferWriteTest extends SocketBufferTestSupport {
/**
* Description of test.
- *
*/
@Test
public void testEnsureCapacityWithAlreadyAllocateMaxBufferSize() {
diff --git a/components/camel-mllp/src/test/java/org/apache/camel/test/junit/rule/mllp/MllpClientResource.java b/components/camel-mllp/src/test/java/org/apache/camel/test/junit/rule/mllp/MllpClientResource.java
index 9ba56232fca..e9feb846a6a 100644
--- a/components/camel-mllp/src/test/java/org/apache/camel/test/junit/rule/mllp/MllpClientResource.java
+++ b/components/camel-mllp/src/test/java/org/apache/camel/test/junit/rule/mllp/MllpClientResource.java
@@ -33,7 +33,7 @@ import org.slf4j.LoggerFactory;
/**
* MLLP Test Client packaged as a JUnit Rule
- *
+ * <p>
* The client can be configured to simulate a large number of error conditions.
*/
public class MllpClientResource implements BeforeEachCallback, AfterEachCallback {
diff --git a/components/camel-mllp/src/test/java/org/apache/camel/test/junit/rule/mllp/MllpServerResource.java b/components/camel-mllp/src/test/java/org/apache/camel/test/junit/rule/mllp/MllpServerResource.java
index 68dcc4e8c73..98ac3f6de28 100644
--- a/components/camel-mllp/src/test/java/org/apache/camel/test/junit/rule/mllp/MllpServerResource.java
+++ b/components/camel-mllp/src/test/java/org/apache/camel/test/junit/rule/mllp/MllpServerResource.java
@@ -39,7 +39,7 @@ import org.slf4j.LoggerFactory;
/**
* MLLP Test Server packaged as a JUnit Rule
- *
+ * <p>
* The server can be configured to simulate a large number of error conditions.
*/
public class MllpServerResource implements BeforeEachCallback, AfterEachCallback {
@@ -541,7 +541,6 @@ public class MllpServerResource implements BeforeEachCallback, AfterEachCallback
*
* @param hl7Message HL7 message that is being acknowledged
* @param acknowledgementCode AA, AE or AR
- *
* @return a HL7 Application Acknowledgement
*/
protected String generateAcknowledgement(String hl7Message, String acknowledgementCode) {
@@ -935,9 +934,7 @@ public class MllpServerResource implements BeforeEachCallback, AfterEachCallback
* Read a MLLP-Framed message
*
* @param anInputStream source input stream
- *
* @return the MLLP payload
- *
* @throws IOException when the underlying Java Socket calls raise these exceptions
*/
public String getMessage(InputStream anInputStream) throws IOException {
@@ -1007,7 +1004,6 @@ public class MllpServerResource implements BeforeEachCallback, AfterEachCallback
* Generates a HL7 Application Accept Acknowledgement
*
* @param hl7Message HL7 message that is being acknowledged
- *
* @return a HL7 Application Accept Acknowlegdement
*/
private String generateAcknowledgementMessage(String hl7Message) {
@@ -1019,7 +1015,6 @@ public class MllpServerResource implements BeforeEachCallback, AfterEachCallback
*
* @param hl7Message HL7 message that is being acknowledged
* @param acknowledgementCode AA, AE or AR
- *
* @return a HL7 Application Acknowledgement
*/
private String generateAcknowledgementMessage(String hl7Message, String acknowledgementCode) {
@@ -1037,7 +1032,7 @@ public class MllpServerResource implements BeforeEachCallback, AfterEachCallback
/**
* Receives HL7 messages and replies with HL7 Acknowledgements.
- *
+ * <p>
* The exact behaviour of this method is very configurable, allowing simulation of varies error conditions.
*/
@Override
diff --git a/components/camel-mllp/src/test/java/org/apache/camel/test/mllp/PassthroughProcessor.java b/components/camel-mllp/src/test/java/org/apache/camel/test/mllp/PassthroughProcessor.java
index bc4cf44fab0..753574bb8fb 100644
--- a/components/camel-mllp/src/test/java/org/apache/camel/test/mllp/PassthroughProcessor.java
+++ b/components/camel-mllp/src/test/java/org/apache/camel/test/mllp/PassthroughProcessor.java
@@ -23,7 +23,7 @@ import org.slf4j.LoggerFactory;
/**
* A Passthrough test processor
- *
+ * <p>
* Used to set breakpoints and diagnose what is going on in test routes
*/
public class PassthroughProcessor implements Processor {
diff --git a/components/camel-mllp/src/test/java/org/apache/camel/test/tcp/JavaSocketManualTests.java b/components/camel-mllp/src/test/java/org/apache/camel/test/tcp/JavaSocketManualTests.java
index 5358445bb7a..7e78db20c2b 100644
--- a/components/camel-mllp/src/test/java/org/apache/camel/test/tcp/JavaSocketManualTests.java
+++ b/components/camel-mllp/src/test/java/org/apache/camel/test/tcp/JavaSocketManualTests.java
@@ -39,11 +39,11 @@ import static org.junit.jupiter.api.Assertions.fail;
/**
* Various tests used to validate the behaviour of Java Sockets.
- *
+ * <p>
* The tests were for experimentation and don't have any assertions in them - JUnit provided a convenient framework to
* explore this behaviour. These tests shouldn't be run with a normal build since they don't have any assertions and
* don't validate any results.
- *
+ * <p>
* NOTE: This class may be deleted in the future
*/
@Disabled(value = "Tests validating Java Socket behaviours")
diff --git a/components/camel-mllp/src/test/resources/keystore.jks b/components/camel-mllp/src/test/resources/keystore.jks
new file mode 100644
index 00000000000..49b70def00f
Binary files /dev/null and b/components/camel-mllp/src/test/resources/keystore.jks differ
diff --git a/components/camel-mllp/src/test/resources/log4j2-test.properties b/components/camel-mllp/src/test/resources/log4j2-test.properties
index 7e3ad87069f..87688619e0b 100644
--- a/components/camel-mllp/src/test/resources/log4j2-test.properties
+++ b/components/camel-mllp/src/test/resources/log4j2-test.properties
@@ -14,21 +14,17 @@
## See the License for the specific language governing permissions and
## limitations under the License.
## ---------------------------------------------------------------------------
-
-appender.file.type = File
-appender.file.name = file
-appender.file.fileName = target/camel-mllp-test.log
-appender.file.layout.type = PatternLayout
-appender.file.layout.pattern = %d %X{camel.contextId} [%t] %-5p %-30.30c{1} - %m%n
-
-appender.out.type = Console
-appender.out.name = out
-appender.out.layout.type = PatternLayout
-appender.out.layout.pattern = %d [%-15.15t] %-5p %-30.30c{1} - %m%n
-
-rootLogger.level = INFO
-rootLogger.appenderRef.file.ref = file
-
-loggers = mllp
-logger.mllp.name = org.apache.camel.component.mllp
+appender.file.type=File
+appender.file.name=file
+appender.file.fileName=target/camel-mllp-test.log
+appender.file.layout.type=PatternLayout
+appender.file.layout.pattern=%d %X{camel.contextId} [%t] %-5p %-30.30c{1} - %m%n
+appender.out.type=Console
+appender.out.name=out
+appender.out.layout.type=PatternLayout
+appender.out.layout.pattern=%d [%-15.15t] %-5p %-30.30c{1} - %m%n
+rootLogger.level=INFO
+rootLogger.appenderRef.file.ref=file
+loggers=mllp
+logger.mllp.name=org.apache.camel.component.mllp
# logger.mllp.level = DEBUG
diff --git a/components/camel-sql/src/generated/java/org/apache/camel/component/sql/stored/template/generated/SSPTParserConstants.java b/components/camel-sql/src/generated/java/org/apache/camel/component/sql/stored/template/generated/SSPTParserConstants.java
index f48d31d1b37..52abb955f07 100644
--- a/components/camel-sql/src/generated/java/org/apache/camel/component/sql/stored/template/generated/SSPTParserConstants.java
+++ b/components/camel-sql/src/generated/java/org/apache/camel/component/sql/stored/template/generated/SSPTParserConstants.java
@@ -1,67 +1,67 @@
-/* Generated By:JavaCC: Do not edit this line. SSPTParserConstants.java */
-package org.apache.camel.component.sql.stored.template.generated;
-
-
-/**
- * Token literal values and constants.
- * Generated by org.javacc.parser.OtherFilesGen#start()
- */
-public interface SSPTParserConstants {
-
- /** End of File. */
- int EOF = 0;
- /** RegularExpression Id. */
- int SCALE = 4;
- /** RegularExpression Id. */
- int NUMBER = 5;
- /** RegularExpression Id. */
- int DIGIT = 6;
- /** RegularExpression Id. */
- int LETTER = 7;
- /** RegularExpression Id. */
- int SPECIAL = 8;
- /** RegularExpression Id. */
- int WHITESPACE = 9;
- /** RegularExpression Id. */
- int COMMA = 10;
- /** RegularExpression Id. */
- int SEPARATOR = 11;
- /** RegularExpression Id. */
- int PROCEDURE_BEGIN = 12;
- /** RegularExpression Id. */
- int PROCEDURE_END = 13;
- /** RegularExpression Id. */
- int SIMPLE_EXP_TOKEN = 14;
- /** RegularExpression Id. */
- int PARAMETER_POS_TOKEN = 15;
- /** RegularExpression Id. */
- int PARAMETER_NAME = 16;
- /** RegularExpression Id. */
- int IDENTIFIER = 17;
-
- /** Lexical state. */
- int DEFAULT = 0;
-
- /** Literal token values. */
- String[] tokenImage = {
- "<EOF>",
- "\" \"",
- "\"OUT \"",
- "\"INOUT \"",
- "<SCALE>",
- "<NUMBER>",
- "<DIGIT>",
- "<LETTER>",
- "<SPECIAL>",
- "<WHITESPACE>",
- "\",\"",
- "<SEPARATOR>",
- "<PROCEDURE_BEGIN>",
- "<PROCEDURE_END>",
- "<SIMPLE_EXP_TOKEN>",
- "<PARAMETER_POS_TOKEN>",
- "<PARAMETER_NAME>",
- "<IDENTIFIER>",
- };
-
-}
+/* Generated By:JavaCC: Do not edit this line. SSPTParserConstants.java */
+package org.apache.camel.component.sql.stored.template.generated;
+
+
+/**
+ * Token literal values and constants.
+ * Generated by org.javacc.parser.OtherFilesGen#start()
+ */
+public interface SSPTParserConstants {
+
+ /** End of File. */
+ int EOF = 0;
+ /** RegularExpression Id. */
+ int SCALE = 4;
+ /** RegularExpression Id. */
+ int NUMBER = 5;
+ /** RegularExpression Id. */
+ int DIGIT = 6;
+ /** RegularExpression Id. */
+ int LETTER = 7;
+ /** RegularExpression Id. */
+ int SPECIAL = 8;
+ /** RegularExpression Id. */
+ int WHITESPACE = 9;
+ /** RegularExpression Id. */
+ int COMMA = 10;
+ /** RegularExpression Id. */
+ int SEPARATOR = 11;
+ /** RegularExpression Id. */
+ int PROCEDURE_BEGIN = 12;
+ /** RegularExpression Id. */
+ int PROCEDURE_END = 13;
+ /** RegularExpression Id. */
+ int SIMPLE_EXP_TOKEN = 14;
+ /** RegularExpression Id. */
+ int PARAMETER_POS_TOKEN = 15;
+ /** RegularExpression Id. */
+ int PARAMETER_NAME = 16;
+ /** RegularExpression Id. */
+ int IDENTIFIER = 17;
+
+ /** Lexical state. */
+ int DEFAULT = 0;
+
+ /** Literal token values. */
+ String[] tokenImage = {
+ "<EOF>",
+ "\" \"",
+ "\"OUT \"",
+ "\"INOUT \"",
+ "<SCALE>",
+ "<NUMBER>",
+ "<DIGIT>",
+ "<LETTER>",
+ "<SPECIAL>",
+ "<WHITESPACE>",
+ "\",\"",
+ "<SEPARATOR>",
+ "<PROCEDURE_BEGIN>",
+ "<PROCEDURE_END>",
+ "<SIMPLE_EXP_TOKEN>",
+ "<PARAMETER_POS_TOKEN>",
+ "<PARAMETER_NAME>",
+ "<IDENTIFIER>",
+ };
+
+}
diff --git a/components/camel-sql/src/generated/java/org/apache/camel/component/sql/stored/template/generated/SSPTParserTokenManager.java b/components/camel-sql/src/generated/java/org/apache/camel/component/sql/stored/template/generated/SSPTParserTokenManager.java
index 7d8fd14b65b..6c3cc71ab48 100644
--- a/components/camel-sql/src/generated/java/org/apache/camel/component/sql/stored/template/generated/SSPTParserTokenManager.java
+++ b/components/camel-sql/src/generated/java/org/apache/camel/component/sql/stored/template/generated/SSPTParserTokenManager.java
@@ -608,60 +608,60 @@ private void jjCheckNAddStates(int start, int end)
} while (start++ != end);
}
- /** Constructor. */
- public SSPTParserTokenManager(SimpleCharStream stream){
-
- if (SimpleCharStream.staticFlag)
- throw new Error("ERROR: Cannot use a static CharStream class with a non-static lexical analyzer.");
-
- input_stream = stream;
- }
-
- /** Constructor. */
- public SSPTParserTokenManager (SimpleCharStream stream, int lexState){
- ReInit(stream);
- SwitchTo(lexState);
- }
-
- /** Reinitialise parser. */
-
- public void ReInit(SimpleCharStream stream)
- {
-
-
- jjmatchedPos =
- jjnewStateCnt =
- 0;
- curLexState = defaultLexState;
- input_stream = stream;
- ReInitRounds();
- }
-
- private void ReInitRounds()
- {
- int i;
- jjround = 0x80000001;
- for (i = 25; i-- > 0;)
- jjrounds[i] = 0x80000000;
- }
-
- /** Reinitialise parser. */
- public void ReInit(SimpleCharStream stream, int lexState)
-
- {
- ReInit(stream);
- SwitchTo(lexState);
- }
-
- /** Switch to specified lex state. */
- public void SwitchTo(int lexState)
- {
- if (lexState >= 1 || lexState < 0)
- throw new TokenMgrError("Error: Ignoring invalid lexical state : " + lexState + ". State unchanged.", TokenMgrError.INVALID_LEXICAL_STATE);
- else
- curLexState = lexState;
- }
-
+ /** Constructor. */
+ public SSPTParserTokenManager(SimpleCharStream stream){
+
+ if (SimpleCharStream.staticFlag)
+ throw new Error("ERROR: Cannot use a static CharStream class with a non-static lexical analyzer.");
+
+ input_stream = stream;
+ }
+
+ /** Constructor. */
+ public SSPTParserTokenManager (SimpleCharStream stream, int lexState){
+ ReInit(stream);
+ SwitchTo(lexState);
+ }
+
+ /** Reinitialise parser. */
+
+ public void ReInit(SimpleCharStream stream)
+ {
+
+
+ jjmatchedPos =
+ jjnewStateCnt =
+ 0;
+ curLexState = defaultLexState;
+ input_stream = stream;
+ ReInitRounds();
+ }
+
+ private void ReInitRounds()
+ {
+ int i;
+ jjround = 0x80000001;
+ for (i = 25; i-- > 0;)
+ jjrounds[i] = 0x80000000;
+ }
+
+ /** Reinitialise parser. */
+ public void ReInit(SimpleCharStream stream, int lexState)
+
+ {
+ ReInit(stream);
+ SwitchTo(lexState);
+ }
+
+ /** Switch to specified lex state. */
+ public void SwitchTo(int lexState)
+ {
+ if (lexState >= 1 || lexState < 0)
+ throw new TokenMgrError("Error: Ignoring invalid lexical state : " + lexState + ". State unchanged.", TokenMgrError.INVALID_LEXICAL_STATE);
+ else
+ curLexState = lexState;
+ }
+
/** Lexer state names. */
public static final String[] lexStateNames = {
@@ -684,13 +684,13 @@ static final long[] jjtoSpecial = {
static final long[] jjtoMore = {
0x0L,
};
- protected SimpleCharStream input_stream;
-
- private final int[] jjrounds = new int[25];
- private final int[] jjstateSet = new int[2 * 25];
- private final StringBuilder jjimage = new StringBuilder();
- private StringBuilder image = jjimage;
- private int jjimageLen;
- private int lengthOfMatch;
- protected int curChar;
+ protected SimpleCharStream input_stream;
+
+ private final int[] jjrounds = new int[25];
+ private final int[] jjstateSet = new int[2 * 25];
+ private final StringBuilder jjimage = new StringBuilder();
+ private StringBuilder image = jjimage;
+ private int jjimageLen;
+ private int lengthOfMatch;
+ protected int curChar;
}
diff --git a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/MllpComponentBuilderFactory.java b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/MllpComponentBuilderFactory.java
index 56ca951d54f..9c591717f18 100644
--- a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/MllpComponentBuilderFactory.java
+++ b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/MllpComponentBuilderFactory.java
@@ -630,6 +630,43 @@ public interface MllpComponentBuilderFactory {
return this;
}
+ /**
+ * Sets the SSLContextParameters for securing TCP connections. If set,
+ * the MLLP component will use SSL/TLS for securing both producer and
+ * consumer TCP connections. This allows the configuration of trust
+ * stores, key stores, protocols, and other SSL/TLS settings. If not
+ * set, the MLLP component will use plain TCP communication.
+ *
+ * The option is a:
+ * <code>org.apache.camel.support.jsse.SSLContextParameters</code> type.
+ *
+ * Group: security
+ *
+ * @param sslContextParameters the value to set
+ * @return the dsl builder
+ */
+ default MllpComponentBuilder sslContextParameters(org.apache.camel.support.jsse.SSLContextParameters sslContextParameters) {
+ doSetProperty("sslContextParameters", sslContextParameters);
+ return this;
+ }
+
+
+ /**
+ * Enable usage of global SSL context parameters.
+ *
+ * The option is a: <code>boolean</code> type.
+ *
+ * Default: false
+ * Group: security
+ *
+ * @param useGlobalSslContextParameters the value to set
+ * @return the dsl builder
+ */
+ default MllpComponentBuilder useGlobalSslContextParameters(boolean useGlobalSslContextParameters) {
+ doSetProperty("useGlobalSslContextParameters", useGlobalSslContextParameters);
+ return this;
+ }
+
/**
* The approximate idle time allowed before the Client TCP Connection
* will be reset. A null value or a value less than or equal to zero
@@ -698,6 +735,8 @@ public interface MllpComponentBuilderFactory {
case "receiveBufferSize": getOrCreateConfiguration((MllpComponent) component).setReceiveBufferSize((java.lang.Integer) value); return true;
case "receiveTimeout": getOrCreateConfiguration((MllpComponent) component).setReceiveTimeout((int) value); return true;
case "sendBufferSize": getOrCreateConfiguration((MllpComponent) component).setSendBufferSize((java.lang.Integer) value); return true;
+ case "sslContextParameters": getOrCreateConfiguration((MllpComponent) component).setSslContextParameters((org.apache.camel.support.jsse.SSLContextParameters) value); return true;
+ case "useGlobalSslContextParameters": ((MllpComponent) component).setUseGlobalSslContextParameters((boolean) value); return true;
case "idleTimeout": getOrCreateConfiguration((MllpComponent) component).setIdleTimeout((java.lang.Integer) value); return true;
default: return false;
}
diff --git a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/MllpEndpointBuilderFactory.java b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/MllpEndpointBuilderFactory.java
index 28f089c37d5..06893f59bf2 100644
--- a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/MllpEndpointBuilderFactory.java
+++ b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/MllpEndpointBuilderFactory.java
@@ -281,6 +281,44 @@ public interface MllpEndpointBuilderFactory {
doSetProperty("bridgeErrorHandler", bridgeErrorHandler);
return this;
}
+ /**
+ * Sets the SSLContextParameters for securing TCP connections. If set,
+ * the MLLP component will use SSL/TLS for securing both producer and
+ * consumer TCP connections. This allows the configuration of trust
+ * stores, key stores, protocols, and other SSL/TLS settings. If not
+ * set, the MLLP component will use plain TCP communication.
+ *
+ * The option is a:
+ * <code>org.apache.camel.support.jsse.SSLContextParameters</code> type.
+ *
+ * Group: security
+ *
+ * @param sslContextParameters the value to set
+ * @return the dsl builder
+ */
+ default MllpEndpointConsumerBuilder sslContextParameters(org.apache.camel.support.jsse.SSLContextParameters sslContextParameters) {
+ doSetProperty("sslContextParameters", sslContextParameters);
+ return this;
+ }
+ /**
+ * Sets the SSLContextParameters for securing TCP connections. If set,
+ * the MLLP component will use SSL/TLS for securing both producer and
+ * consumer TCP connections. This allows the configuration of trust
+ * stores, key stores, protocols, and other SSL/TLS settings. If not
+ * set, the MLLP component will use plain TCP communication.
+ *
+ * The option will be converted to a
+ * <code>org.apache.camel.support.jsse.SSLContextParameters</code> type.
+ *
+ * Group: security
+ *
+ * @param sslContextParameters the value to set
+ * @return the dsl builder
+ */
+ default MllpEndpointConsumerBuilder sslContextParameters(String sslContextParameters) {
+ doSetProperty("sslContextParameters", sslContextParameters);
+ return this;
+ }
}
/**
@@ -1024,6 +1062,44 @@ public interface MllpEndpointBuilderFactory {
doSetProperty("validatePayload", validatePayload);
return this;
}
+ /**
+ * Sets the SSLContextParameters for securing TCP connections. If set,
+ * the MLLP component will use SSL/TLS for securing both producer and
+ * consumer TCP connections. This allows the configuration of trust
+ * stores, key stores, protocols, and other SSL/TLS settings. If not
+ * set, the MLLP component will use plain TCP communication.
+ *
+ * The option is a:
+ * <code>org.apache.camel.support.jsse.SSLContextParameters</code> type.
+ *
+ * Group: security
+ *
+ * @param sslContextParameters the value to set
+ * @return the dsl builder
+ */
+ default MllpEndpointProducerBuilder sslContextParameters(org.apache.camel.support.jsse.SSLContextParameters sslContextParameters) {
+ doSetProperty("sslContextParameters", sslContextParameters);
+ return this;
+ }
+ /**
+ * Sets the SSLContextParameters for securing TCP connections. If set,
+ * the MLLP component will use SSL/TLS for securing both producer and
+ * consumer TCP connections. This allows the configuration of trust
+ * stores, key stores, protocols, and other SSL/TLS settings. If not
+ * set, the MLLP component will use plain TCP communication.
+ *
+ * The option will be converted to a
+ * <code>org.apache.camel.support.jsse.SSLContextParameters</code> type.
+ *
+ * Group: security
+ *
+ * @param sslContextParameters the value to set
+ * @return the dsl builder
+ */
+ default MllpEndpointProducerBuilder sslContextParameters(String sslContextParameters) {
+ doSetProperty("sslContextParameters", sslContextParameters);
+ return this;
+ }
}
/**
@@ -1646,6 +1722,44 @@ public interface MllpEndpointBuilderFactory {
doSetProperty("validatePayload", validatePayload);
return this;
}
+ /**
+ * Sets the SSLContextParameters for securing TCP connections. If set,
+ * the MLLP component will use SSL/TLS for securing both producer and
+ * consumer TCP connections. This allows the configuration of trust
+ * stores, key stores, protocols, and other SSL/TLS settings. If not
+ * set, the MLLP component will use plain TCP communication.
+ *
+ * The option is a:
+ * <code>org.apache.camel.support.jsse.SSLContextParameters</code> type.
+ *
+ * Group: security
+ *
+ * @param sslContextParameters the value to set
+ * @return the dsl builder
+ */
+ default MllpEndpointBuilder sslContextParameters(org.apache.camel.support.jsse.SSLContextParameters sslContextParameters) {
+ doSetProperty("sslContextParameters", sslContextParameters);
+ return this;
+ }
+ /**
+ * Sets the SSLContextParameters for securing TCP connections. If set,
+ * the MLLP component will use SSL/TLS for securing both producer and
+ * consumer TCP connections. This allows the configuration of trust
+ * stores, key stores, protocols, and other SSL/TLS settings. If not
+ * set, the MLLP component will use plain TCP communication.
+ *
+ * The option will be converted to a
+ * <code>org.apache.camel.support.jsse.SSLContextParameters</code> type.
+ *
+ * Group: security
+ *
+ * @param sslContextParameters the value to set
+ * @return the dsl builder
+ */
+ default MllpEndpointBuilder sslContextParameters(String sslContextParameters) {
+ doSetProperty("sslContextParameters", sslContextParameters);
+ return this;
+ }
}
/**