package er.extensions.foundation; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.util.zip.DeflaterOutputStream; import java.util.zip.GZIPInputStream; import java.util.zip.GZIPOutputStream; import java.util.zip.InflaterInputStream; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import java.util.zip.ZipOutputStream; import org.apache.commons.lang3.CharEncoding; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.webobjects.foundation.NSData; public class ERXCompressionUtilities { private static final Logger log = LoggerFactory.getLogger(ERXCompressionUtilities.class); /** * Returns an NSData containing the gzipped version of the given input stream. * * @param input the input stream to compress * @param length the length of the input stream * @return gzipped NSData */ public static NSData gzipInputStreamAsNSData(InputStream input, int length) { try (ERXRefByteArrayOutputStream bos = new ERXRefByteArrayOutputStream(length)) { if (input != null) { try (GZIPOutputStream out = new GZIPOutputStream(bos)) { ERXFileUtilities.writeInputStreamToOutputStream(input, true, out, false); } } return bos.toNSData(); } catch (IOException e) { log.error("Failed to gzip byte array.", e); return null; } } public static NSData gzipNSDataAsNSData(NSData data) { NSData gzippedData = null; if (data != null) { gzippedData = ERXCompressionUtilities.gzipByteArrayAsNSData(data._bytesNoCopy(), 0, data.length()); } return gzippedData; } public static NSData gzipByteArrayAsNSData(byte[] input, int offset, int length) { try (ERXRefByteArrayOutputStream bos = new ERXRefByteArrayOutputStream(length)) { if (input != null) { try (GZIPOutputStream out = new GZIPOutputStream(bos)) { out.write(input, offset, length); } } return bos.toNSData(); } catch (IOException e) { log.error("Failed to gzip byte array.", e); return null; } } public static byte[] gzipByteArray(byte[] input) { try (ByteArrayOutputStream bos = new ByteArrayOutputStream(input.length); GZIPOutputStream out = new GZIPOutputStream(bos)) { out.write(input, 0, input.length); byte[] compressedData = bos.toByteArray(); return compressedData; } catch (IOException e) { log.error("Failed to gzip byte array.", e); return null; } } public static byte[] gunzipByteArray(byte[] input) { try (ByteArrayInputStream bos = new ByteArrayInputStream(input); GZIPInputStream in = new GZIPInputStream(bos)) { byte[] uncompressedData = ERXFileUtilities.bytesFromInputStream(in); return uncompressedData; } catch (IOException e) { return null; } } public static String gunzipString(String source) { try { byte[] b = gunzipByteArray(source.getBytes(CharEncoding.UTF_8)); return new String(b, CharEncoding.UTF_8); } catch (UnsupportedEncodingException e) { return null; } } public static String gunzipByteArrayAsString(byte[] input) { try { byte[] b = gunzipByteArray(input); return new String(b, CharEncoding.UTF_8); } catch (UnsupportedEncodingException e) { return null; } } public static byte[] gzipStringAsByteArray(String source) { try { return gzipByteArray(source.getBytes(CharEncoding.UTF_8)); } catch (UnsupportedEncodingException e) { return null; } } public static byte[] zipByteArray(byte[] input) { return ERXCompressionUtilities.zipByteArray(input, "tmp"); } public static byte[] zipByteArray(byte[] input, String zipEntryName) { try (ByteArrayOutputStream bos = new ByteArrayOutputStream(input.length); ZipOutputStream out = new ZipOutputStream(bos)) { out.putNextEntry(new ZipEntry(zipEntryName)); out.write(input, 0, input.length); out.closeEntry(); byte[] compressedData = bos.toByteArray(); return compressedData; } catch (IOException e) { log.error("Caught exception zipping byte array: {}", e, e); return null; } } public static File unzipByteArrayIntoDirectory(byte[] input, File directory, boolean overwrite) { try { if (!directory.exists()) { directory.mkdirs(); directory.mkdir(); if (!directory.exists()) { throw new IllegalStateException("could not create directory " + directory); } } else { if (!overwrite) { throw new IllegalStateException("overwrite is false and file " + directory + " does exist"); } else if (!directory.isDirectory()) { throw new IllegalArgumentException("file " + directory + " is NOT an directory"); } } long start = System.currentTimeMillis(); try (ByteArrayInputStream bos = new ByteArrayInputStream(input); ZipInputStream in = new ZipInputStream(bos)) { ZipEntry entry = null; while ((entry = in.getNextEntry()) != null) { String oriName = entry.getName(); String filename = directory.getAbsolutePath() + File.separator + oriName; if (entry.isDirectory()) { log.debug("creating directory {}", oriName); File f = new File(filename); f.mkdirs(); f.mkdir(); } else { int uncompressedSize = (int) entry.getSize(); if (uncompressedSize > -1) { byte[] b = new byte[uncompressedSize]; in.read(b); try (FileOutputStream fis = new FileOutputStream(filename)) { fis.write(b); } log.debug("unzipped entry {}", filename); } } } long end = System.currentTimeMillis(); log.debug("whole decompression took {}ms", end - start); return directory; } } catch (IOException e) { return null; } } public static byte[] deflateByteArray(byte[] input) { try (ByteArrayOutputStream bos = new ByteArrayOutputStream(input.length); DeflaterOutputStream out = new DeflaterOutputStream(bos)) { out.write(input, 0, input.length); byte[] compressedData = bos.toByteArray(); return compressedData; } catch (IOException e) { return null; } } public static byte[] inflateByteArray(byte[] input) { try (ByteArrayInputStream bos = new ByteArrayInputStream(input); InflaterInputStream in = new InflaterInputStream(bos)) { byte[] uncompressedData = ERXFileUtilities.bytesFromInputStream(in); return uncompressedData; } catch (IOException e) { return null; } } public static String deflateString(String source) { try { return new String(deflateByteArray(source.getBytes(CharEncoding.UTF_8)), CharEncoding.UTF_8); } catch (UnsupportedEncodingException e) { return null; } } public static String inflateString(String source) { try { byte[] b = inflateByteArray(source.getBytes(CharEncoding.UTF_8)); return new String(b, CharEncoding.UTF_8); } catch (UnsupportedEncodingException e) { return null; } } }