Skip to content

Commit

Permalink
Added sorting
Browse files Browse the repository at this point in the history
- .exes are considered zip archives, will be analyzed
- added optional subdirectory distinction
- added readme
  • Loading branch information
Moresteck committed Jul 3, 2024
1 parent 425b5ad commit 9f927ee
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 13 deletions.
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# jar-analyzer
Usage:

java -Dtz=<tz of jar contents> -jar jar-analyzer.jar /path/to/dir/or/jar/to/analyze

`-Dtz=<tz>` is optional, and if not used, the program will assume the jar contents are UTC.

### TODO
- add printing in tree view as an option
72 changes: 72 additions & 0 deletions src/main/java/uk/betacraft/jaranalyzer/FilenameComparator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package uk.betacraft.jaranalyzer;

import java.io.File;
import java.math.BigInteger;
import java.util.Comparator;
import java.util.regex.Pattern;
/**
* Taken from https://stackoverflow.com/a/48946762
*/
public final class FilenameComparator implements Comparator<File> {
private static final Pattern NUMBERS =
Pattern.compile("(?<=\\D)(?=\\d)|(?<=\\d)(?=\\D)");

@Override public final int compare(File o1, File o2) {
// Optional "NULLS LAST" semantics:
if (o1 == null || o2 == null)
return o1 == null ? o2 == null ? 0 : -1 : 1;

String name1 = o1.getName();
String name2 = o2.getName();

// Fix Notch's inconsistent versioning breaking order... TODO: find a better way of doing this if possible
if ((name1.equals("b1.0.jar") && name2.contains("b1.0_01.jar"))
|| (name1.equals("b1.7.jar") && name2.contains("b1.7_01.jar")))
return -1;
else if ((name2.equals("b1.0.jar") && name1.contains("b1.0_01.jar"))
|| (name2.equals("b1.7.jar") && name1.contains("b1.7_01.jar")))
return 1;
else if ((name1.equals("b1.0_01.jar") && name2.contains("b1.0.2.jar"))
|| (name1.equals("b1.7_01.jar") && name2.contains("b1.7.2.jar"))
|| (name1.equals("b1.7_01.jar") && name2.contains("b1.7.3.jar")))
return -1;
else if ((name2.equals("b1.0_01.jar") && name1.contains("b1.0.2.jar"))
|| (name2.equals("b1.7_01.jar") && name1.contains("b1.7.2.jar"))
|| (name2.equals("b1.7_01.jar") && name1.contains("b1.7.3.jar")))
return 1;

// Splitting both input strings by the above patterns
String[] split1 = NUMBERS.split(name1);
String[] split2 = NUMBERS.split(name2);

for (int i = 0; i < Math.min(split1.length, split2.length); i++) {
char c1 = split1[i].charAt(0);
char c2 = split2[i].charAt(0);
int cmp = 0;

// If both segments start with a digit, sort them numerically using
// BigInteger to stay safe
if (c1 >= '0' && c1 <= '9' && c2 >= '0' && c2 <= '9')
cmp = new BigInteger(split1[i]).compareTo(new BigInteger(split2[i]));

// Place 1.x.jar before 1.x.y.jar
if (c1 == '.' && (split2[i].equals(".jar") || split2[i].equals(".exe") || split2[i].equals(".zip")))
cmp = 1;
else if (c2 == '.' && (split1[i].equals(".jar") || split1[i].equals(".exe") || split1[i].equals(".zip")))
cmp = -1;

// If we haven't sorted numerically before, or if numeric sorting yielded
// equality (e.g 007 and 7) then sort lexicographically
else if (cmp == 0)
cmp = split1[i].compareTo(split2[i]);

// Abort once some prefix has unequal ordering
if (cmp != 0)
return cmp;
}

// If we reach this, then both strings have equally ordered prefixes, but
// maybe one string is longer than the other (i.e. has more segments)
return split1.length - split2.length;
}
}
33 changes: 20 additions & 13 deletions src/main/java/uk/betacraft/jaranalyzer/JarAnalyzer.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.TimeZone;
import java.util.jar.JarEntry;
Expand All @@ -16,6 +17,7 @@
public class JarAnalyzer {
// assuming UTC by default
private static final String tzID = System.getProperty("tz", "UTC");
private static final boolean printSubdirsDistinctly = Boolean.parseBoolean(System.getProperty("subdirs", "false"));
private static TimeZone tz = TimeZone.getTimeZone(tzID);

public static void main(String[] args) {
Expand All @@ -31,27 +33,32 @@ public static void main(String[] args) {
}
}

public static boolean isJarZip(File f) {
return !f.isDirectory() && (f.getName().toLowerCase().endsWith(".jar") || f.getName().toLowerCase().endsWith(".zip"));
public static boolean isZipArchive(File f) {
String fname = f.getName().toLowerCase();

// accept jar, zip, and additionally exe (servers before 1.9 have EXE counterparts)
return !f.isDirectory() && (fname.endsWith(".jar") || fname.endsWith(".zip") || fname.endsWith(".exe"));
}

public static long depth = -1;

public static void analyze(File folder) {
if (isJarZip(folder)) {
if (isZipArchive(folder)) {
printInfoJar(folder);
} else if (folder.isDirectory()) {
System.out.println(" ========= FOLDER: " + folder.getName());

if (printSubdirsDistinctly)
System.out.println(" ========= FOLDER: " + folder.getName());

File[] files = folder.listFiles();

for (File file : files) {
if (file.isDirectory()) {
analyze(file);
} else {
printInfoJar(file);
}
}
Arrays.sort(files, new FilenameComparator());

for (File file : files)
analyze(file);

System.out.println(" ========= END: " + folder.getName());
if (printSubdirsDistinctly)
System.out.println(" ========= END: " + folder.getName());
}
}

Expand Down Expand Up @@ -93,7 +100,7 @@ public static void printInfoJar(File f) {
System.out.printf("%-60.60s %-60.60s%n", relativePath, formattedDateTime);

} catch (ZipException zipException) {
// happens on 1.9+ jars - avoid it as there's nothing that can be done
// disregard non-ZIP or corrupted files
if ("zip END header not found".equals(zipException.getMessage()))
return;

Expand Down

0 comments on commit 9f927ee

Please sign in to comment.