Skip to content

Commit ba42544

Browse files
tomas-sexenianBeta Bot
authored andcommitted
Cherry pick branch 'genexuslabs:Compress' into beta
1 parent 1b78c21 commit ba42544

File tree

1 file changed

+191
-85
lines changed

1 file changed

+191
-85
lines changed

gxcompress/src/main/java/com/genexus/compression/GXCompressor.java

Lines changed: 191 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
import com.genexus.GXBaseCollection;
55
import com.genexus.SdtMessages_Message;
66
import com.genexus.StructSdtMessages_Message;
7-
import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
87
import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream;
8+
import org.apache.commons.compress.compressors.gzip.GzipParameters;
99
import org.apache.logging.log4j.Logger;
1010

1111
import org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry;
@@ -18,10 +18,9 @@
1818
import java.io.*;
1919
import java.nio.file.Files;
2020
import java.util.ArrayList;
21-
import java.util.Enumeration;
2221
import java.util.Stack;
2322
import java.util.jar.JarEntry;
24-
import java.util.jar.JarFile;
23+
import java.util.jar.JarInputStream;
2524
import java.util.jar.JarOutputStream;
2625
import java.util.zip.*;
2726

@@ -287,62 +286,106 @@ private static void addFileToTar(TarArchiveOutputStream tarOut, File file, Strin
287286
}
288287

