Repository: camel
Updated Branches:
  refs/heads/master f1b05572e -> 6a807d605


Add unit test to support folders in zip files.

Add implementation to support folders in zip files.

Add backwards compatibility and separate entries for folders.

Add options to camel-core for ZipFileDataFormat and TarFileDataFormat.

Add unit test to support folders in tar files.

Add implementation to support folders in tar files with backwards
compatibility.

Fix checkstyle errors.


Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/38ff6658
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/38ff6658
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/38ff6658

Branch: refs/heads/master
Commit: 38ff6658f0a3c0b3fa69a8a1923f708ce4ef97d1
Parents: f1b0557
Author: Vreijsen <joery_vreij...@hotmail.com>
Authored: Tue Oct 10 14:46:20 2017 +0200
Committer: Claus Ibsen <davscl...@apache.org>
Committed: Mon Oct 16 11:04:32 2017 +0200

----------------------------------------------------------------------
 .../model/dataformat/TarFileDataFormat.java     | 17 ++++++
 .../model/dataformat/ZipFileDataFormat.java     | 17 ++++++
 .../dataformat/tarfile/TarFileDataFormat.java   | 54 +++++++++++++++++---
 .../tarfile/TarFileDataFormatTest.java          | 31 +++++++++++
 .../camel/dataformat/tarfile/TarUtils.java      | 21 ++++++++
 .../dataformat/zipfile/ZipFileDataFormat.java   | 51 +++++++++++++++---
 .../zipfile/ZipFileDataFormatTest.java          | 36 +++++++++++++
 7 files changed, 214 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/38ff6658/camel-core/src/main/java/org/apache/camel/model/dataformat/TarFileDataFormat.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/main/java/org/apache/camel/model/dataformat/TarFileDataFormat.java
 
