5

I know how to create a executable .jar file. There are many examples of that on the internet. What I am wondering, is if anyone knows of a way that a executable .jar file can auto extract out parts of itself to the "running directory"?

So, instead of:

jar xf TicTacToe.jar TicTacToe.class TicTacToe.properties
java -jar TicTacToe.jar

I would like to only do this:

java -jar TicTacToe.jar TicTacToe.class TicTacToe.properties

This basically makes a self extracting installer. Is this possible, if so, what code is necessary to do this?

NOTE: ultimately, once it works, I will wrap it into launch4j in order to to emulate a .exe self extracting installer.

djangofan
  • 28,471
  • 61
  • 196
  • 289
  • Check this: http://stackoverflow.com/questions/542127/extracting-files-from-a-jar-more-efficently – hbhakhra Aug 23 '11 at 23:37
  • Are you asking how to obtain the argument `TicTacToe.properties` or how to get a reference to the executing jar file? – Kirk Woll Aug 23 '11 at 23:37
  • I am asking how to get a reference to the "self.jar" and then extract a file from "self.jar" . – djangofan Aug 24 '11 at 16:05

2 Answers2

8

You can write a main method which does check if the files are present, and if not extract them (by copying the resource stream to a file). If you only need a fixed set of files (like in your example), this can be easyly done with this:

public class ExtractAndStart
{
    public static void main(String[] args)
    {
        extractFile("TicTacToe.properties");
        Application.main(args);
    }

    private static void extractFile(String name) throws IOException
    {
        File target = new File(name);
        if (target.exists())
            return;

        FileOutputStream out = new FileOutputStream(target);
        ClassLoader cl = ExtractAndStart.class.getClassLoader();
        InputStream in = cl.getResourceAsStream(name);

        byte[] buf = new byte[8*1024];
        int len;
        while((len = in.read(buf)) != -1)
        {
            out.write(buf,0,len);
        }
        out.close();
            in.close();
    }
}

There are also creators for self-extracting archives but they usually extract all and then start some inner component.

Here is a short article how it works:

http://www.javaworld.com/javatips/jw-javatip120.html

And it recommends to use ZipAnywhere which seems outdated. But Ant Installer might be a good alternative.

eckes
  • 10,103
  • 1
  • 59
  • 71
2

You can determine which jar a class was loaded from using the following pattern:

SomeClass.class.getProtectionDomain().getCodeSource().getLocation().getFile()

From that, you should be able to use ZipInputStream to iterate over the contents of the jar and extract them to the directory you want to install to.