View Javadoc

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 }