1
2
3
4
5
6 package earutils.expander;
7
8 import java.io.*;
9 import java.util.*;
10 import java.util.zip.*;
11
12 /***
13 *
14 * @author Sean C. Sullivan
15 *
16 */
17 public class Expander
18 {
19 protected Set expansionExtensions = new java.util.HashSet();
20 protected String outputPath;
21 protected Set listeners = new java.util.HashSet();
22
23 public Expander()
24 {
25 }
26
27 public void addExpanderListener(ExpanderListener l)
28 {
29 listeners.add(l);
30 }
31
32 public void removeExpanderListener(ExpanderListener l)
33 {
34 if (listeners.contains(l))
35 {
36 listeners.remove(l);
37 }
38 }
39
40 protected void fireExpansionStartedEvent(String archiveName)
41 {
42 Iterator iter = listeners.iterator();
43 while (iter.hasNext())
44 {
45 ExpanderListener l = (ExpanderListener) iter.next();
46 l.expansionStarted(archiveName);
47 }
48 }
49
50 protected void fireExpansionFinishedEvent(String archiveName, boolean success, long duration)
51 {
52 Iterator iter = listeners.iterator();
53 while (iter.hasNext())
54 {
55 ExpanderListener l = (ExpanderListener) iter.next();
56 l.expansionFinished(archiveName, success, duration);
57 }
58 }
59
60 protected void fireEntrySkippedEvent(String entryName)
61 {
62 Iterator iter = listeners.iterator();
63 while (iter.hasNext())
64 {
65 ExpanderListener l = (ExpanderListener) iter.next();
66 l.entrySkipped(entryName);
67 }
68 }
69
70 protected void fireFileCreatedEvent(String file)
71 {
72 Iterator iter = listeners.iterator();
73 while (iter.hasNext())
74 {
75 ExpanderListener l = (ExpanderListener) iter.next();
76 l.fileCreated(file);
77 }
78
79 }
80
81 public void setExpansionExtensions(Set s)
82 {
83 this.expansionExtensions = s;
84 }
85
86 public Set getExpansionExtensions()
87 {
88 return this.expansionExtensions;
89 }
90
91 public void setOutputPath(String path)
92 {
93 outputPath = path;
94 }
95
96 public String getOutputPath()
97 {
98 return outputPath;
99 }
100
101 static private void mkdirs(String path)
102 {
103 java.io.File f = new File(path);
104 f.mkdirs();
105 }
106
107 public void expand(String earFilename) throws java.io.IOException
108 {
109 if (earFilename == null)
110 {
111 throw new NullPointerException("earFilename parameter");
112 }
113
114 File f = new File(earFilename);
115
116 validateEARFile(f);
117
118 InputStream in = null;
119
120 in = new FileInputStream(f);
121
122 try
123 {
124 expand(in, f.getName());
125 }
126 finally
127 {
128 if (in != null)
129 {
130 in.close();
131 }
132 }
133 }
134
135 protected void validateOutputPath()
136 {
137 if ( (getOutputPath() == null)
138 || (getOutputPath().length() == 0) )
139 {
140 throw new RuntimeException("Output path is not set");
141 }
142
143 File outputDir = new File(getOutputPath());
144
145 if ( ! outputDir.exists())
146 {
147 throw new RuntimeException("Directory does not exist: "
148 + outputDir.getName());
149 }
150 if ( ! outputDir.isDirectory())
151 {
152 throw new RuntimeException("Not a directory: "
153 + outputDir.getName());
154 }
155 }
156
157 protected void validateEARFile(File earFile)
158 {
159 if ( ! earFile.exists())
160 {
161 throw new RuntimeException("File does not exist: "
162 + earFile.getName());
163 }
164
165 if ( ! earFile.isFile())
166 {
167 throw new RuntimeException("Not a valid file: "
168 + earFile.getName());
169 }
170
171 if ( ! earFile.canRead())
172 {
173 throw new RuntimeException("Cannot read file: "
174 + earFile.getName());
175 }
176 }
177
178 public void expand(InputStream in, String name) throws java.io.IOException
179 {
180 boolean success = false;
181
182 long start = System.currentTimeMillis();
183
184 try
185 {
186 validateOutputPath();
187
188 String path = getOutputPath() + File.separator + name;
189
190 doExpand(in, name, path);
191 success = true;
192 }
193 finally
194 {
195 long end = System.currentTimeMillis();
196 long duration = end - start;
197 fireExpansionFinishedEvent(name, success, duration);
198 }
199 }
200
201 /***
202 *
203 * @param in
204 * @param name
205 * @param path
206 * @throws java.io.IOException
207 *
208 * The caller is responsible for closing the InputStream
209 *
210 */
211 protected void doExpand(InputStream in, String name, String path)
212 throws java.io.IOException
213 {
214 mkdirs(path);
215
216 ZipInputStream zis = new ZipInputStream(in);
217
218 ZipEntry entry = zis.getNextEntry();
219
220 while (entry != null)
221 {
222 processZipEntry(entry, zis, path);
223 zis.closeEntry();
224 entry = zis.getNextEntry();
225 }
226
227 }
228
229 protected boolean ignoreThisEntry(String entryName)
230 {
231 if ("CVS".equals(entryName))
232 {
233 return true;
234 }
235 else if (entryName.indexOf("CVS/") != -1)
236 {
237 return true;
238 }
239 else
240 {
241 return false;
242 }
243 }
244
245 protected void processZipEntry(ZipEntry zipEntry,
246 InputStream is,
247 String path) throws IOException
248 {
249 mkdirs(path);
250 String entryName = zipEntry.getName();
251
252 if (ignoreThisEntry(entryName))
253 {
254 fireEntrySkippedEvent(entryName);
255 }
256 else if (zipEntry.isDirectory())
257 {
258 mkdirs(path + File.separator + entryName);
259 }
260 else if (shouldExpand(entryName))
261 {
262 doExpand(is, entryName, path + File.separator + entryName);
263 }
264 else
265 {
266 String filename;
267 String filepath;
268 int index = entryName.lastIndexOf('/');
269 if (index != -1)
270 {
271 filename = entryName.substring(index + 1, entryName.length());
272 filepath = path + File.separator + entryName.substring(0, index);
273 }
274 else
275 {
276 filename = entryName;
277 filepath = path;
278 }
279
280 createFile(filename, is, filepath);
281 }
282 }
283
284 protected void createFile(String name, InputStream in, String path) throws IOException
285 {
286 path = path.replace('/', File.separatorChar);
287 mkdirs(path);
288 FileOutputStream fos = null;
289
290 String outputFilename = path + File.separator + name;
291 fos = new FileOutputStream(outputFilename);
292
293 byte[] buf = new byte[4096];
294 int n = -1;
295 while ( ( n = in.read(buf) ) != -1)
296 {
297 fos.write(buf, 0, n);
298 }
299 fos.flush();
300 fos.close();
301
302 fireFileCreatedEvent(outputFilename);
303 }
304
305 protected boolean shouldExpand(String name)
306 {
307 boolean result = false;
308
309 if (name == null)
310 {
311 result = false;
312 }
313 else
314 {
315 result = false;
316 String lowercaseName = name.toLowerCase();
317 Iterator iter = getExpansionExtensions().iterator();
318 while (iter.hasNext())
319 {
320 String ext = (String) iter.next();
321 if (lowercaseName.endsWith(ext))
322 {
323 result = true;
324 break;
325 }
326 }
327 }
328
329 return result;
330
331 }
332
333 public String toString()
334 {
335 StringBuffer sb = new StringBuffer();
336 sb.append("outputPath='" + getOutputPath() + "', ");
337 sb.append("expansionExtensions=");
338 sb.append(String.valueOf(this.getExpansionExtensions()));
339 return sb.toString();
340 }
341
342 }