4

I have been trying to zip multiple csv file in my route. I have been successfully able to do that.

I am using spring to do the same.

Now the new requirement is to password protect them. Following is the aggregation strategy I have used. How to achieve this?

<route autoStartup="false" routePolicyRef="routeTwoTimer" startupOrder="2" id="zippingFileRoute">
    <from uri="{{to.file.processed1}}"/>
    <choice id="csvZipFile">
        <when>
            <simple>$simple{header.CamelFileName} regex '^.*(csv|CSV)$'</simple>
            <aggregate strategyRef="zipAggregationStrategy" completionFromBatchConsumer="true" eagerCheckCompletion="true">
                <correlationExpression>
                    <constant>true</constant>
                </correlationExpression>
                <to uri="{{to.file.processed2}}"/>
            </aggregate>
        </when>
    </choice>
</route>
Yoogi
  • 123
  • 7
  • You haven't asked a question. Are you saying you don't know what to do? Have you tried something and it isn't working? – Ray Oct 16 '14 at 15:00
  • Yes Ray I do not know how can it be done. – Yoogi Oct 16 '14 at 22:53
  • You're right, the [actual documentation](http://camel.apache.org/zip-file-dataformat.html) does not say anything about any zip options (like passwords). I guess it is not supported as-is. One option would be to crypt all files and then compress (in the zip), or compress and crypt the zip file after. – рüффп May 09 '15 at 21:03
  • [This post](http://stackoverflow.com/a/10587717/628006) says there's no password encryption in Java OOB. However there are few libraries that can be integrated to your project. I would personally create a specific Camel Processor to use the library to create the Zip file. – рüффп Jul 14 '15 at 10:47

1 Answers1

0

As pointed in comments, Java API is a bit limited in encrypting ZIP files. Apache Camel ZipAggregationStrategy is using ZipOutputStream, so there is this limitation too. You can implement custom Aggregator using any other library, which allows encryption of Zip files. For example Zip4j

Add Maven dependency

<dependency>
    <groupId>net.lingala.zip4j</groupId>
    <artifactId>zip4j</artifactId>
    <version>1.3.2</version>
</dependency>

Implement custom Aggregator

import net.lingala.zip4j.core.ZipFile;
//next few imports. I have added this only to take correct ZipFile class, not the JDK one 

public class PasswordZipAggregationStrategy implements AggregationStrategy {

public static final String ZIP_PASSWORD_HEADER = "PasswordZipAggregationStrategy.ZipPassword";

@Override
public Exchange aggregate(Exchange oldExchange, Exchange newExchange){
    try {
        if (newExchange == null) {
            return oldExchange;
        }
        return aggregateUnchecked(oldExchange,newExchange);
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

private Exchange aggregateUnchecked(Exchange oldExchange, Exchange newExchange) throws Exception{
    ZipFile zipFile;
    String password;
    if (oldExchange == null) { // first
        password = newExchange.getIn().getHeader(ZIP_PASSWORD_HEADER, String.class);
        zipFile = new ZipFile(newExchange.getExchangeId()+".zip");
        File toDelete = new File(zipFile.getFile().getPath());
        newExchange.addOnCompletion(new Synchronization() {
            @Override
            public void onComplete(Exchange exchange) {
                toDelete.delete();
            }

            @Override
            public void onFailure(Exchange exchange) {
            }
        });
    } else {
        password = newExchange.getIn().getHeader(ZIP_PASSWORD_HEADER, String.class);
        zipFile = new ZipFile(oldExchange.getIn().getBody(File.class));
    }

    if (password==null){
        throw new IllegalStateException("Null password given");
    }

    ZipParameters zipParameters = new ZipParameters();
    zipParameters.setPassword(password);
    zipParameters.setEncryptFiles(true);
    zipParameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_FAST);
    zipParameters.setEncryptionMethod(Zip4jConstants.ENC_METHOD_STANDARD);
    zipFile.addFile(newExchange.getIn().getBody(File.class), zipParameters);
    GenericFile genericFile = FileConsumer.asGenericFile(zipFile.getFile().getParent(), zipFile.getFile(), Charset.defaultCharset().toString(), false);
    genericFile.bindToExchange(newExchange);

    newExchange.getIn().setBody(zipFile.getFile());
    newExchange.getIn().setHeader(ZIP_PASSWORD_HEADER, password);
    return newExchange;
}
}

Use it

from("file://in")
    .to("log:in")
    .setHeader(PasswordZipAggregationStrategy.ZIP_PASSWORD_HEADER, constant("testPassword"))
    .aggregate().constant(true).completionFromBatchConsumer()
        .aggregationStrategy(new PasswordZipAggregationStrategy())
.to("log:out")
.to("file://out");
Bedla
  • 4,789
  • 2
  • 13
  • 27