package net.oni2.aeinstaller.backend.packages.unpack; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.Enumeration; import java.util.zip.ZipException; import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; import org.apache.commons.compress.archivers.zip.ZipFile; import org.apache.commons.io.FileUtils; /** * @author Christian Illy */ public class Unpacker implements Runnable { /** * @author Christian Illy */ public enum EState { /** * Unpacker initialized but not started */ INIT, /** * Unpack running */ RUNNING, /** * Unpack interrupted */ INTERRUPTED, /** * Unpack finished successfully */ FINISHED, }; private UnpackListener listener; private File zip; private File target; private Thread t = null; private EState state = EState.INIT; /** * Initialize a new AE package unpacker * * @param zipFile * AE zip package * @param targetFolder * Target folder * @param listener * Listener for progress updates */ public Unpacker(File zipFile, File targetFolder, UnpackListener listener) { this.listener = listener; zip = zipFile; target = targetFolder; } /** * Start the unpack process */ public synchronized void start() { if (t == null) { state = EState.RUNNING; updateStatus(); t = new Thread(this); t.start(); } } /** * Stop (abort) the process */ public synchronized void stop() { if (state != EState.FINISHED) { state = EState.INTERRUPTED; if (t != null) { try { t.join(); } catch (InterruptedException e) { e.printStackTrace(); } t = null; } updateStatus(); if (state != EState.FINISHED) { if (target.exists()) { try { FileUtils.deleteDirectory(target); } catch (IOException e) { e.printStackTrace(); } } } } } private synchronized void updateStatus() { listener.statusUpdate(this, state); } @Override public void run() { try { switch (state) { case INTERRUPTED: return; case RUNNING: ZipFile zf = null; try { int pathStart = 0; String pathStartName = ""; zf = new ZipFile(zip); if (target.exists()) FileUtils.deleteDirectory(target); target.mkdirs(); for (Enumeration e = zf .getEntries(); e.hasMoreElements();) { ZipArchiveEntry ze = e.nextElement(); if (ze.getName().toLowerCase() .endsWith("/mod_info.cfg") || ze.getName().toLowerCase() .equals("mod_info.cfg")) { pathStart = ze.getName().toLowerCase() .indexOf("mod_info.cfg"); pathStartName = ze.getName().substring(0, pathStart); } } for (Enumeration e = zf .getEntries(); e.hasMoreElements();) { if (state == EState.INTERRUPTED) return; ZipArchiveEntry ze = e.nextElement(); if (!ze.isDirectory()) { if (ze.getName().startsWith(pathStartName)) { if (!(ze.getName().endsWith("aei.cfg") || ze .getName().endsWith(".DS_Store"))) { File targetFile = new File(target, ze .getName().substring(pathStart)); File parent = targetFile .getParentFile(); parent.mkdirs(); InputStream in = zf.getInputStream(ze); int read = 0; byte[] data = new byte[1024]; FileOutputStream fileOut = new FileOutputStream( targetFile); while ((read = in.read(data, 0, 1024)) != -1) { fileOut.write(data, 0, read); } fileOut.close(); if ((ze.getUnixMode() & 0111) != 0) targetFile.setExecutable(true); } } } } } catch (ZipException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { try { if (zf != null) zf.close(); } catch (IOException e) { e.printStackTrace(); } } break; default: break; } } finally { } state = EState.FINISHED; updateStatus(); } }