/**
* Copyright (C) 2007 - 2016 52°North Initiative for Geospatial Open Source
* Software GmbH
*
* Licensed 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.n52.wps.io;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
import org.apache.commons.codec.binary.Base64InputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.xpath.XPathAPI;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;
import static org.apache.commons.io.IOUtils.*;
public class IOUtils {
/**
* Reads the given input stream as a string and decodes that base64 string
* into a file with the specified extension
*
* @param input
* the stream with the base64 string
* @param extension
* the extension of the result file (without the '.' at the
* beginning)
* @return the decoded base64 file written to disk
* @throws IOException
* if an error occurs while writing the contents to disk
*/
private static Logger LOGGER = LoggerFactory.getLogger(IOUtils.class);
public static File writeBase64ToFile(InputStream input, String extension)
throws IOException {
File file = File.createTempFile(
"file" + UUID.randomUUID(),
"." + extension,
new File(System.getProperty("java.io.tmpdir")));
OutputStream outputStream = null;
try {
outputStream = new FileOutputStream(file);
copyLarge(new Base64InputStream(input), outputStream);
} finally {
closeQuietly(outputStream);
}
return file;
}
public static File writeStreamToFile(InputStream inputStream, String extension)
throws IOException {
File file = File.createTempFile("file" + UUID.randomUUID(), "." + extension);
return writeStreamToFile(inputStream, extension, file);
}
public static File writeStreamToFile(InputStream inputStream,
String extension, File file) throws IOException {
FileOutputStream output = new FileOutputStream(file);
byte buf[]=new byte[1024];
int len;
while((len=inputStream.read(buf))>0){
output.write(buf,0,len);
}
output.close();
inputStream.close();
return file;
}
public static File writeBase64XMLToFile(InputStream stream, String extension)
throws SAXException, IOException, ParserConfigurationException,
DOMException, TransformerException {
// ToDo: look at StAX to stream XML parsing instead of in memory DOM
Document document = DocumentBuilderFactory.newInstance()
.newDocumentBuilder().parse(stream);
String binaryContent = XPathAPI.selectSingleNode(
document.getFirstChild(), "text()").getTextContent();
InputStream byteStream = null;
try {
byteStream = new ByteArrayInputStream(binaryContent.getBytes());
return writeBase64ToFile(byteStream, extension);
} finally {
closeQuietly(byteStream);
}
}
/**
* Zip the files. Returns a zipped file and delete the specified files
*
* @param files
* files to zipped
* @return the zipped file
* @throws IOException
* if the zipping process fails.
*/
public static File zip(File... files) throws IOException {
File zip = File.createTempFile("zip" + UUID.randomUUID(), ".zip");
ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zip));
byte[] buffer = new byte[4096];
for (File file : files) {
if (!file.exists()) {
LOGGER.debug("Could not zip " + file.getAbsolutePath());
continue;
}
out.putNextEntry(new ZipEntry(file.getName()));
FileInputStream in = new FileInputStream(file);
int len;
while ((len = in.read(buffer)) > 0) {
out.write(buffer, 0, len);
}
out.closeEntry();
in.close();
}
deleteResources(files);
out.close();
return zip;
}
/**
* Unzip the file. Returns the unzipped file with the specified extension
* and deletes the zipped file
*
* @param file
* the file to unzip
* @param extension
* the extension to search in the content files
* @return the file with the specified extension
* @throws IOException
* if the unzipping process fails
*/
public static List<File> unzip(File file, String extension) throws IOException {
return unzip(file, extension, null);
}
public static List<File> unzip(File file, String extension, File directory) throws IOException {
int bufferLength = 2048;
byte buffer[] = new byte[bufferLength];
List<File> foundFiles = new ArrayList<File>();
ZipInputStream zipInputStream = new ZipInputStream(
new BufferedInputStream(new FileInputStream(file)));
ZipEntry entry;
File tempDir = directory;
if (tempDir == null || !directory.isDirectory()) {
tempDir = File.createTempFile("unzipped" + UUID.randomUUID(), "", new File(System
.getProperty("java.io.tmpdir")));
tempDir.delete();
tempDir.mkdir();
}
while ((entry = zipInputStream.getNextEntry()) != null) {
int count;
File entryFile = new File(tempDir, entry.getName());
entryFile.createNewFile();
FileOutputStream fos = new FileOutputStream(entryFile);
BufferedOutputStream dest = new BufferedOutputStream(fos,
bufferLength);
while ((count = zipInputStream.read(buffer, 0, bufferLength)) != -1) {
dest.write(buffer, 0, count);
}
dest.flush();
dest.close();
if (entry.getName().endsWith("." + extension)) {
foundFiles.add(entryFile);
}
}
zipInputStream.close();
deleteResources(file);
return foundFiles;
}
public static List<File> unzipAll(File file) throws IOException {
int bufferLength = 2048;
byte buffer[] = new byte[bufferLength];
List<File> foundFiles = new ArrayList<File>();
ZipInputStream zipInputStream = new ZipInputStream(
new BufferedInputStream(new FileInputStream(file)));
ZipEntry entry;
File tempDir = File.createTempFile("unzipped" + UUID.randomUUID(), "", new File(System
.getProperty("java.io.tmpdir")));
tempDir.delete();
tempDir.mkdir();
while ((entry = zipInputStream.getNextEntry()) != null) {
int count;
File entryFile = new File(tempDir, entry.getName());
entryFile.createNewFile();
FileOutputStream fos = new FileOutputStream(entryFile);
BufferedOutputStream dest = new BufferedOutputStream(fos,
bufferLength);
while ((count = zipInputStream.read(buffer, 0, bufferLength)) != -1) {
dest.write(buffer, 0, count);
}
dest.flush();
dest.close();
foundFiles.add(entryFile);
}
zipInputStream.close();
deleteResources(file);
return foundFiles;
}
/**
* Delete the given files and all the files with the same name but different
* extension. If some file is <code>null</code> just doesn't process it and
* continue to the next element of the array
*
* @param files
* the files to delete
*/
public static void deleteResources(File... files) {
for (File file : files) {
if (file != null) {
if (file.getAbsolutePath().startsWith(
System.getProperty("java.io.tmpdir"))) {
delete(file);
File parent = file.getAbsoluteFile().getParentFile();
if (parent != null
&& !(parent.getAbsolutePath().equals(System
.getProperty("java.io.tmpdir")))) {
parent.deleteOnExit();
}
}
}
}
}
/**
* Delete the given files and all the files with the same name but different
* extension. If some file is <code>null</code> just doesn't process it and
* continue to the next element of the array
*
* @param files
* the files to delete
*/
private static void delete(File... files) {
for (File file : files) {
if (file != null) {
final String baseName = file.getName().substring(0,
file.getName().lastIndexOf("."));
File[] list = file.getAbsoluteFile().getParentFile().listFiles(
new FileFilter() {
@Override
public boolean accept(File pathname) {
return pathname.getName().startsWith(baseName);
}
});
for (File f : list) {
f.deleteOnExit();
}
file.deleteOnExit();
}
}
}
}