You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ac...@apache.org on 2018/12/05 11:32:07 UTC

[camel] 01/15: [CAMEL-12605] Added support for compression

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

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

commit 73ec6892b72a56d4823eba08b2a884b3ef7a4d5d
Author: William Collins <pu...@gmail.com>
AuthorDate: Mon Nov 26 16:03:27 2018 -0500

    [CAMEL-12605] Added support for compression
---
 ... ApplicationPkcs7MimeCompressedDataEntity.java} | 57 +++++++-------
 .../as2/api/entity/ApplicationPkcs7MimeEntity.java |  2 +-
 .../component/as2/api/entity/EntityParser.java     | 87 ++++++++++++++-------
 .../as2/api/entity/CompressedEntityTest.java       | 89 ++++++++++++++++++++++
 4 files changed, 176 insertions(+), 59 deletions(-)

diff --git a/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/entity/ApplicationPkcs7MimeEntity.java b/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/entity/ApplicationPkcs7MimeCompressedDataEntity.java
similarity index 64%
copy from components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/entity/ApplicationPkcs7MimeEntity.java
copy to components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/entity/ApplicationPkcs7MimeCompressedDataEntity.java
index c1d6952..7a88761 100644
--- a/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/entity/ApplicationPkcs7MimeEntity.java
+++ b/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/entity/ApplicationPkcs7MimeCompressedDataEntity.java
@@ -19,7 +19,6 @@ package org.apache.camel.component.as2.api.entity;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
-import java.security.PrivateKey;
 
 import org.apache.camel.component.as2.api.AS2Charset;
 import org.apache.camel.component.as2.api.AS2Header;
@@ -31,42 +30,43 @@ import org.apache.http.HttpException;
 import org.apache.http.entity.ContentType;
 import org.apache.http.message.BasicNameValuePair;
 import org.apache.http.util.Args;
-import org.bouncycastle.cms.CMSEnvelopedData;
-import org.bouncycastle.cms.CMSEnvelopedDataGenerator;
+import org.bouncycastle.cms.CMSCompressedData;
+import org.bouncycastle.cms.CMSCompressedDataGenerator;
 import org.bouncycastle.cms.CMSProcessableByteArray;
 import org.bouncycastle.cms.CMSTypedData;
-import org.bouncycastle.operator.OutputEncryptor;
+import org.bouncycastle.operator.InputExpanderProvider;
+import org.bouncycastle.operator.OutputCompressor;
 
