Java tutorial
package org.whitesource.agent.utils; /** * Copyright (C) 2014 WhiteSource Ltd. * * 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. */ import org.apache.commons.codec.binary.Base64; // import sun.misc.BASE64Decoder; // import sun.misc.BASE64Encoder; import java.io.*; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.zip.GZIPInputStream; import java.util.zip.GZIPOutputStream; /** * Utility class for various zip operations. * * @author tom.shapira * @author eugen.horovitz */ public class ZipUtils { /* --- Static members --- */ //private static final Logger logger = LoggerFactory.getLogger(ZipUtils.class); private static final String JAVA_TEMP_DIR = System.getProperty("java.io.tmpdir"); private static final String ZIP_UTILS = System.getProperty("WSZipUtils"); private static final String UTF_8 = "UTF-8"; private static final int BYTES_BUFFER_SIZE = 32 * 1024; private static final int STRING_MAX_SIZE = BYTES_BUFFER_SIZE; private static final String TMP_IN_ = "tmp_in_"; private static final String TMP_OUT_ = "tmp_out_"; private static final String ZIP_UTILS_SUFFIX = ".json"; private static final int N_THREADS = 2; /* --- Static methods --- */ /** * The method compresses the string using gzip. * * @param text The string to compress. * @return The compressed string. * @throws java.io.IOException Does some thing in old style. * @deprecated use {@link #compressString(String)} instead. */ @Deprecated public static String compress(String text) throws IOException { String result; if (text != null && text.length() > 0) { try (ByteArrayOutputStream baos = new ByteArrayOutputStream(text.length()); GZIPOutputStream gzipos = new GZIPOutputStream(baos);) { gzipos.write(text.getBytes(UTF_8)); gzipos.close(); baos.close(); // result = (new BASE64Encoder()).encode(baos.toByteArray()); result = Base64.encodeBase64String(baos.toByteArray()); /* TODO Replace result raw to this one : result = Base64.encodeBase64String(baos.toByteArray()); See : Should not be using classes that are in sun.* packages - those classes are not part of the public API Java and can change in any new Java version http://stackoverflow.com/questions/29692146/java-lang-noclassdeffounderror-sun-misc-base64encoder http://www.oracle.com/technetwork/java/faq-sun-packages-142232.html */ } } else { result = text; } return result; } /** * The method decompresses the string using gzip. * * @param text The string to decompress. * @return The decompressed string. * @throws java.io.IOException Does some thing in old style. * @deprecated use {@link #decompressString(String)} instead. */ public static String decompress(String text) throws IOException { if (text == null || text.length() == 0) { return text; } // byte[] bytes = new BASE64Decoder().decodeBuffer(text); byte[] bytes = Base64.decodeBase64(text); try (GZIPInputStream gis = new GZIPInputStream(new ByteArrayInputStream(bytes)); BufferedReader bf = new BufferedReader(new InputStreamReader(gis, UTF_8));) { StringBuilder outStr = new StringBuilder(); String line; while ((line = bf.readLine()) != null) { outStr.append(line); } return outStr.toString(); } } /** * The method decompresses the big strings using gzip - low memory via the File system * * @param text The string to decompress. * @return The decompressed temp file path that should be deleted on a later stage. * @throws java.io.IOException */ public static Path decompressChunks(String text) throws IOException { File tempFileOut = File.createTempFile(TMP_OUT_, ZIP_UTILS_SUFFIX, new File(JAVA_TEMP_DIR)); if (text == null || text.length() == 0) { return null; } // todo make it in chunks byte[] bytes = Base64.decodeBase64(text); try (InputStream inputStream = new ByteArrayInputStream(bytes)) { decompressChunks(inputStream, tempFileOut.toPath()); return tempFileOut.toPath(); } } /** * The method decompresses the big strings using gzip - low memory via the File system * * @param inputStream * @param tempFileOut * @throws IOException */ public static void decompressChunks(InputStream inputStream, Path tempFileOut) throws IOException { try (BufferedWriter writer = Files.newBufferedWriter(tempFileOut)) { try (GZIPInputStream chunkZipper = new GZIPInputStream(inputStream); InputStream in = new BufferedInputStream(chunkZipper);) { byte[] buffer = new byte[BYTES_BUFFER_SIZE]; int len; while ((len = in.read(buffer)) > 0) { byte[] writtenBytes = new byte[len]; getBytes(buffer, 0, len, writtenBytes, 0); String val = new String(writtenBytes, StandardCharsets.UTF_8); writer.write(val); } } } } public static String compressString(String text) throws IOException { try (ByteArrayOutputStream exportByteArrayOutputStream = new ByteArrayOutputStream()) { fillExportStreamCompress(text, exportByteArrayOutputStream); return getStringFromEncode(exportByteArrayOutputStream.toByteArray()); } } /** * The method compresses the big strings using gzip - low memory via Streams * @param inputStream * @param outputStream * @throws IOException */ public static void compressString(InputStream inputStream, OutputStream outputStream) throws IOException { try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) { fillExportStreamCompress(inputStream, byteArrayOutputStream); // to do -> make it in chunks String result = getStringFromEncode(byteArrayOutputStream.toByteArray()); try (PrintWriter printWriter = new PrintWriter(outputStream)) { printWriter.write(result); } } } public static String decompressString(String text) throws IOException { StringBuilder stringBuilder = new StringBuilder(); fillExportStreamDecompress(text, stringBuilder); return stringBuilder.toString(); } /** * The method decompresses the big strings using gzip - low memory via Streams * @param inputStream * @param outputStream * @throws IOException */ public static void decompressString(InputStream inputStream, OutputStream outputStream) throws IOException { try (InputStream bufferedInputStream = new BufferedInputStream(inputStream); PrintWriter printWriter = new PrintWriter(outputStream);) { byte[] buffer = new byte[BYTES_BUFFER_SIZE]; int len; while ((len = bufferedInputStream.read(buffer)) > 0) { String val = new String(buffer, StandardCharsets.UTF_8); String str = decompressString(val); printWriter.write(str); } } } /** * The method compresses the big strings using gzip - low memory via the File system * * @param text The string to compress. * @return The compressed string. * @throws java.io.IOException */ public static String compressChunks(String text) throws IOException { Path tempFolder = Paths.get(JAVA_TEMP_DIR, ZIP_UTILS); File tempFileIn = File.createTempFile(TMP_IN_, ZIP_UTILS_SUFFIX, tempFolder.toFile()); File tempFileOut = File.createTempFile(TMP_OUT_, ZIP_UTILS_SUFFIX, tempFolder.toFile()); writeChunkBytes(text, tempFileIn); String result; if (text != null && text.length() > 0) { try (InputStream in = new FileInputStream(tempFileIn); FileOutputStream fileOutputStream = new FileOutputStream(tempFileOut); BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream); OutputStream out = new GZIPOutputStream(bufferedOutputStream);) { byte[] bytes = new byte[BYTES_BUFFER_SIZE]; int len; while ((len = in.read(bytes)) > 0) { out.write(bytes, 0, len); } in.close(); out.flush(); out.close(); // result = new BASE64Encoder().encode(Files.readAllBytes(tempFileOut.toPath())); result = Base64.encodeBase64String(Files.readAllBytes(tempFileOut.toPath())); } } else { result = text; } Files.deleteIfExists(tempFileIn.toPath()); Files.deleteIfExists(tempFileOut.toPath()); return result; } /* --- Compress Helpers --- */ private static String getStringFromEncode(byte[] bytes) { // return new BASE64Encoder().encode(bytes); return Base64.encodeBase64String(bytes); } private static void fillExportStreamCompress(InputStream inputStream, OutputStream outputStream) { try { try (PipedInputStream pipedInputStream = new PipedInputStream()) { try (PipedOutputStream pipedOutputStream = new PipedOutputStream()) { pipedInputStream.connect(pipedOutputStream); Runnable producer = new Runnable() { @Override public void run() { produceCompressDataFromStream(inputStream, pipedOutputStream); } }; Runnable consumer = new Runnable() { @Override public void run() { consumeCompressData(pipedInputStream, outputStream); } }; transferData(producer, consumer); } } } catch (IOException e) { // logger.error("Failed to produce data :", e); } } private static void fillExportStreamCompress(String text, OutputStream exportByteArrayOutputStream) { try { try (PipedInputStream pipedInputStream = new PipedInputStream()) { try (PipedOutputStream pipedOutputStream = new PipedOutputStream()) { pipedInputStream.connect(pipedOutputStream); Runnable producer = new Runnable() { @Override public void run() { produceCompressDataFromText(text, pipedOutputStream); } }; Runnable consumer = new Runnable() { @Override public void run() { consumeCompressData(pipedInputStream, exportByteArrayOutputStream); } }; transferData(producer, consumer); } } } catch (IOException e) { // logger.error("Failed to produce data :", e); } } private static void transferData(Runnable producer, Runnable consumer) { ExecutorService threadPool = Executors.newFixedThreadPool(N_THREADS); threadPool.submit(producer); try { threadPool.submit(consumer).get(); } catch (InterruptedException e) { // logger.error("Task failed : ", e); } catch (ExecutionException e) { // logger.error("Task failed : ", e); } finally { // threadPool.shutdown(); } } private static void consumeCompressData(PipedInputStream pipedInputStream, OutputStream exportByteArrayOutputStream) { try (OutputStream out = new GZIPOutputStream(new BufferedOutputStream(exportByteArrayOutputStream))) { try { byte[] bytes = new byte[BYTES_BUFFER_SIZE]; int len; while ((len = pipedInputStream.read(bytes)) > 0) { out.write(bytes, 0, len); } out.flush(); } catch (IOException e) { // logger.error("Failed to consume data to compress:", e); } } catch (IOException e) { // logger.error("Failed to consume data to compress:", e); } } private static void produceCompressDataFromStream(InputStream inputStream, PipedOutputStream pipedOutputStream) { try (BufferedInputStream in = new BufferedInputStream(inputStream)) { byte[] buffer = new byte[BYTES_BUFFER_SIZE]; int len; while ((len = in.read(buffer)) > 0) { pipedOutputStream.write(buffer, 0, len); } pipedOutputStream.close(); } catch (IOException e) { // logger.error("Failed to produce data to compress : ", e); } } private static void produceCompressDataFromText(String text, PipedOutputStream pipedOutputStream) { int start_String = 0; int chunk = text.length(); if (text.length() > STRING_MAX_SIZE) { chunk = text.length() / STRING_MAX_SIZE; } try { while (start_String < text.length()) { int end = start_String + chunk; if (end > text.length()) { end = text.length(); } byte[] bytes = text.substring(start_String, end).getBytes(StandardCharsets.UTF_8); pipedOutputStream.write(bytes); start_String = end; } pipedOutputStream.close(); } catch (IOException e) { // logger.error("Failed to produce data to compress : ", e); } } private static void fillExportStreamDecompress(String text, StringBuilder stringBuilder) { try { try (PipedInputStream pipedInputStream = new PipedInputStream()) { try (PipedOutputStream pipedOutputStream = new PipedOutputStream()) { pipedInputStream.connect(pipedOutputStream); Runnable producer = new Runnable() { @Override public void run() { produceDecompressData(text, pipedOutputStream); } }; Runnable consumer = new Runnable() { @Override public void run() { consumeDecompressData(pipedInputStream, stringBuilder); } }; transferData(producer, consumer); } } } catch (IOException e) { // logger.error("Failed to decompress : ", e); } } private static void consumeDataDecompressStream(PipedInputStream pipedInputStream, OutputStream outputStream) { try (GZIPInputStream chunkZipper = new GZIPInputStream(pipedInputStream); InputStream in = new BufferedInputStream(chunkZipper);) { byte[] buffer = new byte[BYTES_BUFFER_SIZE]; int len; while ((len = in.read(buffer)) > 0) { outputStream.write(buffer, 0, len); } pipedInputStream.close(); } catch (IOException e) { // logger.error("Failed to decompress : ", e); } } private static void consumeDecompressData(PipedInputStream pipedInputStream, StringBuilder stringBuilder) { try (GZIPInputStream chunkZipper = new GZIPInputStream(pipedInputStream); InputStream in = new BufferedInputStream(chunkZipper);) { byte[] buffer = new byte[BYTES_BUFFER_SIZE]; int len; while ((len = in.read(buffer)) > 0) { if (len < buffer.length) { byte[] writtenBytes = new byte[len]; getBytes(buffer, 0, len, writtenBytes, 0); stringBuilder.append(new String(writtenBytes, StandardCharsets.UTF_8)); } else { stringBuilder.append(new String(buffer, StandardCharsets.UTF_8)); } } pipedInputStream.close(); } catch (IOException e) { // logger.error("Failed to decompress : ", e); } } public static void getBytes(byte[] source, int srcBegin, int srcEnd, byte[] destination, int dstBegin) { System.arraycopy(source, srcBegin, destination, dstBegin, srcEnd - srcBegin); } private static void produceDecompressData(String text, PipedOutputStream pipedOutputStream) { try { byte[] bytes = getStringFromDecode(text); pipedOutputStream.write(bytes); } catch (IOException e) { e.printStackTrace(); } } private static byte[] getStringFromDecode(String text) throws IOException { return Base64.decodeBase64(text); } /** * Writes a string piece by piece to file * * @param text to input * @param tempFileIn input * @throws IOException exception when writing */ private static void writeChunkBytes(String text, File tempFileIn) throws IOException { try (FileOutputStream writer = new FileOutputStream(tempFileIn)) { int chunk = text.length(); if (text.length() > STRING_MAX_SIZE) { chunk = text.length() / STRING_MAX_SIZE; } int startString = 0; while (startString < text.length()) { int endString = startString + chunk; if (endString > text.length()) { endString = text.length(); } byte[] bytes = text.substring(startString, endString).getBytes(StandardCharsets.UTF_8); writer.write(bytes); startString = endString; } } } /* --- Constructors --- */ /** * Private default constructor */ private ZipUtils() { // avoid instantiation } }