289288
private static void compressToGzip(File[] files, String outputPath) throws IOException {
289+
if (files == null || files.length == 0) {
290+
throw new IllegalArgumentException("No files to compress");
291+
}
290292
if (outputPath == null || outputPath.isEmpty()) {
291293
throw new IllegalArgumentException("Output path is null or empty");
292294
}
293295
File outputFile = new File(outputPath);
294296
if (outputFile.exists() && !outputFile.canWrite()) {
295297
throw new IOException("Cannot write to output file");
296-
} else {
297-
File parentDir = outputFile.getParentFile();
298-
if (parentDir != null && !parentDir.exists() && !parentDir.mkdirs()) {
299-
throw new IOException("Failed to create output directory");
300-
}
301298
}
302-
try (FileOutputStream fos = new FileOutputStream(outputFile);
303-
BufferedOutputStream bos = new BufferedOutputStream(fos);
304-
GzipCompressorOutputStream gcos = new GzipCompressorOutputStream(bos);
305-
TarArchiveOutputStream taos = new TarArchiveOutputStream(gcos)) {
306-
taos.setLongFileMode(TarArchiveOutputStream.LONGFILE_GNU);
307-
Stack<File> stack = new Stack<>();
308-
Stack<String> pathStack = new Stack<>();
309-
for (File file : files) {
310-
if (file == null) continue;
311-
stack.push(file);
312-
pathStack.push("");
299+
File parentDir = outputFile.getParentFile();
300+
if (parentDir != null && !parentDir.exists() && !parentDir.mkdirs()) {
301+
throw new IOException("Failed to create output directory");
302+
}
303+
boolean singleFile = files.length == 1 && files[0].isFile();
304+
File tempFile = File.createTempFile("compress_", ".tmp", parentDir);
305+
if (singleFile) {
306+
try (
307+
FileInputStream fis = new FileInputStream(files[0]);
308+
FileOutputStream fos = new FileOutputStream(tempFile);
309+
BufferedOutputStream bos = new BufferedOutputStream(fos);
310+
GzipCompressorOutputStream gcos = new GzipCompressorOutputStream(bos)
311+
) {
312+
byte[] buffer = new byte[8192];
313+
int len;
314+
while ((len = fis.read(buffer)) != -1) {
315+
gcos.write(buffer, 0, len);
316+
}
313317
}
314-
while (!stack.isEmpty()) {
315-
File currentFile = stack.pop();
316-
String path = pathStack.pop();
317-
String entryName = path + currentFile.getName();
318-
if (currentFile.isDirectory()) {
319-
File[] dirFiles = currentFile.listFiles();
320-
if (dirFiles != null) {
321-
if (dirFiles.length == 0) {
318+
} else {
319+
try (
320+
FileOutputStream fos = new FileOutputStream(tempFile);
321+
BufferedOutputStream bos = new BufferedOutputStream(fos);
322+
GzipCompressorOutputStream gcos = new GzipCompressorOutputStream(bos);
323+
TarArchiveOutputStream taos = new TarArchiveOutputStream(gcos)
324+
) {
325+
taos.setLongFileMode(TarArchiveOutputStream.LONGFILE_GNU);
326+
Stack<File> fileStack = new Stack<>();
327+
Stack<String> pathStack = new Stack<>();
328+
for (File f : files) {
329+
if (f != null) {
330+
fileStack.push(f);
331+
pathStack.push("");
332+
}
333+
}
334+
while (!fileStack.isEmpty()) {
335+
File currentFile = fileStack.pop();
336+
String path = pathStack.pop();
337+
String entryName = path + currentFile.getName();
338+
if (currentFile.isDirectory()) {
339+
File[] children = currentFile.listFiles();
340+
if (children != null && children.length > 0) {
341+
for (File child : children) {
342+
fileStack.push(child);
343+
pathStack.push(entryName + "/");
344+
}
345+
} else {
322346
TarArchiveEntry entry = new TarArchiveEntry(entryName + "/");
323347
taos.putArchiveEntry(entry);
324348
taos.closeArchiveEntry();
325-
} else {
326-
for (File child : dirFiles) {
327-
stack.push(child);
328-
pathStack.push(entryName + "/");
329-
}
330349
}
331-
}
332-
} else {
333-
TarArchiveEntry entry = new TarArchiveEntry(currentFile, entryName);
334-
taos.putArchiveEntry(entry);
335-
try (FileInputStream fis = new FileInputStream(currentFile)) {
336-
byte[] buffer = new byte[1024];
337-
int len;
338-
while ((len = fis.read(buffer)) != -1) {
339-
taos.write(buffer, 0, len);
350+
} else {
351+
TarArchiveEntry entry = new TarArchiveEntry(currentFile, entryName);
352+
taos.putArchiveEntry(entry);
353+
try (FileInputStream fis = new FileInputStream(currentFile)) {
354+
byte[] buffer = new byte[8192];
355+
int len;
356+
while ((len = fis.read(buffer)) != -1) {
357+
taos.write(buffer, 0, len);
358+
}
340359
}
360+
taos.closeArchiveEntry();
341361
}
342-
taos.closeArchiveEntry();
343362
}
344363
}
345364
}
365+
if (!tempFile.exists()) {
366+
throw new IOException("Failed to create the archive");
367+
}
368+
String finalName = outputPath;
369+
if (singleFile) {
370+
if (!finalName.toLowerCase().endsWith(".gz")) {
371+
finalName += ".gz";
372+
}
373+
} else {
374+
if (finalName.toLowerCase().endsWith(".tar.gz")) {
375+
// do nothing
376+
} else if (finalName.toLowerCase().endsWith(".gz")) {
377+
finalName = finalName.substring(0, finalName.length() - 3) + ".tar.gz";
378+
} else {
379+
finalName += ".tar.gz";
380+
}
381+
}
382+
File finalFile = new File(finalName);
383+
if (finalFile.exists() && !finalFile.delete()) {
384+
throw new IOException("Failed to delete existing file with desired name");
385+
}
386+
if (!tempFile.renameTo(finalFile)) {
387+
throw new IOException("Failed to rename archive to desired name");
388+
}
346389
}
347390

348391
private static void compressToJar(File[] files, String outputPath) throws IOException {
@@ -481,54 +524,117 @@ private static void decompressTar(File archive, String directory) throws IOExcep
481524
}
482525

483526
private static void decompressGzip(File archive, String directory) throws IOException {
484-
byte[] buffer = new byte[8192];
485-
InputStream fi = Files.newInputStream(archive.toPath());
486-
InputStream bi = new BufferedInputStream(fi);
487-
InputStream gzi = new GzipCompressorInputStream(bi);
488-
String fileName = archive.getName();
489-
if (fileName.endsWith(".gz")) {
490-
fileName = fileName.substring(0, fileName.length() - 3);
491-
}
492-
File outputFile = new File(directory, fileName);
493-
File parent = outputFile.getParentFile();
494-
if (!parent.exists()) {
495-
parent.mkdirs();
496-
}
497-
OutputStream fo = Files.newOutputStream(outputFile.toPath());
498-
int len;
499-
while ((len = gzi.read(buffer)) != -1) {
500-
fo.write(buffer, 0, len);
501-
}
502-
fo.close();
503-
gzi.close();
504-
}
527+
if (!archive.exists() || !archive.isFile()) {
528+
throw new IllegalArgumentException("The archive file does not exist or is not a file.");
529+
}
530+
File targetDir = new File(directory);
531+
if (!targetDir.exists() || !targetDir.isDirectory()) {
532+
throw new IllegalArgumentException("The specified directory does not exist or is not a directory.");
533+
}
534+
File tempFile = File.createTempFile("decompressed_", ".tmp");
535+
try (
536+
FileInputStream fis = new FileInputStream(archive);
537+
GZIPInputStream gzipInputStream = new GZIPInputStream(fis);
538+
FileOutputStream fos = new FileOutputStream(tempFile)
539+
) {
540+
byte[] buffer = new byte[8192];
541+
int len;
542+
while ((len = gzipInputStream.read(buffer)) != -1) {
543+
fos.write(buffer, 0, len);
544+
}
545+
}
505546

506-
private static void decompressJar(File archive, String directory) throws IOException {
507-
byte[] buffer = new byte[1024];
508-
JarFile jarFile = new JarFile(archive);
509-
Enumeration<JarEntry> entries = jarFile.entries();
510-
while (entries.hasMoreElements()) {
511-
JarEntry entry = entries.nextElement();
512-
File newFile = new File(directory, entry.getName());
513-
if (entry.isDirectory()) {
514-
if (!newFile.isDirectory() && !newFile.mkdirs()) {
515-
throw new IOException("Failed to create directory " + newFile);
547+
boolean isTar = false;
548+
try (FileInputStream tempFis = new FileInputStream(tempFile);
549+
TarArchiveInputStream testTar = new TarArchiveInputStream(tempFis)) {
550+
TarArchiveEntry testEntry = testTar.getNextTarEntry();
551+
if (testEntry != null) {
552+
isTar = true;
553+
}
554+
} catch (IOException ignored) {}
555+
if (isTar) {
556+
try (FileInputStream tarFis = new FileInputStream(tempFile);
557+
TarArchiveInputStream tarInput = new TarArchiveInputStream(tarFis)) {
558+
559+
TarArchiveEntry entry;
560+
while ((entry = tarInput.getNextTarEntry()) != null) {
561+
File outFile = new File(targetDir, entry.getName());
562+
if (entry.isDirectory()) {
563+
if (!outFile.exists() && !outFile.mkdirs()) {
564+
throw new IOException("Failed to create directory: " + outFile);
565+
}
566+
} else {
567+
File parent = outFile.getParentFile();
568+
if (!parent.exists() && !parent.mkdirs()) {
569+
throw new IOException("Failed to create directory: " + parent);
570+
}
571+
try (FileOutputStream os = new FileOutputStream(outFile)) {
572+
byte[] buffer = new byte[8192];
573+
int count;
574+
while ((count = tarInput.read(buffer)) != -1) {
575+
os.write(buffer, 0, count);
576+
}
577+
}
578+
}
516579
}
517-
} else {
518-
File parent = newFile.getParentFile();
519-
if (!parent.isDirectory() && !parent.mkdirs()) {
520-
throw new IOException("Failed to create directory " + parent);
580+
}
581+
} else {
582+
String name = archive.getName();
583+
if (name.toLowerCase().endsWith(".gz")) {
584+
name = name.substring(0, name.length() - 3);
585+
}
586+
File singleOutFile = new File(targetDir, name);
587+
if (!tempFile.renameTo(singleOutFile)) {
588+
try (
589+
FileInputStream in = new FileInputStream(tempFile);
590+
FileOutputStream out = new FileOutputStream(singleOutFile)
591+
) {
592+
byte[] buffer = new byte[8192];
593+
int len;
594+
while ((len = in.read(buffer)) != -1) {
595+
out.write(buffer, 0, len);
596+
}
521597
}
522-
InputStream is = jarFile.getInputStream(entry);
523-
FileOutputStream fos = new FileOutputStream(newFile);
524-
int len;
525-
while ((len = is.read(buffer)) > 0) {
526-
fos.write(buffer, 0, len);
598+
}
599+
}
600+
if (!tempFile.delete()) {
601+
tempFile.deleteOnExit();
602+
}
603+
}
604+
605+
private static void decompressJar(File archive, String directory) throws IOException {
606+
if (!archive.exists() || !archive.isFile()) {
607+
throw new IOException("Invalid archive file.");
608+
}
609+
File targetDir = new File(directory);
610+
if (!targetDir.exists()) {
611+
if (!targetDir.mkdirs()) {
612+
throw new IOException("Failed to create target directory.");
613+
}
614+
}
615+
try (JarInputStream jarInputStream = new JarInputStream(Files.newInputStream(archive.toPath()))) {
616+
JarEntry entry;
617+
while ((entry = jarInputStream.getNextJarEntry()) != null) {
618+
File outputFile = new File(targetDir, entry.getName());
619+
if (entry.isDirectory()) {
620+
if (!outputFile.exists() && !outputFile.mkdirs()) {
621+
throw new IOException("Failed to create directory: " + outputFile.getAbsolutePath());
622+
}
623+
} else {
624+
File parent = outputFile.getParentFile();
625+
if (!parent.exists() && !parent.mkdirs()) {
626+
throw new IOException("Failed to create parent directory: " + parent.getAbsolutePath());
627+
}
628+
try (FileOutputStream fos = new FileOutputStream(outputFile)) {
629+
byte[] buffer = new byte[1024];
630+
int bytesRead;
631+
while ((bytesRead = jarInputStream.read(buffer)) != -1) {
632+
fos.write(buffer, 0, bytesRead);
633+
}
634+
}
527635
}
528-
fos.close();
529-
is.close();
636+
jarInputStream.closeEntry();
530637
}
531638
}
532-
jarFile.close();
533639
}
534640
}

0 commit comments

Comments
 (0)