package javacodebook.io.enablejar;

import java.io.*;
import java.util.*;
import java.util.jar.*;

public class JarManager {

    private File jarFileName;
    private int numOfEntries;
    private Manifest manifest;

    public JarManager(File f)
    throws IOException {
        jarFileName = f;
        //zuerst wird ermittelt, ob es bereits eine Manifest-Datei gibt
        FileInputStream in = new FileInputStream(jarFileName);
        JarInputStream jarIn = new JarInputStream(in);
        manifest = jarIn.getManifest();
        //ist keine Manifest-Datei vorhanden, wird ein neues Manifest erzeugt
        if (manifest == null)
            manifest = new Manifest();
        jarIn.close();
    }

    public String getMainClass() {
        Attributes a = manifest.getMainAttributes();
        return a.getValue("Main-Class");
    }

    public void setMainClass(String className)
    throws IOException {
        //die Jar-Datei öffnen
        FileInputStream in = new FileInputStream(jarFileName);
        JarInputStream jarIn = new JarInputStream(in);

        //den Namen der Main-Klasse im Manifest setzen
        Attributes a = manifest.getMainAttributes();
        a.putValue("Main-Class", className);

        //das neue Jar-Archiv erhält den Dateinamen + "_exe"
        String fileName = jarFileName.getAbsolutePath();
        fileName = fileName.substring(0, fileName.lastIndexOf(".")) + "_exe.jar";

        //Die Ausgabe erfolgt über einen JarOutputStream, über den
        //in das neue Jar-Archiv geschrieben wird.
        FileOutputStream out = new FileOutputStream(fileName);
        //Das Manifest wird direkt an den Konstruktor vom JarOutputStream
        //übergeben
        JarOutputStream jarOut = new JarOutputStream(out, manifest);

        //Dateien aus der alten Jar-Datei müssen in die neue kopiert werden
        //das erfolgt analog zum kopieren von Dateien. Die Klasse JarEntry
        //repräsentiert Dateien im Jar-Archiv.
        JarEntry entry;
        byte[] buf = new byte[4096];
        while ((entry = jarIn.getNextJarEntry()) != null) {
            //Die Manifest-Datei aus dem alten Jar wird ausgelassen
            if ("META-INF/MANIFEST.MF".equals(entry.getName()))
                continue;

            //Es wird ein Eintrag in das neue Jar-Archiv hinzugefügt
            jarOut.putNextEntry(entry);

            //Die Datei aus dem alten Archiv wird blockweise gelesen und in
            //das neue Archiv geschrieben.
            int bytes;
            while ((bytes = jarIn.read(buf)) != -1)
                jarOut.write(buf, 0, bytes);
            jarOut.closeEntry();
        }
        jarOut.flush();
        jarOut.close();
    }
}
