added initial buggy version of executable jar plugin

This commit is contained in:
2021-08-14 09:25:47 +02:00
parent 305d903c17
commit da358d3522
13 changed files with 979 additions and 0 deletions

View File

@@ -0,0 +1,3 @@
plugins {
id 'java-library'
}

View File

@@ -0,0 +1,117 @@
package net.woggioni.executable.jar;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.util.AbstractMap;
import java.util.Map;
import java.util.Optional;
import java.util.function.Supplier;
import java.util.zip.CRC32;
import java.util.zip.ZipEntry;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.SneakyThrows;
import java.io.IOException;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class Common {
final private static char[] hexArray = "0123456789ABCDEF".toCharArray();
public static String bytesToHex(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
for (int j = 0; j < bytes.length; j++) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = hexArray[v >>> 4];
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
}
return new String(hexChars);
}
@SneakyThrows
public static byte[] computeSHA256Digest(Supplier<InputStream> streamSupplier) {
byte[] buffer = new byte[Constants.BUFFER_SIZE];
MessageDigest md = MessageDigest.getInstance("SHA-256");
return computeDigest(streamSupplier, md, buffer);
}
@SneakyThrows
public static byte[] computeDigest(Supplier<InputStream> streamSupplier, MessageDigest md, byte[] buffer) {
try(InputStream stream = new DigestInputStream(streamSupplier.get(), md)) {
while(stream.read(buffer) >= 0) {}
}
return md.digest();
}
@SneakyThrows
public static void computeSizeAndCrc32(
ZipEntry zipEntry,
InputStream inputStream,
byte[] buffer) {
CRC32 crc32 = new CRC32();
long sz = 0L;
while (true) {
int read = inputStream.read(buffer);
if (read < 0) break;
sz += read;
crc32.update(buffer, 0, read);
}
zipEntry.setSize(sz);
zipEntry.setCompressedSize(sz);
zipEntry.setCrc(crc32.getValue());
}
@SneakyThrows
public static void write2Stream(InputStream inputStream, OutputStream os,
byte[] buffer) {
while (true) {
int read = inputStream.read(buffer);
if (read < 0) break;
os.write(buffer, 0, read);
}
}
public static void write2Stream(InputStream inputStream, OutputStream os) {
write2Stream(inputStream, os, new byte[Constants.BUFFER_SIZE]);
}
public static Optional<Map.Entry<String, String>> splitExtension(String fileName) {
int index = fileName.lastIndexOf('.');
if (index == -1) {
return Optional.empty();
} else {
return Optional.of(
new AbstractMap.SimpleEntry<>(fileName.substring(0, index), fileName.substring(index)));
}
}
/**
* Helper method to create an {@link InputStream} from a file without having to catch the possibly
* thrown {@link IOException}, use {@link FileInputStream#FileInputStream(File)} if you need to catch it.
* @param file the {@link File} to be opened
* @return an open {@link InputStream} instance reading from the file
*/
@SneakyThrows
public static InputStream read(File file, boolean buffered) {
InputStream result = new FileInputStream(file);
return buffered ? new BufferedInputStream(result) : result;
}
/**
* Helper method to create an {@link OutputStream} from a file without having to catch the possibly
* thrown {@link IOException}, use {@link FileOutputStream#FileOutputStream(File)} if you need to catch it.
* @param file the {@link File} to be opened
* @return an open {@link OutputStream} instance writing to the file
*/
@SneakyThrows
public static OutputStream write(File file, boolean buffered) {
OutputStream result = new FileOutputStream(file);
return buffered ? new BufferedOutputStream(result) : result;
}
}

View File

@@ -0,0 +1,29 @@
package net.woggioni.executable.jar;
import java.util.Calendar;
import java.util.GregorianCalendar;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class Constants {
public static final String LIBRARIES_FOLDER = "LIB-INF";
public static final String METADATA_FOLDER = "META-INF";
public static final int BUFFER_SIZE = 0x10000;
public static final String DEFAULT_LAUNCHER = "net.woggioni.executable.jar.Launcher";
public static class ManifestAttributes {
public static final String MAIN_MODULE = "Executable-Jar-Main-Module";
public static final String MAIN_CLASS = "Executable-Jar-Main-Class";
public static final String ENTRY_HASH = "SHA-256-Digest";
}
/**
* This value is used as a default file timestamp for all the zip entries when
* <a href="https://docs.gradle.org/current/javadoc/org/gradle/api/tasks/bundling/AbstractArchiveTask.html#isPreserveFileTimestamps--">AbstractArchiveTask.isPreserveFileTimestamps</a>
* is true; its value is taken from Gradle's <a href="https://github.com/gradle/gradle/blob/master/subprojects/core/src/main/java/org/gradle/api/internal/file/archive/ZipCopyAction.java#L42-L57">ZipCopyAction<a/>
* for the reasons outlined there.
*/
public static final long ZIP_ENTRIES_DEFAULT_TIMESTAMP =
new GregorianCalendar(1980, Calendar.FEBRUARY, 1, 0, 0, 0).getTimeInMillis();
}