This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch camel-4.8.x
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/camel-4.8.x by this push:
     new 8f9a777743a CAMEL-22037: Provide fix for TextPlainEntity along with a 
unit test (#17967)
8f9a777743a is described below

commit 8f9a777743af6912fe548ca3c04f8a4e00b927ae
Author: Jürgen Link <juergen.l...@scoop-software.de>
AuthorDate: Tue May 6 13:13:45 2025 +0200

    CAMEL-22037: Provide fix for TextPlainEntity along with a unit test (#17967)
    
    * Provide fix for TextPlainEntity along with a unit test
    
    * Add Apache license header, alter test to use complete HTTP request as 
input
    
    * Duplicate EntityParserTest and provide test data provider with the 
ability to use LF or CRLF line endings
    
    * Add Apache license header
    
    * remove debug output
    
    * Format code, rename unit test method
    
    ---------
    
    Co-authored-by: jlink <juergen.link_...@pharma-mall.de>
---
 .../component/as2/api/entity/TextPlainEntity.java  |   2 +-
 .../entity/EntityParserContentLineEndingTest.java  | 333 +++++++++++++++++++++
 .../api/entity/EntityParserContentProvider.java    | 144 +++++++++
 .../as2/api/entity/TextPlainEntityTest.java        |  51 ++++
 4 files changed, 529 insertions(+), 1 deletion(-)

diff --git 
a/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/entity/TextPlainEntity.java
 
b/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/entity/TextPlainEntity.java
index 00f5659fb68..9c308b2ea21 100644
--- 
a/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/entity/TextPlainEntity.java
+++ 
b/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/entity/TextPlainEntity.java
@@ -54,7 +54,7 @@ public class TextPlainEntity extends MimeEntity {
             }
 
             // Write out content
-            
canonicalOutstream.write(content.getBytes(StandardCharsets.US_ASCII), 0, 
content.length());
+            outstream.write(content.getBytes(StandardCharsets.US_ASCII), 0, 
content.length());
         }
     }
 
diff --git 
a/components/camel-as2/camel-as2-api/src/test/java/org/apache/camel/component/as2/api/entity/EntityParserContentLineEndingTest.java
 