-public class ApplicationPkcs7MimeEntity extends MimeEntity {
+public class ApplicationPkcs7MimeCompressedDataEntity extends MimeEntity {
     
-    private static final String CONTENT_DISPOSITION = "attachment; filename=\"smime.p7m\"";
+    private static final String CONTENT_DISPOSITION = "attachment; filename=\"smime.p7z\"";
     
-    private byte[] encryptedData;
+    private byte[] compressedData;
     
-    public ApplicationPkcs7MimeEntity(MimeEntity entity2Encrypt,
-                                CMSEnvelopedDataGenerator dataGenerator,
-                                OutputEncryptor encryptor,
-                                String encryptedContentTransferEncoding,
-                                boolean isMainBody)
+    public ApplicationPkcs7MimeCompressedDataEntity(MimeEntity entity2Encrypt,
+                                                    CMSCompressedDataGenerator dataGenerator,
+                                                    OutputCompressor compressor,
+                                                    String compressedContentTransferEncoding,
+                                                    boolean isMainBody)
             throws HttpException {
-        setContentType(ContentType.create("application/pkcs7-mime", new BasicNameValuePair("smime-type", "enveloped-data"),
-                new BasicNameValuePair("name", "smime.p7m")));
-        setContentTransferEncoding(encryptedContentTransferEncoding);
+        setContentType(ContentType.create("application/pkcs7-mime", new BasicNameValuePair("smime-type", "compressed-data"),
+                new BasicNameValuePair("name", "smime.p7z")));
+        setContentTransferEncoding(compressedContentTransferEncoding);
         addHeader(AS2Header.CONTENT_DISPOSITION, CONTENT_DISPOSITION);
         setMainBody(isMainBody);
         try {
-            this.encryptedData = createEncryptedData(entity2Encrypt, dataGenerator, encryptor);
+            this.compressedData = createCompressedData(entity2Encrypt, dataGenerator, compressor);
         } catch (Exception e) {
             throw new HttpException("Failed to create encrypted data");
         }
     }
     
-    public ApplicationPkcs7MimeEntity(byte[] encryptedData, String encryptedContentTransferEncoding, boolean isMainBody) {
-        this.encryptedData = Args.notNull(encryptedData, "encryptedData");
+    public ApplicationPkcs7MimeCompressedDataEntity(byte[] compressedData, String compressedContentTransferEncoding, boolean isMainBody) {
+        this.compressedData = Args.notNull(compressedData, "encryptedData");
         
-        setContentType(ContentType.create("application/pkcs7-mime", new BasicNameValuePair("smime-type", "enveloped-datat"),
-                new BasicNameValuePair("name", "smime.p7m")));
-        setContentTransferEncoding(encryptedContentTransferEncoding);
+        setContentType(ContentType.create("application/pkcs7-mime", new BasicNameValuePair("smime-type", "compressed-datat"),
+                new BasicNameValuePair("name", "smime.p7z")));
+        setContentTransferEncoding(compressedContentTransferEncoding);
         addHeader(AS2Header.CONTENT_DISPOSITION, CONTENT_DISPOSITION);
         setMainBody(isMainBody);
     }
@@ -94,27 +94,24 @@ public class ApplicationPkcs7MimeEntity extends MimeEntity {
         String transferEncoding = getContentTransferEncoding() == null ? null : getContentTransferEncoding().getValue();
         try (OutputStream transferEncodedStream = EntityUtils.encode(ncos, transferEncoding)) {
 
-            transferEncodedStream.write(encryptedData);
+            transferEncodedStream.write(compressedData);
         } catch (Exception e) {
             throw new IOException("Failed to write to output stream", e);
         }
     }
     
-    public MimeEntity getEncryptedEntity(PrivateKey privateKey) {
-        
-        return EntityParser.parseEnvelopedEntity(encryptedData, privateKey);
-        
-        
+    public MimeEntity getCompressedEntity(InputExpanderProvider expanderProvider) throws HttpException {
+        return EntityParser.parseCompressedEntity(compressedData, expanderProvider);
     }
     
-    private byte[] createEncryptedData(MimeEntity entity2Encrypt, CMSEnvelopedDataGenerator envelopedDataGenerator, OutputEncryptor encryptor) throws Exception {
+    private byte[] createCompressedData(MimeEntity entity2Encrypt, CMSCompressedDataGenerator compressedDataGenerator, OutputCompressor compressor) throws Exception {
         try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
             entity2Encrypt.writeTo(bos);
             bos.flush();
 
             CMSTypedData contentData = new CMSProcessableByteArray(bos.toByteArray());
-            CMSEnvelopedData  envelopedData = envelopedDataGenerator.generate(contentData, encryptor);
-            return envelopedData.getEncoded();
+            CMSCompressedData  compressedData = compressedDataGenerator.generate(contentData, compressor);
+            return compressedData.getEncoded();
         } catch (Exception e) {
             throw new Exception("", e);
         }
diff --git a/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/entity/ApplicationPkcs7MimeEntity.java b/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/entity/ApplicationPkcs7MimeEntity.java
index c1d6952..5487055 100644
--- a/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/entity/ApplicationPkcs7MimeEntity.java
+++ b/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/entity/ApplicationPkcs7MimeEntity.java
@@ -100,7 +100,7 @@ public class ApplicationPkcs7MimeEntity extends MimeEntity {
         }
     }
     
-    public MimeEntity getEncryptedEntity(PrivateKey privateKey) {
+    public MimeEntity getEncryptedEntity(PrivateKey privateKey) throws HttpException {
         
         return EntityParser.parseEnvelopedEntity(encryptedData, privateKey);
         
diff --git a/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/entity/EntityParser.java b/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/entity/EntityParser.java
index aaf12e8..4d8a2b2 100644
--- a/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/entity/EntityParser.java
+++ b/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/entity/EntityParser.java
@@ -51,11 +51,14 @@ import org.apache.http.message.LineParser;
 import org.apache.http.message.ParserCursor;
 import org.apache.http.util.Args;
 import org.apache.http.util.CharArrayBuffer;
+import org.bouncycastle.cms.CMSCompressedData;
 import org.bouncycastle.cms.CMSEnvelopedData;
+import org.bouncycastle.cms.CMSException;
 import org.bouncycastle.cms.Recipient;
 import org.bouncycastle.cms.RecipientInformation;
 import org.bouncycastle.cms.RecipientInformationStore;
 import org.bouncycastle.cms.jcajce.JceKeyTransEnvelopedRecipient;
+import org.bouncycastle.operator.InputExpanderProvider;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -177,12 +180,26 @@ public final class EntityParser {
 
     }
     
-    public static MimeEntity parseEnvelopedEntity(byte[] envelopedContent, PrivateKey privateKey) {
+    public static MimeEntity parseCompressedEntity(byte[] compressedData, InputExpanderProvider expanderProvider)
+            throws HttpException {
+
+        byte[] uncompressedContent = uncompressData(compressedData, expanderProvider);
+
+        return parseEntity(uncompressedContent);
+    }
+
+    public static MimeEntity parseEnvelopedEntity(byte[] envelopedContent, PrivateKey privateKey) throws HttpException {
+
+        byte[] decryptedContent = decryptData(envelopedContent, privateKey);
+
+        return parseEntity(decryptedContent);
+    }
+
+    public static MimeEntity parseEntity(byte[] content) throws HttpException {
         
         try {
-            byte[] decryptedContent = decryptData(envelopedContent, privateKey);
             
-            InputStream is = new ByteArrayInputStream(decryptedContent);
+            InputStream is = new ByteArrayInputStream(content);
             AS2SessionInputBuffer inbuffer = new AS2SessionInputBuffer(new HttpTransportMetricsImpl(), DEFAULT_BUFFER_SIZE);
             inbuffer.bind(is);
 
@@ -191,54 +208,68 @@ public final class EntityParser {
                     new ArrayList<CharArrayBuffer>());
 
             // Get Content-Type and Content-Transfer-Encoding
-            ContentType envelopedEntityContentType = null;
-            String envelopedEntityContentTransferEncoding = null;
+            ContentType entityContentType = null;
+            String entityContentTransferEncoding = null;
             for (Header header : headers) {
                 switch (header.getName()) {
                 case AS2Header.CONTENT_TYPE:
-                    envelopedEntityContentType = ContentType.parse(header.getValue());
+                    entityContentType = ContentType.parse(header.getValue());
                     break;
                 case AS2Header.CONTENT_TRANSFER_ENCODING:
-                    envelopedEntityContentTransferEncoding = header.getValue();
+                    entityContentTransferEncoding = header.getValue();
                     break;
                 default:
                     continue;
                 }
             }
-            if (envelopedEntityContentType == null) {
+            if (entityContentType == null) {
                 throw new HttpException("Failed to find Content-Type header in enveloped entity");
             }
 
-            MimeEntity entity = parseEntityBody(inbuffer, null, envelopedEntityContentType, envelopedEntityContentTransferEncoding, headers);
+            MimeEntity entity = parseEntityBody(inbuffer, null, entityContentType, entityContentTransferEncoding, headers);
             entity.removeAllHeaders();
             entity.setHeaders(headers);
             
             return entity;
         } catch (Exception e) {
-            return null;
+            throw new HttpException("Failed to parse entity", e);
         }
     }
 
-    public static byte[] decryptData(byte[] encryptedData, PrivateKey privateKey) throws Exception {
-        // Create enveloped data from encrypted data
-        CMSEnvelopedData cmsEnvelopedData = new CMSEnvelopedData(encryptedData);
-        
-        // Extract recipient information form enveloped data.
-        RecipientInformationStore recipientsInformationStore = cmsEnvelopedData.getRecipientInfos();
-        Collection<RecipientInformation> recipients = recipientsInformationStore.getRecipients();
-        Iterator<RecipientInformation> it = recipients.iterator();
-        
-        // Decrypt if enveloped data contains recipient information
-        if (it.hasNext()) {
-            // Create recipient from private key.
-            Recipient recipient = new JceKeyTransEnvelopedRecipient(privateKey);
-
-            // Extract decrypted data from recipient information
-            RecipientInformation recipientInfo = it.next();
-            return recipientInfo.getContent(recipient);
+    public static byte[] uncompressData(byte[] compressedData, InputExpanderProvider expanderProvider)
+            throws HttpException {
+        try {
+            CMSCompressedData cmsCompressedData = new CMSCompressedData(compressedData);
+            return cmsCompressedData.getContent(expanderProvider);
+        } catch (CMSException e) {
+            throw new HttpException("Failed to decompress data", e);
+        }
+    }
+
+    public static byte[] decryptData(byte[] encryptedData, PrivateKey privateKey) throws HttpException {
+        try {
+            // Create enveloped data from encrypted data
+            CMSEnvelopedData cmsEnvelopedData = new CMSEnvelopedData(encryptedData);
+            
+            // Extract recipient information form enveloped data.
+            RecipientInformationStore recipientsInformationStore = cmsEnvelopedData.getRecipientInfos();
+            Collection<RecipientInformation> recipients = recipientsInformationStore.getRecipients();
+            Iterator<RecipientInformation> it = recipients.iterator();
+            
+            // Decrypt if enveloped data contains recipient information
+            if (it.hasNext()) {
+                // Create recipient from private key.
+                Recipient recipient = new JceKeyTransEnvelopedRecipient(privateKey);
+
+                // Extract decrypted data from recipient information
+                RecipientInformation recipientInfo = it.next();
+                return recipientInfo.getContent(recipient);
+            }
+        } catch (CMSException e) {
+            throw new HttpException("Failed to decrypt data", e);
         }
         
-        return null;
+        throw new HttpException("Failed to decrypt data: bno recipeint information");
     }
     
     public static void parseMultipartSignedEntity(HttpMessage message)
diff --git a/components/camel-as2/camel-as2-api/src/test/java/org/apache/camel/component/as2/api/entity/CompressedEntityTest.java b/components/camel-as2/camel-as2-api/src/test/java/org/apache/camel/component/as2/api/entity/CompressedEntityTest.java
new file mode 100644
index 0000000..dc549e9
--- /dev/null
+++ b/components/camel-as2/camel-as2-api/src/test/java/org/apache/camel/component/as2/api/entity/CompressedEntityTest.java
@@ -0,0 +1,89 @@
+/**
+ * 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 org.bouncycastle.cms.CMSCompressedDataGenerator;
+import org.bouncycastle.cms.jcajce.ZlibCompressor;
+import org.bouncycastle.cms.jcajce.ZlibExpanderProvider;
+import org.bouncycastle.operator.OutputCompressor;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class CompressedEntityTest {
+    
+    public static final String TEXT_PLAIN_CONTENT =
+            "MDN for -\r\n"
+            + " Message ID: <200207310834482A70BF63@\\\"~~foo~~\\\">\r\n"
+            + "  From: \"\\\"  as2Name  \\\"\"\r\n"
+            + "  To: \"0123456780000\""
+            + "  Received on: 2002-07-31 at 09:34:14 (EDT)\r\n"
+            + " Status: processed\r\n"
+            + " Comment: This is not a guarantee that the message has\r\n"
+            + "  been completely processed or &understood by the receiving\r\n"
+            + "  translator\r\n"
+            + "\r\n";
+
+    public static final String TEXT_PLAIN_CONTENT_CHARSET_NAME = "US-ASCII";
+
+    public static final String TEXT_PLAIN_CONTENT_TRANSFER_ENCODING = "7bit";
+
+    public static final String EXPECTED_TEXT_PLAIN_CONTENT =
+            "MDN for -\r\n"
+            + " Message ID: <200207310834482A70BF63@\\\"~~foo~~\\\">\r\n"
+            + "  From: \"\\\"  as2Name  \\\"\"\r\n"
+            + "  To: \"0123456780000\""
+            + "  Received on: 2002-07-31 at 09:34:14 (EDT)\r\n"
+            + " Status: processed\r\n"
+            + " Comment: This is not a guarantee that the message has\r\n"
+            + "  been completely processed or &understood by the receiving\r\n"
+            + "  translator\r\n"
+            + "\r\n";
+
+    
+    public static final String APPLICATION_PKCS7_MIME_COMPRESSED_TRANSFER_ENCODING = "base64";
+
+    @Before
+    public void setUp() throws Exception {
+    }
+
+    @After
+    public void tearDown() throws Exception {
+    }
+    
+    @Test
+    public void createCompressedEntityTest() throws Exception {
+        TextPlainEntity textPlainEntity = new TextPlainEntity(TEXT_PLAIN_CONTENT, TEXT_PLAIN_CONTENT_CHARSET_NAME,
+                TEXT_PLAIN_CONTENT_TRANSFER_ENCODING, false);
+
+        CMSCompressedDataGenerator cGen = new CMSCompressedDataGenerator();
+
+        OutputCompressor compressor = new ZlibCompressor();
+
+        ApplicationPkcs7MimeCompressedDataEntity compressedEntity = new ApplicationPkcs7MimeCompressedDataEntity(
+                textPlainEntity, cGen, compressor, APPLICATION_PKCS7_MIME_COMPRESSED_TRANSFER_ENCODING, false);
+
+        MimeEntity decompressedEntity = compressedEntity.getCompressedEntity(new ZlibExpanderProvider());
+        assertTrue("", decompressedEntity instanceof TextPlainEntity);
+        TextPlainEntity decompressedTextPlainEntity = (TextPlainEntity) decompressedEntity;
+        assertEquals("", EXPECTED_TEXT_PLAIN_CONTENT, decompressedTextPlainEntity.getText());
+    }
+
+}