Skip to content

Instantly share code, notes, and snippets.

@ullgren
Last active May 25, 2020 15:26
Show Gist options
  • Save ullgren/3a8d924b8e5c7320eb4f to your computer and use it in GitHub Desktop.
Save ullgren/3a8d924b8e5c7320eb4f to your computer and use it in GitHub Desktop.
Mule transformer to extract a zip file into a List of InputStream
/*
* Licensed to the soi-toolkit project under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The soi-toolkit project 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 com.ullgren.mule.transformer.compression;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import org.mule.api.MuleMessage;
import org.mule.api.transformer.TransformerException;
import org.mule.config.i18n.MessageFactory;
import org.mule.routing.filters.WildcardFilter;
import org.mule.transformer.AbstractMessageTransformer;
import org.mule.transformer.types.SimpleDataType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Extracts the files in a zip-file and places them in a {@link List} of {@link InputStream}s.
* Expects the zip-file as byte-array or an inputStream.
*
* This class was initially been copied from the SOI Toolkit project (http://code.google.com/p/soi-toolkit/), updated to Mule 3 and added support for multiple files.
*
* @author magnus larsson
* @author Pontus Ullgren
*/
public class UnzipTransformer extends AbstractMessageTransformer {
private static final Logger log = LoggerFactory.getLogger(UnzipTransformer.class);
private WildcardFilter filter = new WildcardFilter("*");
private int BUFFER = 2048;
public UnzipTransformer() {
registerSourceType(new SimpleDataType<Object>(InputStream.class));
registerSourceType(new SimpleDataType<Object>(byte[].class));
setReturnDataType(new SimpleDataType<Object>(List.class));
}
public void setFilenamePattern(String pattern) {
filter.setPattern(pattern);
}
public String getFilenamePattern() {
return filter.getPattern();
}
@Override
public Object transformMessage(MuleMessage message, String outputEncoding) throws TransformerException {
Object payload = message.getPayload();
List<InputStream> resultList = new ArrayList<InputStream>();
InputStream is = null;
if (payload instanceof InputStream) {
is = (InputStream)payload;
} else if (payload instanceof byte[]) {
is = new ByteArrayInputStream((byte[]) payload);
} else {
throw new RuntimeException("Unknown payload type: " + payload.getClass().getName());
}
ZipInputStream zis = new ZipInputStream(is);
ZipEntry entry = null;
try {
while ((entry = zis.getNextEntry()) != null) {
String name = entry.getName();
// Skip folders...
if (entry.isDirectory()) {
log.debug("skip folder " + name);
continue;
}
// Does the file pass the filename-filter?
if (!filter.accept(name)) {
log.debug("skip file " + name + " did not match filename pattern: " + filter.getPattern());
continue;
}
int lastDirSep = name.lastIndexOf('/');
if (lastDirSep != -1) {
log.debug("unzip strips zip-folderpath " + name.substring(0, lastDirSep));
name = name.substring(lastDirSep + 1);
}
File tempFile = File.createTempFile("mule", "tmp");
// write the current file to disk
FileOutputStream fos = new FileOutputStream(tempFile);
// read and write until last byte is encountered
byte[] buf = new byte[BUFFER];
int readBytes = 0;
while( (readBytes = zis.read(buf,0, BUFFER)) != -1) {
fos.write(buf,0, readBytes);
}
zis.closeEntry();
fos.close();
resultList.add(new DeleteOnCloseFileInputStream(tempFile));
}
// ZipInputStream#close() will also close the underlying input stream.
zis.close();
} catch (IOException ioException) {
throw new TransformerException(MessageFactory.createStaticMessage("Failed to uncompress file."), this, ioException);
} catch (Exception e) {
throw new TransformerException(MessageFactory.createStaticMessage("Failed to uncompress file."), this, e);
}
return resultList;
}
}
package com.ullgren.mule.transformer.compression;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class DeleteOnCloseFileInputStream extends FileInputStream {
private File file;
public DeleteOnCloseFileInputStream(File file) throws FileNotFoundException {
super(file);
this.file = file;
}
public void close() throws IOException {
try {
super.close();
} finally {
if(file != null) {
file.delete();
file = null;
}
}
}
}
@ullgren
Copy link
Author

ullgren commented Jan 15, 2015

Filenames is named to force gist to list the files in a understandable order. Rename the files to be able to compile.

@alex-teles2
Copy link

Very good face, it helped me a lot

@klevertton
Copy link

I used the java classes in my mulesoft project and it helped me a lot for file extraction. Congratulations. I noticed that the return of the class is an input stream. I have a .csv file inside the .zip ... my doubt is, how do I after I extract the file to retrieve the csv name because it comes the name of the input stream.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment