1 |
package net.oni2.aeinstaller.backend.unpack; |
2 |
|
3 |
import java.io.File; |
4 |
import java.io.FileOutputStream; |
5 |
import java.io.IOException; |
6 |
import java.io.InputStream; |
7 |
import java.util.Enumeration; |
8 |
import java.util.zip.ZipEntry; |
9 |
import java.util.zip.ZipException; |
10 |
import java.util.zip.ZipFile; |
11 |
|
12 |
import org.apache.commons.io.FileUtils; |
13 |
|
14 |
/** |
15 |
* @author Christian Illy |
16 |
*/ |
17 |
public class Unpacker implements Runnable { |
18 |
/** |
19 |
* @author Christian Illy |
20 |
*/ |
21 |
public enum EState { |
22 |
/** |
23 |
* Unpacker initialized but not started |
24 |
*/ |
25 |
INIT, |
26 |
/** |
27 |
* Unpack running |
28 |
*/ |
29 |
RUNNING, |
30 |
/** |
31 |
* Unpack interrupted |
32 |
*/ |
33 |
INTERRUPTED, |
34 |
/** |
35 |
* Unpack finished successfully |
36 |
*/ |
37 |
FINISHED, |
38 |
}; |
39 |
|
40 |
private UnpackListener listener; |
41 |
|
42 |
private File zip; |
43 |
private File target; |
44 |
|
45 |
private Thread t = null; |
46 |
|
47 |
private EState state = EState.INIT; |
48 |
|
49 |
/** |
50 |
* Initialize a new AE package unpacker |
51 |
* |
52 |
* @param zipFile |
53 |
* AE zip package |
54 |
* @param targetFolder |
55 |
* Target folder |
56 |
* @param listener |
57 |
* Listener for progress updates |
58 |
*/ |
59 |
public Unpacker(File zipFile, File targetFolder, UnpackListener listener) { |
60 |
this.listener = listener; |
61 |
zip = zipFile; |
62 |
target = targetFolder; |
63 |
} |
64 |
|
65 |
/** |
66 |
* Start the unpack process |
67 |
*/ |
68 |
public synchronized void start() { |
69 |
if (t == null) { |
70 |
t = new Thread(this); |
71 |
t.start(); |
72 |
state = EState.RUNNING; |
73 |
updateStatus(); |
74 |
} |
75 |
} |
76 |
|
77 |
/** |
78 |
* Stop (abort) the process |
79 |
*/ |
80 |
public synchronized void stop() { |
81 |
if (state != EState.FINISHED) { |
82 |
state = EState.INTERRUPTED; |
83 |
if (t != null) { |
84 |
try { |
85 |
t.join(); |
86 |
} catch (InterruptedException e) { |
87 |
// TODO Auto-generated catch block |
88 |
e.printStackTrace(); |
89 |
} |
90 |
t = null; |
91 |
} |
92 |
updateStatus(); |
93 |
if (state != EState.FINISHED) { |
94 |
if (target.exists()) { |
95 |
try { |
96 |
FileUtils.deleteDirectory(target); |
97 |
} catch (IOException e) { |
98 |
// TODO Auto-generated catch block |
99 |
e.printStackTrace(); |
100 |
} |
101 |
} |
102 |
} |
103 |
} |
104 |
} |
105 |
|
106 |
private synchronized void updateStatus() { |
107 |
listener.statusUpdate(this, state); |
108 |
} |
109 |
|
110 |
@Override |
111 |
public void run() { |
112 |
try { |
113 |
switch (state) { |
114 |
case INTERRUPTED: |
115 |
return; |
116 |
case RUNNING: |
117 |
try { |
118 |
int pathStart = 0; |
119 |
|
120 |
ZipFile zf = new ZipFile(zip); |
121 |
target.mkdirs(); |
122 |
for (Enumeration<? extends ZipEntry> e = zf.entries(); e |
123 |
.hasMoreElements();) { |
124 |
ZipEntry ze = e.nextElement(); |
125 |
if (ze.getName().toLowerCase() |
126 |
.endsWith("mod_info.cfg")) { |
127 |
pathStart = ze.getName().toLowerCase() |
128 |
.indexOf("mod_info.cfg"); |
129 |
} |
130 |
} |
131 |
|
132 |
for (Enumeration<? extends ZipEntry> e = zf.entries(); e |
133 |
.hasMoreElements();) { |
134 |
if (state == EState.INTERRUPTED) |
135 |
return; |
136 |
ZipEntry ze = e.nextElement(); |
137 |
if (!ze.isDirectory()) { |
138 |
File targetFile = new File(target, ze.getName() |
139 |
.substring(pathStart)); |
140 |
targetFile.getParentFile().mkdirs(); |
141 |
|
142 |
InputStream in = zf.getInputStream(ze); |
143 |
|
144 |
int read = 0; |
145 |
byte[] data = new byte[1024]; |
146 |
FileOutputStream fileOut = new FileOutputStream( |
147 |
targetFile); |
148 |
while ((read = in.read(data, 0, 1024)) != -1) { |
149 |
fileOut.write(data, 0, read); |
150 |
} |
151 |
fileOut.close(); |
152 |
} |
153 |
} |
154 |
} catch (ZipException e) { |
155 |
// TODO Auto-generated catch block |
156 |
e.printStackTrace(); |
157 |
} catch (IOException e) { |
158 |
// TODO Auto-generated catch block |
159 |
e.printStackTrace(); |
160 |
} |
161 |
break; |
162 |
default: |
163 |
break; |
164 |
} |
165 |
} finally { |
166 |
} |
167 |
|
168 |
state = EState.FINISHED; |
169 |
updateStatus(); |
170 |
} |
171 |
} |