b/components/camel-as2/camel-as2-api/src/test/java/org/apache/camel/component/as2/api/entity/EntityParserContentLineEndingTest.java
new file mode 100644
index 00000000000..fa85444aebf
--- /dev/null
+++ 
b/components/camel-as2/camel-as2-api/src/test/java/org/apache/camel/component/as2/api/entity/EntityParserContentLineEndingTest.java
@@ -0,0 +1,333 @@
+/*
+ * 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.as2.api.entity;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigInteger;
+import java.security.*;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import org.apache.camel.component.as2.api.AS2Header;
+import org.apache.camel.component.as2.api.io.AS2SessionInputBuffer;
+import org.apache.camel.component.as2.api.util.EntityUtils;
+import org.apache.camel.component.as2.api.util.HttpMessageUtils;
+import org.apache.hc.core5.http.*;
+import org.apache.hc.core5.http.impl.BasicHttpTransportMetrics;
+import org.apache.hc.core5.http.impl.EnglishReasonPhraseCatalog;
+import org.apache.hc.core5.http.io.entity.BasicHttpEntity;
+import org.apache.hc.core5.http.message.BasicClassicHttpResponse;
+import org.apache.hc.core5.http.message.BasicHeader;
+import org.bouncycastle.asn1.x500.X500Name;
+import org.bouncycastle.asn1.x509.AuthorityKeyIdentifier;
+import org.bouncycastle.asn1.x509.Extension;
+import org.bouncycastle.asn1.x509.SubjectKeyIdentifier;
+import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
+import org.bouncycastle.cert.X509v3CertificateBuilder;
+import org.bouncycastle.cert.bc.BcX509ExtensionUtils;
+import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
+import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
+import org.bouncycastle.cms.CMSAlgorithm;
+import org.bouncycastle.cms.CMSEnvelopedDataGenerator;
+import org.bouncycastle.cms.jcajce.JceCMSContentEncryptorBuilder;
+import org.bouncycastle.cms.jcajce.JceKeyTransRecipientInfoGenerator;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.operator.OperatorCreationException;
+import org.bouncycastle.operator.OutputEncryptor;
+import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+
+import static org.apache.camel.component.as2.api.entity.EntityParserTest.*;
+import static org.junit.jupiter.api.Assertions.*;
+
+public class EntityParserContentLineEndingTest {
+
+    private static final int DEFAULT_BUFFER_SIZE = 8 * 1024;
+
+    //
+    // certificate serial number seed.
+    //
+    int serialNo = 1;
+
+    @BeforeEach
+    public void setUp() throws Exception {
+    }
+
+    @AfterEach
+    public void tearDown() throws Exception {
+    }
+
+    @ParameterizedTest
+    @ValueSource(strings = { "\r", "" })
+    public void parseMessageDispositionNotificationReportMessageTest(String 
carriageReturn) throws Exception {
+        HttpResponse response = new BasicClassicHttpResponse(
+                HttpStatus.SC_OK, 
EnglishReasonPhraseCatalog.INSTANCE.getReason(HttpStatus.SC_OK, null));
+        response.setVersion(new ProtocolVersion("HTTP", 1, 1));
+        HttpMessageUtils.setHeaderValue(response, 
AS2Header.CONTENT_TRANSFER_ENCODING,
+                DISPOSITION_NOTIFICATION_CONTENT_TRANSFER_ENCODING);
+
+        InputStream is = new ByteArrayInputStream(
+                
EntityParserContentProvider.dispositionNotificationReportContent(carriageReturn)
+                        
.getBytes(DISPOSITION_NOTIFICATION_REPORT_CONTENT_CHARSET_NAME));
+        BasicHttpEntity entity = new BasicHttpEntity(is, 
ContentType.parse(REPORT_CONTENT_TYPE_VALUE));
+        EntityUtils.setMessageEntity(response, entity);
+
+        EntityParser.parseAS2MessageEntity(response);
+        HttpEntity parsedEntity = EntityUtils.getMessageEntity(response);
+        assertNotNull(parsedEntity, "Unexpected Null message disposition 
notification report entity");
+        assertTrue(parsedEntity instanceof 
DispositionNotificationMultipartReportEntity,
+                "Unexpected type for message disposition notification report 
entity");
+    }
+
+    @ParameterizedTest
+    @ValueSource(strings = { "\r", "" })
+    public void parseMessageDispositionNotificationReportBodyTest(String 
carriageReturn) throws Exception {
+
+        DispositionNotificationMultipartReportEntity 
dispositionNotificationMultipartReportEntity
+                = 
createMdnEntity(EntityParserContentProvider.dispositionNotificationReportContent(carriageReturn),
+                        DISPOSITION_NOTIFICATION_REPORT_CONTENT_BOUNDARY);
+
+        assertNotNull(dispositionNotificationMultipartReportEntity,
+                "Unexpected Null disposition notification multipart entity");
+        assertEquals(2, 
dispositionNotificationMultipartReportEntity.getPartCount(), "Unexpected number 
of body parts");
+
+        assertTrue(dispositionNotificationMultipartReportEntity.getPart(0) 
instanceof TextPlainEntity,
+                "Unexpected type for first body part");
+        assertTrue(dispositionNotificationMultipartReportEntity.getPart(1) 
instanceof AS2MessageDispositionNotificationEntity,
+                "Unexpected type for second body part");
+    }
+
+    // verify that parsing the Disposition Notification Report has made no 
alteration to the entity's body part fields
+    @ParameterizedTest
+    @ValueSource(strings = { "\r", "" })
+    public void messageDispositionNotificationReportBodyContentTest(String 
carriageReturn) throws Exception {
+
+        DispositionNotificationMultipartReportEntity 
dispositionNotificationMultipartReportEntity
+                = 
createMdnEntity(EntityParserContentProvider.dispositionNotificationReportContentUnfolded(carriageReturn),
+                        DISPOSITION_NOTIFICATION_REPORT_CONTENT_BOUNDARY);
+
+        String expectedContent = String.format("%s\r\n%s\r\n%s",
+                new BasicHeader(AS2Header.CONTENT_TYPE, 
REPORT_CONTENT_TYPE_VALUE),
+                new BasicHeader(AS2Header.CONTENT_TRANSFER_ENCODING, 
DISPOSITION_NOTIFICATION_REPORT_CONTENT_TRANSFER_ENCODING),
+                
EntityParserContentProvider.dispositionNotificationReportContentUnfolded(carriageReturn));
+
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        dispositionNotificationMultipartReportEntity.writeTo(out);
+
+        assertEquals(expectedContent, 
out.toString(DISPOSITION_NOTIFICATION_CONTENT_CHARSET_NAME));
+    }
+
+    @ParameterizedTest
+    @ValueSource(strings = { "\r", "" })
+    public void parseTextPlainBodyTest(String carriageReturn) throws Exception 
{
+
+        InputStream is = new ByteArrayInputStream(
+                
EntityParserContentProvider.textPlainContent(carriageReturn).getBytes(TEXT_PLAIN_CONTENT_CHARSET_NAME));
+        AS2SessionInputBuffer inbuffer
+                = new AS2SessionInputBuffer(new BasicHttpTransportMetrics(), 
DEFAULT_BUFFER_SIZE, DEFAULT_BUFFER_SIZE);
+
+        TextPlainEntity textPlainEntity = 
EntityParser.parseTextPlainEntityBody(inbuffer, is, TEXT_PLAIN_CONTENT_BOUNDARY,
+                TEXT_PLAIN_CONTENT_CHARSET_NAME, 
TEXT_PLAIN_CONTENT_TRANSFER_ENCODING);
+
+        String text = textPlainEntity.getText();
+
+        
assertEquals(EntityParserContentProvider.expectedTextPlainContent(carriageReturn),
 text, "Unexpected text");
+    }
+
+    @ParameterizedTest
+    @ValueSource(strings = { "\r", "" })
+    public void parseTextPlainBodyTestWithEntityMarshalling(String 
carriageReturn) throws Exception {
+
+        InputStream is = new ByteArrayInputStream(
+                
EntityParserContentProvider.textPlainContent(carriageReturn).getBytes(TEXT_PLAIN_CONTENT_CHARSET_NAME));
+        AS2SessionInputBuffer inbuffer
+                = new AS2SessionInputBuffer(new BasicHttpTransportMetrics(), 
DEFAULT_BUFFER_SIZE, DEFAULT_BUFFER_SIZE);
+
+        TextPlainEntity textPlainEntity = 
EntityParser.parseTextPlainEntityBody(inbuffer, is, TEXT_PLAIN_CONTENT_BOUNDARY,
+                TEXT_PLAIN_CONTENT_CHARSET_NAME, 
TEXT_PLAIN_CONTENT_TRANSFER_ENCODING);
+
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        textPlainEntity.setMainBody(true);
+        textPlainEntity.writeTo(out);
+        String text = out.toString();
+
+        
assertEquals(EntityParserContentProvider.expectedTextPlainContent(carriageReturn),
 text, "Unexpected text");
+    }
+
+    @ParameterizedTest
+    @ValueSource(strings = { "\r", "" })
+    public void parseMessageDispositionNotificationBodyTest(String 
carriageReturn) throws Exception {
+
+        InputStream is = new ByteArrayInputStream(
+                
EntityParserContentProvider.dispositionNotificationContent(carriageReturn)
+                        
.getBytes(DISPOSITION_NOTIFICATION_CONTENT_CHARSET_NAME));
+        AS2SessionInputBuffer inbuffer
+                = new AS2SessionInputBuffer(new BasicHttpTransportMetrics(), 
DEFAULT_BUFFER_SIZE, DEFAULT_BUFFER_SIZE);
+
+        AS2MessageDispositionNotificationEntity 
messageDispositionNotificationEntity = EntityParser
+                .parseMessageDispositionNotificationEntityBody(inbuffer, is, 
DISPOSITION_NOTIFICATION_CONTENT_BOUNDARY,
+                        DISPOSITION_NOTIFICATION_CONTENT_CHARSET_NAME);
+
+        assertEquals(EXPECTED_REPORTING_UA, 
messageDispositionNotificationEntity.getReportingUA(),
+                "Unexpected Reporting UA value");
+        assertEquals(EXPECTED_MTN_NAME, 
messageDispositionNotificationEntity.getMtnName(), "Unexpected MTN Name");
+        assertEquals(EXPECTED_ORIGINAL_RECIPIENT,
+                
messageDispositionNotificationEntity.getExtensionFields().get("Original-Recipient"),
+                "Unexpected Original Recipient");
+        assertEquals(EXPECTED_FINAL_RECIPIENT, 
messageDispositionNotificationEntity.getFinalRecipient(),
+                "Unexpected Final Reciptient");
+        assertEquals(EXPECTED_ORIGINAL_MESSAGE_ID, 
messageDispositionNotificationEntity.getOriginalMessageId(),
+                "Unexpected Original Message ID");
+        assertEquals(EXPECTED_DISPOSITION_MODE, 
messageDispositionNotificationEntity.getDispositionMode(),
+                "Unexpected Disposition Mode");
+        
assertNotNull(messageDispositionNotificationEntity.getDispositionModifier(), 
"Unexpected Null Disposition Modifier");
+        assertEquals(EXPECTED_DISPOSITION_MODIFIER, 
messageDispositionNotificationEntity.getDispositionModifier().getModifier(),
+                "Unexpected Disposition Modifier");
+        assertEquals(EXPECTED_DISPOSITION_TYPE, 
messageDispositionNotificationEntity.getDispositionType(),
+                "Unexpected Disposition Type");
+        assertArrayEquals(EXPECTED_FAILURE, 
messageDispositionNotificationEntity.getFailureFields(),
+                "Unexpected Failure Array value");
+        assertArrayEquals(EXPECTED_ERROR, 
messageDispositionNotificationEntity.getErrorFields(),
+                "Unexpected Error Array value");
+        assertArrayEquals(EXPECTED_WARNING, 
messageDispositionNotificationEntity.getWarningFields(),
+                "Unexpected Warning Array value");
+        
assertNotNull(messageDispositionNotificationEntity.getReceivedContentMic(), 
"Unexpected Null Received Content MIC");
+        assertEquals(EXPECTED_ENCODED_MESSAGE_DIGEST,
+                
messageDispositionNotificationEntity.getReceivedContentMic().getEncodedMessageDigest(),
+                "Unexpected Encoded Message Digest");
+        assertEquals(EXPECTED_DIGEST_ALGORITHM_ID,
+                
messageDispositionNotificationEntity.getReceivedContentMic().getDigestAlgorithmId(),
+                "Unexpected Digest Algorithm ID");
+    }
+
+    @Test
+    public void parseEnvelopedBodyTest() throws Exception {
+
+        Security.addProvider(new BouncyCastleProvider());
+
+        //
+        // set up our certificates
+        //
+        KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA", "BC");
+
+        kpg.initialize(1024, new SecureRandom());
+
+        String issueDN = "O=Punkhorn Software, C=US";
+        KeyPair issueKP = kpg.generateKeyPair();
+        X509Certificate issuerCertificate = makeCertificate(issueKP, issueDN, 
issueKP, issueDN);
+
+        //
+        // certificate we encrypt against
+        //
+        String encryptDN = "CN=William J. Collins, E=punkhor...@gmail.com, 
O=Punkhorn Software, C=US";
+        KeyPair encryptKP = kpg.generateKeyPair();
+        X509Certificate encryptionCertificate = makeCertificate(encryptKP, 
encryptDN, issueKP, issueDN);
+
+        List<X509Certificate> certList = new ArrayList<>();
+
+        certList.add(encryptionCertificate);
+        certList.add(issuerCertificate);
+
+        //
+        // Create generator
+        //
+        CMSEnvelopedDataGenerator cmsEnvelopeDataGenerator = new 
CMSEnvelopedDataGenerator();
+
+        JceKeyTransRecipientInfoGenerator recipientInfoGenerator = new 
JceKeyTransRecipientInfoGenerator(encryptionCertificate);
+        
cmsEnvelopeDataGenerator.addRecipientInfoGenerator(recipientInfoGenerator);
+
+        //
+        // Create encryptor
+        //
+        OutputEncryptor contentEncryptor = new 
JceCMSContentEncryptorBuilder(CMSAlgorithm.AES128_CCM).build();
+
+        //
+        // Build Enveloped Entity
+        //
+        TextPlainEntity textEntity = new TextPlainEntity("This is a super 
secret messatge!", "US-ASCII", "7bit", false);
+        ApplicationPkcs7MimeEnvelopedDataEntity applicationPkcs7MimeEntity = 
new ApplicationPkcs7MimeEnvelopedDataEntity(
+                textEntity, cmsEnvelopeDataGenerator, contentEncryptor, 
"binary", true);
+
+        MimeEntity decryptedMimeEntity = 
applicationPkcs7MimeEntity.getEncryptedEntity(encryptKP.getPrivate());
+        assertEquals("text/plain; charset=US-ASCII", 
decryptedMimeEntity.getContentType(),
+                "Decrypted entity has unexpected content type");
+        assertEquals("This is a super secret messatge!", ((TextPlainEntity) 
decryptedMimeEntity).getText(),
+                "Decrypted entity has unexpected content");
+    }
+
+    /**
+     * create a basic X509 certificate from the given keys
+     */
+    private X509Certificate makeCertificate(KeyPair subKP, String subDN, 
KeyPair issKP, String issDN)
+            throws GeneralSecurityException, IOException, 
OperatorCreationException {
+        PublicKey subPub = subKP.getPublic();
+        PrivateKey issPriv = issKP.getPrivate();
+        PublicKey issPub = issKP.getPublic();
+
+        X509v3CertificateBuilder v3CertGen = new JcaX509v3CertificateBuilder(
+                new X500Name(issDN),
+                BigInteger.valueOf(serialNo++), new 
Date(System.currentTimeMillis()),
+                new Date(System.currentTimeMillis() + (1000L * 60 * 60 * 24 * 
100)), new X500Name(subDN), subPub);
+
+        v3CertGen.addExtension(Extension.subjectKeyIdentifier, false, 
createSubjectKeyId(subPub));
+
+        v3CertGen.addExtension(Extension.authorityKeyIdentifier, false, 
createAuthorityKeyId(issPub));
+
+        return new 
JcaX509CertificateConverter().setProvider("BC").getCertificate(
+                v3CertGen.build(new 
JcaContentSignerBuilder("MD5withRSA").setProvider("BC").build(issPriv)));
+    }
+
+    private AuthorityKeyIdentifier createAuthorityKeyId(PublicKey pub) throws 
IOException {
+        SubjectPublicKeyInfo info = 
SubjectPublicKeyInfo.getInstance(pub.getEncoded());
+
+        BcX509ExtensionUtils utils = new BcX509ExtensionUtils();
+        return utils.createAuthorityKeyIdentifier(info);
+    }
+
+    private DispositionNotificationMultipartReportEntity 
createMdnEntity(String reportContent, String boundary)
+            throws Exception {
+        InputStream is = new ByteArrayInputStream(
+                
reportContent.getBytes(DISPOSITION_NOTIFICATION_REPORT_CONTENT_CHARSET_NAME));
+        AS2SessionInputBuffer inbuffer
+                = new AS2SessionInputBuffer(new BasicHttpTransportMetrics(), 
DEFAULT_BUFFER_SIZE, DEFAULT_BUFFER_SIZE);
+
+        DispositionNotificationMultipartReportEntity 
dispositionNotificationMultipartReportEntity = EntityParser
+                .parseMultipartReportEntityBody(inbuffer, is, boundary,
+                        DISPOSITION_NOTIFICATION_REPORT_CONTENT_CHARSET_NAME,
+                        
DISPOSITION_NOTIFICATION_REPORT_CONTENT_TRANSFER_ENCODING);
+
+        assertNotNull(dispositionNotificationMultipartReportEntity,
+                "Unexpected Null disposition notification multipart entity");
+
+        return dispositionNotificationMultipartReportEntity;
+    }
+
+    static SubjectKeyIdentifier createSubjectKeyId(PublicKey pub) throws 
IOException {
+        SubjectPublicKeyInfo info = 
SubjectPublicKeyInfo.getInstance(pub.getEncoded());
+
+        return new BcX509ExtensionUtils().createSubjectKeyIdentifier(info);
+    }
+}
diff --git 
a/components/camel-as2/camel-as2-api/src/test/java/org/apache/camel/component/as2/api/entity/EntityParserContentProvider.java
 
