diff --git a/self-extracting-jar-creator/.classpath b/self-extracting-jar-creator/.classpath new file mode 100644 index 000000000..0ca1374d8 --- /dev/null +++ b/self-extracting-jar-creator/.classpath @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/self-extracting-jar-creator/.project b/self-extracting-jar-creator/.project new file mode 100644 index 000000000..a7412000c --- /dev/null +++ b/self-extracting-jar-creator/.project @@ -0,0 +1,23 @@ + + + self-extracting-jar-creator + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + + diff --git a/self-extracting-jar-creator/.settings/org.eclipse.jdt.apt.core.prefs b/self-extracting-jar-creator/.settings/org.eclipse.jdt.apt.core.prefs new file mode 100644 index 000000000..d4313d4b2 --- /dev/null +++ b/self-extracting-jar-creator/.settings/org.eclipse.jdt.apt.core.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.apt.aptEnabled=false diff --git a/self-extracting-jar-creator/.settings/org.eclipse.jdt.core.prefs b/self-extracting-jar-creator/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..1b6e1ef22 --- /dev/null +++ b/self-extracting-jar-creator/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,9 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore +org.eclipse.jdt.core.compiler.processAnnotations=disabled +org.eclipse.jdt.core.compiler.release=disabled +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/self-extracting-jar-creator/.settings/org.eclipse.m2e.core.prefs b/self-extracting-jar-creator/.settings/org.eclipse.m2e.core.prefs new file mode 100644 index 000000000..f897a7f1c --- /dev/null +++ b/self-extracting-jar-creator/.settings/org.eclipse.m2e.core.prefs @@ -0,0 +1,4 @@ +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 diff --git a/self-extracting-jar-creator/pom.xml b/self-extracting-jar-creator/pom.xml new file mode 100644 index 000000000..44b5240d0 --- /dev/null +++ b/self-extracting-jar-creator/pom.xml @@ -0,0 +1,29 @@ + + 4.0.0 + com.github.kdvolder + self-extracing-jar-creator + 0.0.1-SNAPSHOT + + 1.8 + 1.8 + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + true + SelfExtractor + + + + + + + \ No newline at end of file diff --git a/self-extracting-jar-creator/src/main/java/SelfExtractor.java b/self-extracting-jar-creator/src/main/java/SelfExtractor.java new file mode 100644 index 000000000..1250caeaa --- /dev/null +++ b/self-extracting-jar-creator/src/main/java/SelfExtractor.java @@ -0,0 +1,132 @@ +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URL; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; +import java.util.zip.ZipOutputStream; + + +/** + * SelfExtractor + */ +public class SelfExtractor { + + private static final String CONTENTS_ZIP_RSRC = "/contents.zip"; + private static final int BUF_SIZE = 1024*8; + + byte[] buffer = new byte[BUF_SIZE]; + + public static void main(String[] args) throws Exception { + new SelfExtractor().run(args); + } + + private void run(String[] args) throws Exception { + if (args.length==0) { + unpack(); + } else if (args.length==1) { + repack(args[0]); + } else { + throw new IllegalArgumentException("Expecting one argument pointing to zipfile to re-wrap"); + } + } + + private void repack(String _contentsZip) throws Exception { + File contentsZip = new File(_contentsZip); + System.out.println("Repackaging "+contentsZip); + if (!contentsZip.isFile()) { + throw new IllegalArgumentException("File not found:" + contentsZip); + } + String repackagedPath = contentsZip.toString(); + if (repackagedPath.endsWith(".zip")) { + repackagedPath = repackagedPath.substring(0, repackagedPath.length()-4); + } + repackagedPath = repackagedPath + ".self-extracting.jar"; + System.out.println(" as "+repackagedPath); + + File wrapperJar = getMyJar(); + System.out.println("wrapperJar = "+wrapperJar); + try (ZipInputStream zipIn = new ZipInputStream(new FileInputStream(wrapperJar))) { + try (ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(new File(repackagedPath)))) { + ZipEntry entry; + while ((entry = zipIn.getNextEntry())!=null) { + System.out.println("Adding: "+entry.getName()); + if (entry.getName().equals("contents.zip")) { + //skip. We need to write the wrapped zip contents here. + } else { + zipOut.putNextEntry(new ZipEntry(entry)); + if (entry.getName().endsWith("/")) { + //skip directory has no bytes as contents + } else { + copy(zipIn, zipOut); + } + } + } //end while + entry = new ZipEntry("contents.zip"); + zipOut.putNextEntry(entry); + System.out.println("Adding: "+entry.getName()); + try (FileInputStream contentsZipIn = new FileInputStream(contentsZip)) { + copy(contentsZipIn, zipOut); + } + } //end: zipOut + }//end: zipIn + } + + private void copy(InputStream in, OutputStream out) throws IOException { + int bytesRead; + while ((bytesRead = in.read(buffer)) > 0) { + out.write(buffer, 0, bytesRead); + } + } + + private File getMyJar() { + Class myklass = this.getClass(); + String resourceName = this.getClass().getName() + ".class"; + URL resource = myklass.getResource(resourceName); + String myResourceUrl = resource.toString(); + //Example: jar:file:/home/.../self-extracing-jar-creator-0.0.1-SNAPSHOT.jar!/SelfExtractor.class + if (!myResourceUrl.startsWith("jar:file:")) { + File devJar = new File("target/self-extracing-jar-creator-0.0.1-SNAPSHOT.jar"); + if (devJar.isFile()) { + return devJar; + } + throw new IllegalStateException("To create self extracting jar, you must run this code from a jar"); + } + return new File(myResourceUrl.substring("jar:file:".length(), myResourceUrl.indexOf('!'))); + } + + private ZipInputStream openContentsZip() { + InputStream zip = this.getClass().getResourceAsStream(CONTENTS_ZIP_RSRC); + if (zip==null) { + throw new IllegalArgumentException("Couldn't find embedded '"+CONTENTS_ZIP_RSRC+""); + } + return new ZipInputStream(zip); + } + + public void unpack() throws Exception { + File destDir = new File(System.getProperty("user.dir")); + try (ZipInputStream zip = openContentsZip()) { + ZipEntry entry; + while ((entry = zip.getNextEntry())!=null) { + String name = entry.getName(); + System.out.println(name); + File outfile = new File(destDir, name); + if (outfile.exists()) { + throw new IllegalArgumentException("File already exists: "+outfile); + } + if (name.endsWith("/")) { + outfile.mkdirs(); + } else { + //file + outfile.getParentFile().mkdirs(); + try (FileOutputStream out = new FileOutputStream(outfile)) { + copy(zip, out); + } + } + } + } + } +} \ No newline at end of file diff --git a/self-extracting-jar-creator/src/main/resources/META-INF/MANIFEST.MF b/self-extracting-jar-creator/src/main/resources/META-INF/MANIFEST.MF new file mode 100644 index 000000000..47237f2d7 --- /dev/null +++ b/self-extracting-jar-creator/src/main/resources/META-INF/MANIFEST.MF @@ -0,0 +1 @@ +Main-Class: SelfExtractor \ No newline at end of file