b/camel-core/src/main/java/org/apache/camel/model/dataformat/TarFileDataFormat.java
index 26153f8..b9b5a0e 100644
--- 
a/camel-core/src/main/java/org/apache/camel/model/dataformat/TarFileDataFormat.java
+++ 
b/camel-core/src/main/java/org/apache/camel/model/dataformat/TarFileDataFormat.java
@@ -37,6 +37,8 @@ public class TarFileDataFormat extends DataFormatDefinition {
     private Boolean usingIterator;
     @XmlAttribute
     private Boolean allowEmptyDirectory;
+    @XmlAttribute
+    private Boolean preservePathElements;
 
     public TarFileDataFormat() {
         super("tarfile");
@@ -47,6 +49,9 @@ public class TarFileDataFormat extends DataFormatDefinition {
         if (usingIterator != null) {
             setProperty(camelContext, dataFormat, "usingIterator", 
usingIterator);
         }
+        if (preservePathElements != null) {
+            setProperty(camelContext, dataFormat, "preservePathElements", 
preservePathElements);
+        }
     }
 
     public Boolean getUsingIterator() {
@@ -57,6 +62,10 @@ public class TarFileDataFormat extends DataFormatDefinition {
         return allowEmptyDirectory;
     }
 
+    public Boolean getPreservePathElements() {
+        return preservePathElements;
+    }
+
     /**
      * If the tar file has more then one entry, the setting this option to 
true, allows to work with the splitter EIP,
      * to split the data using an iterator in a streaming mode.
@@ -72,4 +81,12 @@ public class TarFileDataFormat extends DataFormatDefinition {
     public void setAllowEmptyDirectory(Boolean allowEmptyDirectory) {
         this.allowEmptyDirectory = allowEmptyDirectory;
     }
+
+    /**
+     * If the file name contains path elements, setting this option to true, 
allows the path to be maintained
+     * in the tar file.
+     */
+    public void setPreservePathElements(Boolean preservePathElements) {
+        this.preservePathElements = preservePathElements;
+    }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/38ff6658/camel-core/src/main/java/org/apache/camel/model/dataformat/ZipFileDataFormat.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/main/java/org/apache/camel/model/dataformat/ZipFileDataFormat.java
 
b/camel-core/src/main/java/org/apache/camel/model/dataformat/ZipFileDataFormat.java
index ff2dd60..4d98796 100644
--- 
a/camel-core/src/main/java/org/apache/camel/model/dataformat/ZipFileDataFormat.java
+++ 
b/camel-core/src/main/java/org/apache/camel/model/dataformat/ZipFileDataFormat.java
@@ -38,6 +38,8 @@ public class ZipFileDataFormat extends DataFormatDefinition {
     private Boolean usingIterator;
     @XmlAttribute
     private Boolean allowEmptyDirectory;
+    @XmlAttribute
+    private Boolean preservePathElements;
 
     public ZipFileDataFormat() {
         super("zipfile");
@@ -51,6 +53,9 @@ public class ZipFileDataFormat extends DataFormatDefinition {
         if (allowEmptyDirectory != null) {
             setProperty(camelContext, dataFormat, "allowEmptyDirectory", 
allowEmptyDirectory);
         }
+        if (preservePathElements != null) {
+            setProperty(camelContext, dataFormat, "preservePathElements", 
preservePathElements);
+        }
     }
 
     public Boolean getUsingIterator() {
@@ -61,6 +66,10 @@ public class ZipFileDataFormat extends DataFormatDefinition {
         return allowEmptyDirectory;
     }
 
+    public Boolean getPreservePathElements() {
+        return preservePathElements;
+    }
+
     /**
      * If the zip file has more then one entry, the setting this option to 
true, allows to work with the splitter EIP,
      * to split the data using an iterator in a streaming mode.
@@ -77,4 +86,12 @@ public class ZipFileDataFormat extends DataFormatDefinition {
         this.allowEmptyDirectory = allowEmptyDirectory;
     }
 
+    /**
+     * If the file name contains path elements, setting this option to true, 
allows the path to be maintained
+     * in the zip file.
+     */
+    public void setPreservePathElements(Boolean preservePathElements) {
+        this.preservePathElements = preservePathElements;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/38ff6658/components/camel-tarfile/src/main/java/org/apache/camel/dataformat/tarfile/TarFileDataFormat.java
----------------------------------------------------------------------
diff --git 
a/components/camel-tarfile/src/main/java/org/apache/camel/dataformat/tarfile/TarFileDataFormat.java
 
b/components/camel-tarfile/src/main/java/org/apache/camel/dataformat/tarfile/TarFileDataFormat.java
index b226c6e..35b1a9c 100644
--- 
a/components/camel-tarfile/src/main/java/org/apache/camel/dataformat/tarfile/TarFileDataFormat.java
+++ 
b/components/camel-tarfile/src/main/java/org/apache/camel/dataformat/tarfile/TarFileDataFormat.java
@@ -17,9 +17,12 @@
 package org.apache.camel.dataformat.tarfile;
 
 import java.io.BufferedInputStream;
+import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.nio.file.Path;
 import java.nio.file.Paths;
+import java.util.Iterator;
 
 import org.apache.camel.Exchange;
 import org.apache.camel.converter.stream.OutputStreamBuilder;
@@ -43,6 +46,7 @@ import static org.apache.camel.Exchange.FILE_NAME;
 public class TarFileDataFormat extends ServiceSupport implements DataFormat, 
DataFormatName {
     private boolean usingIterator;
     private boolean allowEmptyDirectory;
+    private boolean preservePathElements;
 
     @Override
     public String getDataFormatName() {
@@ -51,13 +55,14 @@ public class TarFileDataFormat extends ServiceSupport 
implements DataFormat, Dat
 
     @Override
     public void marshal(final Exchange exchange, final Object graph, final 
OutputStream stream) throws Exception {
-        String filename = exchange.getIn().getHeader(FILE_NAME, String.class);
+        String filename;
+        String filepath = exchange.getIn().getHeader(FILE_NAME, String.class);
         Long filelength = exchange.getIn().getHeader(FILE_LENGTH, Long.class);
-        if (filename == null) {
+        if (filepath == null) {
             // generate the file name as the camel file component would do
-            filename = StringHelper.sanitize(exchange.getIn().getMessageId());
+            filename = filepath = 
StringHelper.sanitize(exchange.getIn().getMessageId());
         } else {
-            filename = Paths.get(filename).getFileName().toString(); // remove 
any path elements
+            filename = Paths.get(filepath).getFileName().toString(); // remove 
any path elements
         }
 
         TarArchiveOutputStream tos = new TarArchiveOutputStream(stream);
@@ -69,9 +74,11 @@ public class TarFileDataFormat extends ServiceSupport 
implements DataFormat, Dat
             filelength = (long) is.available();
         }
 
-        TarArchiveEntry entry = new TarArchiveEntry(filename);
-        entry.setSize(filelength);
-        tos.putArchiveEntry(entry);
+        if (preservePathElements) {
+            createTarEntries(tos, filepath, filelength);
+        } else {
+            createTarEntries(tos, filename, filelength);
+        }
 
         try {
             IOHelper.copy(is, tos);
@@ -115,6 +122,31 @@ public class TarFileDataFormat extends ServiceSupport 
implements DataFormat, Dat
         }
     }
 
+    private void createTarEntries(TarArchiveOutputStream tos, String filepath, 
Long filelength) throws IOException {
+        Iterator<Path> elements = Paths.get(filepath).iterator();
+        StringBuilder sb = new StringBuilder();
+
+        while (elements.hasNext()) {
+            Path path = elements.next();
+            String element = path.toString();
+            Long length = filelength;
+
+            // If there are more elements to come this element is a directory
+            // The "/" at the end tells the TarEntry it is a folder
+            if (elements.hasNext()) {
+                element += "/";
+                length = 0L;
+            }
+
+            // Each entry needs the complete path, including previous created 
folders.
+            TarArchiveEntry entry = new TarArchiveEntry(sb + element);
+            entry.setSize(length);
+            tos.putArchiveEntry(entry);
+
+            sb.append(element);
+        }
+    }
+
     public boolean isUsingIterator() {
         return usingIterator;
     }
@@ -131,6 +163,14 @@ public class TarFileDataFormat extends ServiceSupport 
implements DataFormat, Dat
         this.allowEmptyDirectory = allowEmptyDirectory;
     }
 
+    public boolean isPreservePathElements() {
+        return preservePathElements;
+    }
+
+    public void setPreservePathElements(boolean preservePathElements) {
+        this.preservePathElements = preservePathElements;
+    }
+
     @Override
     protected void doStart() throws Exception {
         // noop

http://git-wip-us.apache.org/repos/asf/camel/blob/38ff6658/components/camel-tarfile/src/test/java/org/apache/camel/dataformat/tarfile/TarFileDataFormatTest.java
----------------------------------------------------------------------
diff --git 
a/components/camel-tarfile/src/test/java/org/apache/camel/dataformat/tarfile/TarFileDataFormatTest.java
 
b/components/camel-tarfile/src/test/java/org/apache/camel/dataformat/tarfile/TarFileDataFormatTest.java
index 7f8b792..b74cfb6 100644
--- 
a/components/camel-tarfile/src/test/java/org/apache/camel/dataformat/tarfile/TarFileDataFormatTest.java
+++ 
b/components/camel-tarfile/src/test/java/org/apache/camel/dataformat/tarfile/TarFileDataFormatTest.java
@@ -43,6 +43,7 @@ import static org.apache.camel.Exchange.FILE_NAME;
 import static org.apache.camel.dataformat.tarfile.TarUtils.TEXT;
 import static org.apache.camel.dataformat.tarfile.TarUtils.getBytes;
 import static org.apache.camel.dataformat.tarfile.TarUtils.getTaredText;
+import static 
org.apache.camel.dataformat.tarfile.TarUtils.getTaredTextInFolder;
 
 /**
  * Unit tests for {@link TarFileDataFormat}.
@@ -81,6 +82,36 @@ public class TarFileDataFormatTest extends CamelTestSupport {
     }
 
     @Test
+    public void testTarWithPathElements() throws Exception {
+        MockEndpoint mock = getMockEndpoint("mock:tar");
+        mock.expectedMessageCount(1);
+        mock.expectedHeaderReceived(FILE_NAME, "poem.txt.tar");
+
+        template.sendBodyAndHeader("direct:tar", TEXT, FILE_NAME, 
"poems/poem.txt");
+
+        assertMockEndpointsSatisfied();
+
+        Exchange exchange = mock.getReceivedExchanges().get(0);
+        assertTrue(ObjectHelper.equalByteArray(getTaredText("poem.txt"), 
(byte[]) exchange.getIn().getBody()));
+    }
+
+    @Test
+    public void testTarWithPreservedPathElements() throws Exception {
+        MockEndpoint mock = getMockEndpoint("mock:tar");
+        mock.expectedMessageCount(1);
+        mock.expectedHeaderReceived(FILE_NAME, "poem.txt.tar");
+
+        tar.setPreservePathElements(true);
+
+        template.sendBodyAndHeader("direct:tar", TEXT, FILE_NAME, 
"poems/poem.txt");
+
+        assertMockEndpointsSatisfied();
+
+        Exchange exchange = mock.getReceivedExchanges().get(0);
+        assertTrue(ObjectHelper.equalByteArray(getTaredTextInFolder("poems/", 
"poems/poem.txt"), (byte[]) exchange.getIn().getBody()));
+    }
+
+    @Test
     public void testUntar() throws Exception {
         getMockEndpoint("mock:untar").expectedBodiesReceived(TEXT);
         getMockEndpoint("mock:untar").expectedHeaderReceived(FILE_NAME, 
"file");

http://git-wip-us.apache.org/repos/asf/camel/blob/38ff6658/components/camel-tarfile/src/test/java/org/apache/camel/dataformat/tarfile/TarUtils.java
----------------------------------------------------------------------
diff --git 
a/components/camel-tarfile/src/test/java/org/apache/camel/dataformat/tarfile/TarUtils.java
 
b/components/camel-tarfile/src/test/java/org/apache/camel/dataformat/tarfile/TarUtils.java
index df07907..4acf633 100644
--- 
a/components/camel-tarfile/src/test/java/org/apache/camel/dataformat/tarfile/TarUtils.java
+++ 
b/components/camel-tarfile/src/test/java/org/apache/camel/dataformat/tarfile/TarUtils.java
@@ -59,6 +59,27 @@ final class TarUtils {
         return baos.toByteArray();
     }
 
+    static byte[] getTaredTextInFolder(String folder, String file) throws 
IOException {
+        ByteArrayInputStream bais = new 
ByteArrayInputStream(TEXT.getBytes("UTF-8"));
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        TarArchiveOutputStream tos = new TarArchiveOutputStream(baos);
+        try {
+            TarArchiveEntry folderEntry = new TarArchiveEntry(folder);
+            folderEntry.setSize(0L);
+            tos.putArchiveEntry(folderEntry);
+
+            TarArchiveEntry fileEntry = new TarArchiveEntry(file);
+            fileEntry.setSize(bais.available());
+            tos.putArchiveEntry(fileEntry);
+
+            IOHelper.copy(bais, tos);
+        } finally {
+            tos.closeArchiveEntry();
+            IOHelper.close(bais, tos);
+        }
+        return baos.toByteArray();
+    }
+
     static byte[] getBytes(File file) throws IOException {
         FileInputStream fis = new FileInputStream(file);
         ByteArrayOutputStream baos = new ByteArrayOutputStream();

http://git-wip-us.apache.org/repos/asf/camel/blob/38ff6658/components/camel-zipfile/src/main/java/org/apache/camel/dataformat/zipfile/ZipFileDataFormat.java
----------------------------------------------------------------------
diff --git 
a/components/camel-zipfile/src/main/java/org/apache/camel/dataformat/zipfile/ZipFileDataFormat.java
 
b/components/camel-zipfile/src/main/java/org/apache/camel/dataformat/zipfile/ZipFileDataFormat.java
index 171858e..28ce82c 100644
--- 
a/components/camel-zipfile/src/main/java/org/apache/camel/dataformat/zipfile/ZipFileDataFormat.java
+++ 
b/components/camel-zipfile/src/main/java/org/apache/camel/dataformat/zipfile/ZipFileDataFormat.java
@@ -16,9 +16,12 @@
  */
 package org.apache.camel.dataformat.zipfile;
 
+import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.nio.file.Path;
 import java.nio.file.Paths;
+import java.util.Iterator;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipInputStream;
 import java.util.zip.ZipOutputStream;
@@ -40,6 +43,7 @@ import static org.apache.camel.Exchange.FILE_NAME;
 public class ZipFileDataFormat extends ServiceSupport implements DataFormat, 
DataFormatName {
     private boolean usingIterator;
     private boolean allowEmptyDirectory;
+    private boolean preservePathElements;
 
     @Override
     public String getDataFormatName() {
@@ -48,16 +52,22 @@ public class ZipFileDataFormat extends ServiceSupport 
implements DataFormat, Dat
 
     @Override
     public void marshal(final Exchange exchange, final Object graph, final 
OutputStream stream) throws Exception {
-        String filename = exchange.getIn().getHeader(FILE_NAME, String.class);
-        if (filename == null) {
+        String filename;
+        String filepath = exchange.getIn().getHeader(FILE_NAME, String.class);
+        if (filepath == null) {
             // generate the file name as the camel file component would do
-            filename = StringHelper.sanitize(exchange.getIn().getMessageId());
+            filename = filepath = 
StringHelper.sanitize(exchange.getIn().getMessageId());
         } else {
-            filename = Paths.get(filename).getFileName().toString(); // remove 
any path elements
+            filename = Paths.get(filepath).getFileName().toString(); // remove 
any path elements
         }
 
         ZipOutputStream zos = new ZipOutputStream(stream);
-        zos.putNextEntry(new ZipEntry(filename));
+
+        if (preservePathElements) {
+            createZipEntries(zos, filepath);
+        } else {
+            createZipEntries(zos, filename);
+        }
 
         InputStream is = 
exchange.getContext().getTypeConverter().mandatoryConvertTo(InputStream.class, 
exchange, graph);
 
@@ -100,6 +110,27 @@ public class ZipFileDataFormat extends ServiceSupport 
implements DataFormat, Dat
         }
     }
 
+    private void createZipEntries(ZipOutputStream zos, String filepath) throws 
IOException {
+        Iterator<Path> elements = Paths.get(filepath).iterator();
+        StringBuilder sb = new StringBuilder();
+
+        while (elements.hasNext()) {
+            Path path = elements.next();
+            String element = path.toString();
+
+            // If there are more elements to come this element is a directory
+            // The "/" at the end tells the ZipEntry it is a folder
+            if (elements.hasNext()) {
+                element += "/";
+            }
+
+            // Each entry needs the complete path, including previous created 
folders.
+            zos.putNextEntry(new ZipEntry(sb + element));
+
+            sb.append(element);
+        }
+    }
+
     public boolean isUsingIterator() {
         return usingIterator;
     }
@@ -116,6 +147,14 @@ public class ZipFileDataFormat extends ServiceSupport 
implements DataFormat, Dat
         this.allowEmptyDirectory = allowEmptyDirectory;
     }
 
+    public boolean isPreservePathElements() {
+        return preservePathElements;
+    }
+
+    public void setPreservePathElements(boolean preservePathElements) {
+        this.preservePathElements = preservePathElements;
+    }
+
     @Override
     protected void doStart() throws Exception {
         // noop
@@ -125,4 +164,4 @@ public class ZipFileDataFormat extends ServiceSupport 
implements DataFormat, Dat
     protected void doStop() throws Exception {
         // noop
     }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/38ff6658/components/camel-zipfile/src/test/java/org/apache/camel/dataformat/zipfile/ZipFileDataFormatTest.java
----------------------------------------------------------------------
diff --git 
a/components/camel-zipfile/src/test/java/org/apache/camel/dataformat/zipfile/ZipFileDataFormatTest.java
 
b/components/camel-zipfile/src/test/java/org/apache/camel/dataformat/zipfile/ZipFileDataFormatTest.java
index 305283e..63b1b03 100644
--- 
a/components/camel-zipfile/src/test/java/org/apache/camel/dataformat/zipfile/ZipFileDataFormatTest.java
+++ 
b/components/camel-zipfile/src/test/java/org/apache/camel/dataformat/zipfile/ZipFileDataFormatTest.java
@@ -104,6 +104,28 @@ public class ZipFileDataFormatTest extends 
CamelTestSupport {
     }
 
     @Test
+    public void testZipWithPathElements() throws Exception {
+        
getMockEndpoint("mock:zip").expectedBodiesReceived(getZippedText("poem.txt"));
+        getMockEndpoint("mock:zip").expectedHeaderReceived(FILE_NAME, 
"poem.txt.zip");
+
+        template.sendBodyAndHeader("direct:zip", TEXT, FILE_NAME, 
"poems/poem.txt");
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Test
+    public void testZipWithPreservedPathElements() throws Exception {
+        zip.setPreservePathElements(true);
+
+        
getMockEndpoint("mock:zip").expectedBodiesReceived(getZippedTextInFolder("poems/",
 "poems/poem.txt"));
+        getMockEndpoint("mock:zip").expectedHeaderReceived(FILE_NAME, 
"poem.txt.zip");
+
+        template.sendBodyAndHeader("direct:zip", TEXT, FILE_NAME, 
"poems/poem.txt");
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Test
     public void testUnzip() throws Exception {
         getMockEndpoint("mock:unzip").expectedBodiesReceived(TEXT);
         getMockEndpoint("mock:unzip").expectedHeaderReceived(FILE_NAME, 
"file");
@@ -298,6 +320,20 @@ public class ZipFileDataFormatTest extends 
CamelTestSupport {
         return baos.toByteArray();
     }
 
+    private static byte[] getZippedTextInFolder(String folder, String file) 
throws IOException {
+        ByteArrayInputStream bais = new 
ByteArrayInputStream(TEXT.getBytes("UTF-8"));
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ZipOutputStream zos = new ZipOutputStream(baos);
+        try {
+            zos.putNextEntry(new ZipEntry(folder));
+            zos.putNextEntry(new ZipEntry(file));
+            IOHelper.copy(bais, zos);
+        } finally {
+            IOHelper.close(bais, zos);
+        }
+        return baos.toByteArray();
+    }
+
     private static byte[] getBytes(File file) throws IOException {
         FileInputStream fis = new FileInputStream(file);
         ByteArrayOutputStream baos = new ByteArrayOutputStream();

Reply via email to