b/components/camel-as2/camel-as2-api/src/test/java/org/apache/camel/component/as2/api/entity/EntityParserContentProvider.java
new file mode 100644
index 00000000000..81c80dc0188
--- /dev/null
+++ 
b/components/camel-as2/camel-as2-api/src/test/java/org/apache/camel/component/as2/api/entity/EntityParserContentProvider.java
@@ -0,0 +1,144 @@
+/*
+ * 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.as2.api.entity;
+
+public class EntityParserContentProvider {
+
+    public static String dispositionNotificationReportContent(String 
contentLineEnding) {
+        return """
+                \r
+                ------=_Part_56_1672293592.1028122454656\r
+                Content-Type: text/plain\r
+                Content-Transfer-Encoding: 7bit\r
+                \r
+                MDN for -_CR
+                 Message ID: <200207310834482A70BF63@\\"~~foo~~\\">_CR
+                  From: "\\"  as2Name  \\""_CR
+                  To: "0123456780000" Received on: 2002-07-31 at 09:34:14 
(EDT)_CR
+                 Status: processed_CR
+                 Comment: This is not a guarantee that the message has_CR
+                  been completely processed or &understood by the receiving_CR
+                  translator_CR
+                \r
+                ------=_Part_56_1672293592.1028122454656\r
+                Content-Type: message/disposition-notification\r
+                Content-Transfer-Encoding: 7bit\r
+                \r
+                Reporting-UA: AS2 Server\r
+                MDN-Gateway: dns; example.com\r
+                Original-Recipient: rfc822; 0123456780000\r
+                Final-Recipient: rfc822; 0123456780000\r
+                Original-Message-ID: <200207310834482A70BF63@\\"~~foo~~\\">\r
+                Disposition: automatic-action/MDN-sent-automatically;\r
+                  processed/warning: you're awesome\r
+                Failure: oops-a-failure\r
+                Error: oops-an-error\r
+                Warning: oops-a-warning\r
+                Received-content-MIC: 7v7F++fQaNB1sVLFtMRp+dF+eG4=, sha1\r
+                \r
+                ------=_Part_56_1672293592.1028122454656--\r
+                """
+                .replaceAll("_CR", contentLineEnding);
+    }
+
+    public static String dispositionNotificationReportContentUnfolded(String 
contentLineEnding) {
+        return """
+                \r
+                ------=_Part_56_1672293592.1028122454656\r
+                Content-Type: text/plain\r
+                Content-Transfer-Encoding: 7bit\r
+                \r
+                MDN for -_CR
+                 Message ID: <200207310834482A70BF63@\\"~~foo~~\\">_CR
+                  From: "\\"  as2Name  \\""_CR
+                  To: "0123456780000""
+                  Received on: 2002-07-31 at 09:34:14 (EDT)_CR
+                 Status: processed_CR
+                 Comment: This is not a guarantee that the message has_CR
+                  been completely processed or &understood by the receiving_CR
+                  translator_CR
+                \r
+                ------=_Part_56_1672293592.1028122454656\r
+                Content-Type: message/disposition-notification\r
+                Content-Transfer-Encoding: 7bit\r
+                \r
+                Reporting-UA: AS2 Server\r
+                MDN-Gateway: dns; example.com\r
+                Original-Recipient: rfc822; 0123456780000\r
+                Final-Recipient: rfc822; 0123456780000\r
+                Original-Message-ID: <200207310834482A70BF63@\\"~~foo~~\\">\r
+                Disposition: automatic-action/MDN-sent-automatically; 
rocessed/warning: you're awesome\r
+                Failure: oops-a-failure\r
+                Error: oops-an-error\r
+                Warning: oops-a-warning\r
+                Received-content-MIC: 7v7F++fQaNB1sVLFtMRp+dF+eG4=, sha1\r
+                \r
+                ------=_Part_56_1672293592.1028122454656--\r
+                """
+                .replaceAll("_CR", contentLineEnding);
+    }
+
+    public static String textPlainContent(String contentLineEnding) {
+        return """
+                MDN for -_CR
+                 Message ID: <200207310834482A70BF63@\\"~~foo~~\\">_CR
+                  From: "\\"  as2Name  \\""_CR
+                  To: "0123456780000" Received on: 2002-07-31 at 09:34:14 
(EDT)_CR
+                 Status: processed_CR
+                 Comment: This is not a guarantee that the message has_CR
+                  been completely processed or &understood by the receiving_CR
+                  translator_CR
+                \r
+                ------=_Part_56_1672293592.1028122454656--\r
+                """
+                .replaceAll("_CR", contentLineEnding);
+    }
+
+    public static String expectedTextPlainContent(String contentLineEnding) {
+
+        return """
+                MDN for -_CR
+                 Message ID: <200207310834482A70BF63@\\"~~foo~~\\">_CR
+                  From: "\\"  as2Name  \\""_CR
+                  To: "0123456780000" Received on: 2002-07-31 at 09:34:14 
(EDT)_CR
+                 Status: processed_CR
+                 Comment: This is not a guarantee that the message has_CR
+                  been completely processed or &understood by the receiving_CR
+                  translator_CR
+                """
+                .replaceAll("_CR", contentLineEnding);
+    }
+
+    public static String dispositionNotificationContent(String 
contentLineEnding) {
+        return """
+                Reporting-UA: AS2 Server_CR
+                MDN-Gateway: dns; example.com_CR
+                Original-Recipient: rfc822; 0123456780000_CR
+                Final-Recipient: rfc822; 0123456780000_CR
+                Original-Message-ID: <200207310834482A70BF63@\\"~~foo~~\\">_CR
+                Disposition: automatic-action/MDN-sent-automatically;_CR
+                  processed/warning: you're awesome_CR
+                Failure: oops-a-failure_CR
+                Error: oops-an-error_CR
+                Warning: oops-a-warning_CR
+                Received-content-MIC: 7v7F++fQaNB1sVLFtMRp+dF+eG4=, sha1_CR
+                \r
+                ------=_Part_56_1672293592.1028122454656--\r
+                """
+                .replaceAll("_CR", contentLineEnding);
+    }
+}
diff --git 
a/components/camel-as2/camel-as2-api/src/test/java/org/apache/camel/component/as2/api/entity/TextPlainEntityTest.java
 
b/components/camel-as2/camel-as2-api/src/test/java/org/apache/camel/component/as2/api/entity/TextPlainEntityTest.java
new file mode 100644
index 00000000000..c4c28124b4a
--- /dev/null
+++ 
b/components/camel-as2/camel-as2-api/src/test/java/org/apache/camel/component/as2/api/entity/TextPlainEntityTest.java
@@ -0,0 +1,51 @@
+/*
+ * 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.as2.api.entity;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+
+import org.apache.hc.core5.http.HttpException;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class TextPlainEntityTest {
+
+    @Test
+    void test_parse() throws IOException, HttpException {
+
+        String parsedMimeMessage;
+        try (MimeEntity mimeEntity = 
EntityParser.parseEntity(MESSAGE.getBytes(StandardCharsets.US_ASCII))) {
+            ByteArrayOutputStream out = new ByteArrayOutputStream();
+            mimeEntity.writeTo(out);
+            parsedMimeMessage = new String(out.toByteArray(), 
StandardCharsets.US_ASCII);
+        }
+
+        Assertions.assertEquals(parsedMimeMessage, MESSAGE);
+    }
+
+    String MESSAGE = """
+            Content-Type: text/plain; charset=US-ASCII\r
+            Content-Transfer-Encoding: binary\r
+            \r
+            <root>
+            \t<item/>
+            </root>
+            """;
+
+}

Reply via email to