1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 package org.openoffice.test.common;
25 
26 import java.io.BufferedInputStream;
27 import java.io.BufferedOutputStream;
28 import java.io.BufferedReader;
29 import java.io.File;
30 import java.io.FileInputStream;
31 import java.io.FileNotFoundException;
32 import java.io.FileOutputStream;
33 import java.io.FileWriter;
34 import java.io.IOException;
35 import java.io.InputStream;
36 import java.io.InputStreamReader;
37 import java.io.OutputStream;
38 import java.net.MalformedURLException;
39 import java.net.URI;
40 import java.net.URL;
41 import java.net.URLConnection;
42 import java.text.DateFormat;
43 import java.text.MessageFormat;
44 import java.text.SimpleDateFormat;
45 import java.util.Date;
46 import java.util.Properties;
47 import java.util.logging.Level;
48 import java.util.zip.ZipEntry;
49 import java.util.zip.ZipInputStream;
50 import java.util.zip.ZipOutputStream;
51 
52 import javax.xml.parsers.DocumentBuilder;
53 import javax.xml.parsers.DocumentBuilderFactory;
54 import javax.xml.transform.TransformerFactory;
55 import javax.xml.transform.dom.DOMSource;
56 import javax.xml.transform.stream.StreamResult;
57 import javax.xml.transform.stream.StreamSource;
58 import javax.xml.xpath.XPath;
59 import javax.xml.xpath.XPathExpression;
60 import javax.xml.xpath.XPathExpressionException;
61 import javax.xml.xpath.XPathFactory;
62 
63 import org.w3c.dom.Document;
64 
65 
66 /**
67  * Utilities related to the file system
68  *
69  */
70 public class FileUtil {
71 
72 	private final static DateFormat FILENAME_FORMAT = new SimpleDateFormat("yyMMddHHmm");
73 
74 	private final static Logger log = Logger.getLogger(FileUtil.class);
75 
FileUtil()76 	private FileUtil(){
77 
78 	}
79 
80 	/**
81 	 * Parse XML file to Document model
82 	 * @param path
83 	 * @return
84 	 */
parseXML(String path)85 	public static Document parseXML(String path) {
86 		try {
87 			DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance();
88 			dbfac.setNamespaceAware(true);
89 			DocumentBuilder docBuilder = dbfac.newDocumentBuilder();
90 			return docBuilder.parse(path);
91 		} catch (Exception e) {
92 			return null;
93 		}
94 	}
95 
96 	/**
97 	 * Create a new xml document
98 	 * @return
99 	 */
newXML()100 	public static Document newXML() {
101 		try {
102 			DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance();
103 			dbfac.setNamespaceAware(true);
104 			DocumentBuilder docBuilder = dbfac.newDocumentBuilder();
105 			return docBuilder.newDocument();
106 		} catch (Exception e) {
107 			return null;
108 		}
109 	}
110 
storeXML(Document doc, File file)111 	public static boolean storeXML(Document doc, File file) {
112 		try {
113 			file.getParentFile().mkdirs();
114 			TransformerFactory.newInstance().newTransformer().transform(new DOMSource(doc), new StreamResult(file));
115 			return true;
116 		} catch (Exception e) {
117 			return false;
118 		}
119 	}
120 
storeXML(Document doc, File file, File xls)121 	public static boolean storeXML(Document doc, File file, File xls) {
122 		try {
123 			file.getParentFile().mkdirs();
124 			TransformerFactory.newInstance().newTransformer(new StreamSource(xls)).transform(new DOMSource(doc), new StreamResult(file));
125 			return true;
126 		} catch (Exception e) {
127 			return false;
128 		}
129 	}
130 
storeXML(Document doc, File file, InputStream xls)131 	public static boolean storeXML(Document doc, File file, InputStream xls) {
132 		try {
133 			file.getParentFile().mkdirs();
134 			TransformerFactory.newInstance().newTransformer(new StreamSource(xls)).transform(new DOMSource(doc), new StreamResult(file));
135 			return true;
136 		} catch (Exception e) {
137 			return false;
138 		}
139 	}
140 
141 	/**
142 	 * Get a string by XPATH from a xml file
143 	 * @param xml
144 	 * @param xpathStr
145 	 * @return
146 	 */
getStringByXPath(String xml, String xpathStr)147 	public static String getStringByXPath(String xml, String xpathStr) {
148 		Document doc = parseXML(xml);
149 		if (doc == null)
150 			return null;
151 
152 	    try {
153 	    	XPathFactory factory = XPathFactory.newInstance();
154 			XPath xpath = factory.newXPath();
155 			XPathExpression expr = xpath.compile(xpathStr);
156 			return (String) expr.evaluate(doc);
157 		} catch (XPathExpressionException e) {
158 			e.printStackTrace();
159 			return null;
160 		}
161 
162 
163 	}
164 
165 
166 
167 	/**
168 	 * Update the given property in a properties file
169 	 * @param file the properties file path
170 	 * @param key the key
171 	 * @param value the value
172 	 */
updateProperty(String file, String key, String value)173 	public static void updateProperty(String file, String key, String value) {
174 		Properties map = new Properties();
175 		map.put(key, value);
176 		updateProperty(file, map);
177 	}
178 
179 	/**
180 	 * Update the given properties in a properties file
181 	 * @param file the properties file path
182 	 * @param props properties updated
183 	 */
updateProperty(String file, Properties props)184 	public static void updateProperty(String file, Properties props) {
185 		Properties properties = loadProperties(file);
186 		properties.putAll(props);
187 		storeProperties(file, properties);
188 	}
189 
190 	/**
191 	 * Load a properties file to Properties class
192 	 * @param file the properties file path
193 	 * @return
194 	 */
loadProperties(String file)195 	public static Properties loadProperties(String file) {
196 		return loadProperties(new File(file));
197 	}
198 
199 	/**
200 	 * Load a properties file to Properties class
201 	 * @param file the properties file
202 	 * @return
203 	 */
loadProperties(File file)204 	public static Properties loadProperties(File file) {
205 		Properties properties = new Properties();
206 		FileInputStream fis = null;
207 		try {
208 			fis = new FileInputStream(file);
209 			properties.load(fis);
210 		} catch (IOException e) {
211 			//System.out.println("Can't read properties file.");
212 		} finally {
213 			if (fis != null) {
214 				try {
215 					fis.close();
216 				} catch (IOException e) {
217 					// ignore
218 				}
219 			}
220 		}
221 
222 		return properties;
223 	}
224 
225 	/**
226 	 * Store properties into a file
227 	 * @param file the properties file path
228 	 * @param properties the properties to be stored
229 	 */
storeProperties(String file, Properties properties)230 	public static void storeProperties(String file, Properties properties) {
231 		FileOutputStream fos = null;
232 		try {
233 			fos = new FileOutputStream(file);
234 			properties.store(fos, "Generated By PropertyFileUtils");
235 		} catch (IOException e) {
236 			throw new RuntimeException(e);
237 		} finally {
238 			if (fos != null) {
239 				try {
240 					fos.close();
241 				} catch (IOException e) {
242 					// ignore
243 				}
244 			}
245 		}
246 	}
247 
248 
249 
250 	/**
251 	 * Delete a property in a properties file
252 	 * @param file the properties file path
253 	 * @param key the key to be deleted
254 	 */
deleteProperty(String file, String key)255 	public static void deleteProperty(String file, String key) {
256 		Properties properties = loadProperties(file);
257 		properties.remove(key);
258 		storeProperties(file, properties);
259 	}
260 
261 	/**
262 	 * Load a file as string
263 	 * @param file the file path
264 	 * @return
265 	 */
readFileAsString(String file)266 	public static String readFileAsString(String file) {
267 		return readFileAsString(new File(file));
268 	}
269 
270 	/**
271 	 * Load a file as string
272 	 * @param file the file path
273 	 * @return
274 	 */
readFileAsString(File file)275 	public static String readFileAsString(File file) {
276 		try {
277 			return readStreamAsString(new FileInputStream(file), null);
278 		} catch (FileNotFoundException e) {
279 			return "";
280 		}
281 	}
282 
readStreamAsString(InputStream inputStream, String charsetName)283 	public static String readStreamAsString(InputStream inputStream, String charsetName) {
284 		StringBuffer strBuffer = new StringBuffer(10240);
285 		BufferedReader reader = null;
286 		try {
287 			reader = new BufferedReader(charsetName == null ? new InputStreamReader(inputStream) : new InputStreamReader(inputStream, charsetName));
288 			char[] buf = new char[1024];
289 			int count = 0;
290 			while ((count = reader.read(buf)) != -1) {
291 				strBuffer.append(buf, 0, count);
292 			}
293 		} catch (IOException e) {
294 
295 		} finally {
296 			if (reader != null)
297 				try {
298 					reader.close();
299 				} catch (IOException e) {
300 					// ignore
301 				}
302 		}
303 
304 		return strBuffer.toString();
305 	}
306 
307 
isSymbolicLink(File file)308 	public static boolean isSymbolicLink(File file) {
309 		try {
310 			File parent = file.getParentFile();
311 			String name = file.getName() ;
312 			File toTest = parent != null ? new File(parent.getCanonicalPath(), name) : new File(name);
313 			return !toTest.getAbsolutePath().equals(toTest.getCanonicalPath());
314 		} catch (Exception e) {
315 			return false;
316 		}
317 	}
318 
319 	/**
320 	 * Find the first file matching the given name.
321 	 * @param dir The directory to search in
322 	 * @param name Regular Expression to match the file name
323 	 * @return
324 	 */
findFile(File dir, String name)325 	public static File findFile(File dir, String name) {
326 		if (!dir.isDirectory())
327 			return null;
328 		File[] files = dir.listFiles();
329 		for (int i = 0; i < files.length; i++) {
330 			if (files[i].isDirectory()) {
331 				File ret = findFile(files[i], name);
332 				if (ret != null)
333 					return ret;
334 			} else if (files[i].getName().matches(name)) {
335 				return files[i];
336 			}
337 		}
338 
339 		return null;
340 	}
341 
findFile(File dir, String name, boolean followSymbolicLink)342 	public static File findFile(File dir, String name, boolean followSymbolicLink) {
343 		if (!dir.isDirectory())
344 			return null;
345 		File[] files = dir.listFiles();
346 		for (int i = 0; i < files.length; i++) {
347 			if (files[i].isDirectory() && (followSymbolicLink || !isSymbolicLink(files[i]))) {
348 				File ret = findFile(files[i], name);
349 				if (ret != null)
350 					return ret;
351 			} else if (files[i].getName().matches(name)) {
352 				return files[i];
353 			}
354 		}
355 
356 		return null;
357 	}
358 
359 	/**
360 	 * Find the last file matching the given name.
361 	 * @param dir The directory to search in
362 	 * @param name Regular Expression to match the file name
363 	 * @return
364 	 */
findLastFile(File dir, String name)365 	public static File findLastFile(File dir, String name) {
366 		if (!dir.isDirectory())
367 			return null;
368 		File[] files = dir.listFiles();
369 		File file = null;
370 		for (int i = 0; i < files.length; i++) {
371 			if (files[i].isDirectory()) {
372 				File ret = findFile(files[i], name);
373 				if (ret != null)
374 					file = ret;
375 			} else if (files[i].getName().matches(name)) {
376 				file = files[i];
377 			}
378 		}
379 
380 		return file;
381 	}
382 
383 	/**
384 	 * find the first file matching the given name.
385 	 * @param dirs The directories to search in. Use ';' separate each directory.
386 	 * @param name Regular Expression to match the file name
387 	 * @return
388 	 */
findFile(String dirs, String name)389 	public static File findFile(String dirs, String name) {
390 		String[] directories = dirs.split(";");
391 		for (String s : directories) {
392 			File dir = new File(s);
393 			if (!dir.exists())
394 				continue;
395 			File file = findFile(dir, name);
396 			if (file != null)
397 				return file;
398 		}
399 
400 		return null;
401 	}
402 
403 
404 	/**
405 	 * find the last file matching the given name.
406 	 * @param dirs The directories to search in. Use ';' separate each directory.
407 	 * @param name Regular Expression to match the file name
408 	 * @return
409 	 */
findLastFile(String dirs, String name)410 	public static File findLastFile(String dirs, String name) {
411 		String[] directories = dirs.split(";");
412 		for (String s : directories) {
413 			File dir = new File(s);
414 			if (!dir.exists())
415 				continue;
416 			File file = findLastFile(dir, name);
417 			if (file != null)
418 				return file;
419 		}
420 
421 		return null;
422 	}
423 
424 	/**
425 	 * find the directory matching the given name.
426 	 * @param dir The directory to search in
427 	 * @param name Regular Expression to match the file name
428 	 * @return
429 	 */
findDir(String dir, String dirName)430 	public static File findDir(String dir, String dirName) {
431 		File[] files = new File(dir).listFiles();
432 		for (int i = 0; i < files.length; i++) {
433 			if (!files[i].isDirectory()) {
434 				File ret = findFile(files[i], dirName);
435 				if (ret != null)
436 					return ret;
437 			} else if (files[i].getName().matches(dirName)) {
438 				return files[i];
439 			}
440 		}
441 
442 		return null;
443 	}
444 
445 
446 	/**
447 	 * Write string into a file
448 	 * @param path
449 	 * @param contents
450 	 */
writeStringToFile(String path, String contents)451 	public static void writeStringToFile(String path, String contents) {
452 		writeStringToFile(new File(path), contents);
453 	}
454 
455 	/**
456 	 * Write string into a file
457 	 * @param file
458 	 * @param contents
459 	 */
writeStringToFile(File file, String contents)460 	public static void writeStringToFile(File file, String contents) {
461 		FileWriter writer = null;
462 		try {
463 			file.getParentFile().mkdirs();
464 			writer = new FileWriter(file);
465 			if (contents != null)
466 				writer.write(contents);
467 		} catch (IOException e) {
468 			e.printStackTrace();
469 		} finally {
470 			if (writer != null)
471 				try {
472 					writer.close();
473 				} catch (IOException e) {
474 				}
475 		}
476 	}
477 
478 	/**
479 	 * Appeand a string to the tail of a file
480 	 * @param file
481 	 * @param contents
482 	 */
appendStringToFile(String file, String contents)483 	public static void appendStringToFile(String file, String contents) {
484 		FileWriter writer = null;
485 		try {
486 			writer = new FileWriter(file, true);
487 			writer.write(contents);
488 		} catch (IOException e) {
489 			System.out.println("Warning:" + e.getMessage());
490 		} finally {
491 			if (writer != null)
492 				try {
493 					writer.close();
494 				} catch (IOException e) {
495 				}
496 		}
497 	}
498 
499 	/**
500 	 * Replace string in the file use regular expression
501 	 * @param file
502 	 * @param expr
503 	 * @param substitute
504 	 */
replace(String file, String expr, String substitute)505 	public static void replace(String file, String expr, String substitute) {
506 		String str = readFileAsString(file);
507 		str = str.replaceAll(expr, substitute);
508 		writeStringToFile(file, str);
509 	}
510 
511     /**
512      * Recursively copy all files in the source dir into the destination dir
513      * @param fromDirName the source dir
514      * @param toDirName the destination dir
515      * @return
516      */
copyDir(String fromDirName, String toDirName)517     public static boolean copyDir(String fromDirName, String toDirName)  {
518     	return copyDir(new File(fromDirName), new File(toDirName), true);
519     }
520 
521     /**
522      * Copy all files in the source dir into the destination dir
523      * @param fromDir
524      * @param toDir
525      * @param recursive
526      * @return
527      */
copyDir(File fromDir, File toDir, boolean recursive)528     public static boolean copyDir(File fromDir, File toDir, boolean recursive) {
529     	if (!fromDir.exists() || !fromDir.isDirectory()) {
530     		System.err.println("The source dir doesn't exist, or isn't dir.");
531     		return false;
532     	}
533     	if (toDir.exists() && !toDir.isDirectory())
534     		return false;
535     	boolean result = true;
536     	toDir.mkdirs();
537     	File[] files = fromDir.listFiles();
538     	for (int i = 0; i < files.length; i++) {
539     		if (files[i].isDirectory() && recursive)
540     			result &= copyDir(files[i], new File(toDir, files[i].getName()), true);
541     		else
542     			result &= copyFile(files[i], toDir);
543     	}
544 
545     	return result;
546     }
547 
548     /**
549      * Copy a file
550      * @param fromFile
551      * @param toFile
552      * @return
553      */
copyFile(File fromFile, File toFile)554     public static boolean copyFile(File fromFile, File toFile) {
555          if (toFile.isDirectory())
556            toFile = new File(toFile, fromFile.getName());
557 
558          FileInputStream from = null;
559          FileOutputStream to = null;
560          try {
561            from = new FileInputStream(fromFile);
562            File p = toFile.getParentFile();
563            if (p != null && !p.exists())
564         	   p.mkdirs();
565            to = new FileOutputStream(toFile);
566            byte[] buffer = new byte[4096];
567            int bytesRead;
568            while ((bytesRead = from.read(buffer)) != -1)
569              to.write(buffer, 0, bytesRead);
570 
571            return true;
572          } catch (IOException e) {
573          	//Can't copy
574          	e.printStackTrace();
575          	return false;
576          } finally {
577            if (from != null)
578              try {
579                from.close();
580              } catch (IOException e) {
581              }
582            if (to != null)
583              try {
584                to.close();
585              } catch (IOException e) {
586              }
587          }
588     }
589 
590 
591     /**
592      * Pump data from an inputstream into a file
593      * @param from
594      * @param toFile
595      * @return
596      */
writeToFile(InputStream from, File toFile)597 	public static boolean writeToFile(InputStream from, File toFile) {
598 		FileOutputStream to = null;
599 		try {
600 			File p = toFile.getParentFile();
601 			if (p != null && !p.exists())
602 				p.mkdirs();
603 			to = new FileOutputStream(toFile);
604 			byte[] buffer = new byte[4096];
605 			int bytesRead;
606 			while ((bytesRead = from.read(buffer)) != -1)
607 				to.write(buffer, 0, bytesRead);
608 
609 			return true;
610 		} catch (IOException e) {
611 			// Can't copy
612 			e.printStackTrace();
613 			return false;
614 		} finally {
615 			if (from != null)
616 				try {
617 					from.close();
618 				} catch (IOException e) {
619 				}
620 			if (to != null)
621 				try {
622 					to.close();
623 				} catch (IOException e) {
624 				}
625 		}
626 	}
627 
628 	/**
629 	 * Pump data from an inputstream into an output stream
630 	 * @param from
631 	 * @param to
632 	 * @return
633 	 */
pump(InputStream from, OutputStream to)634 	public static boolean pump(InputStream from, OutputStream to) {
635 		try {
636 			byte[] buffer = new byte[4096];
637 			int bytesRead;
638 			while ((bytesRead = from.read(buffer)) != -1)
639 				to.write(buffer, 0, bytesRead);
640 
641 			return true;
642 		} catch (IOException e) {
643 			return false;
644 		} finally {
645 			if (from != null)
646 				try {
647 					from.close();
648 				} catch (IOException e) {
649 				}
650 			if (to != null)
651 				try {
652 					to.close();
653 				} catch (IOException e) {
654 				}
655 		}
656 	}
657 
658     /**
659      * Copy a file
660      * @param fromFileName
661      * @param toFileName
662      * @return
663      */
copyFile(String fromFileName, String toFileName)664     public static boolean copyFile(String fromFileName, String toFileName) {
665     	return copyFile(new File(fromFileName), new File(toFileName));
666     }
667 
668     /**
669      * Copy all the files under fromDirName to toDirName
670      * @param fromDirName
671      * @param toDirName
672      * @return
673      */
copyFiles(String fromDirName, String toDirName)674     public static boolean copyFiles(String fromDirName, String toDirName) {
675     	boolean res = true;
676 
677     	File fromDir = new File(fromDirName);
678     	if (!fromDir.exists() || !fromDir.isDirectory() || !fromDir.canRead()) {
679          	System.err.println(fromDir.getAbsolutePath() + "doesn't exist, or isn't file, or can't be read");
680          	return false;
681          }
682     	File [] files = fromDir.listFiles();
683     	for(int i=0; i<files.length; i++){
684     		if(files[i].isDirectory()){
685     			res = res && copyDir(fromDirName + "/" + files[i].getName(), toDirName + "/" + files[i].getName());
686     		}
687     		else
688     			res = res && copyFile(fromDirName + "/" + files[i].getName(), toDirName + "/" + files[i].getName());
689     	}
690     	return res;
691     }
692 
693     /**
694      * Delete a file or directory
695      * @param file
696      * @return
697      */
deleteFile(File path)698     public static boolean deleteFile(File path) {
699     	if (!path.exists())
700     		return true;
701 
702 		if (path.isDirectory()) {
703 			File[] files = path.listFiles();
704 			for (int i = 0; i < files.length; i++) {
705 				if (files[i].isDirectory()) {
706 					deleteFile(files[i]);
707 				} else {
708 					files[i].delete();
709 				}
710 			}
711 		}
712 
713 		return path.delete();
714 	}
715 
716     /**
717      * Delete a file or directory.
718      * @param path
719      * @return
720      */
deleteFile(String path)721     public static boolean deleteFile(String path) {
722 		return deleteFile(new File(path));
723 	}
724 
725     /**
726      * Check if a file exists
727      * @param file
728      * @return
729      */
fileExists(String file)730     public static boolean fileExists(String file) {
731     	if (file == null)
732     		return false;
733     	return new File(file).exists();
734     }
735 
736     /**
737      * Get the extension name of a file
738      * @param file
739      * @return
740      */
getFileExtName(String file)741 	public static String getFileExtName(String file) {
742 		if (file == null)
743 			return null;
744 		int i = file.lastIndexOf('.');
745 		if (i < 0 && i >= file.length() - 1)
746 			return null;
747 		return file.substring(i+1);
748 	}
749 
750 
751 	/**
752 	 * Get file size. If it's a directory, it calculates the total size of files
753 	 * @param filePath
754 	 * @return
755 	 */
getFileSize(String filePath)756 	public static long getFileSize(String filePath){
757 		return getFileSize(new File(filePath));
758 	}
759 
760 	/**
761 	 * Get file size. If it's a directory, it calculates the total size of files
762 	 * @param file
763 	 * @return
764 	 */
getFileSize(File file)765 	public static long getFileSize(File file){
766 		if (file.isFile())
767 			return file.length();
768 
769 		long size = 0;
770 		File[] files = file.listFiles();
771 		if (files == null)
772 			return size;
773 
774 		for (File f : files) {
775 			size += getFileSize(f);
776 		}
777 		return size;
778 	}
779 
780 	/**
781 	 * Unzip a zip file into the destination directory
782 	 * @param zip
783 	 * @param dest
784 	 * @return
785 	 */
unzip(String zip, String dest)786 	public static boolean unzip(String zip, String dest) {
787 		return unzip(new File(zip), new File(dest));
788 	}
789 
790 	/**
791 	 * Unzip a zip file into the destination directory
792 	 * @param zipFile
793 	 * @param destFile
794 	 * @return
795 	 */
unzip(File zipFile, File destFile)796 	public static boolean unzip(File zipFile, File destFile) {
797 		ZipInputStream zin = null;
798 		FileOutputStream fos = null;
799 		try {
800 			zin = new ZipInputStream(new FileInputStream(zipFile));
801 			ZipEntry entry;
802 			while ((entry = zin.getNextEntry()) != null) {
803 				File entryFile = new File(destFile, entry.getName());
804 				if (entry.isDirectory()) {
805 					entryFile.mkdirs();
806 				} else {
807 					fos = new FileOutputStream(entryFile);
808 					byte[] b = new byte[1024];
809 					int len = 0;
810 					while ((len = zin.read(b)) != -1) {
811 						fos.write(b, 0, len);
812 					}
813 					fos.close();
814 					zin.closeEntry();
815 				}
816 
817 				if (entry.getTime() >= 0)
818 					entryFile.setLastModified(entry.getTime());
819 			}
820 			return true;
821 		} catch (IOException e) {
822 			log.log(Level.SEVERE, MessageFormat.format(" Fail! Unzip [{0}] -> [{1}]", zipFile, destFile), e);
823 			return false;
824 		} finally {
825 			if (zin != null)
826 				try {
827 					zin.close();
828 				} catch (IOException e) {
829 				}
830 			if (fos != null)
831 				try {
832 					fos.close();
833 				} catch (IOException e) {
834 				}
835 		}
836 	}
837 
zip(File dir, ZipOutputStream out, String prefix)838 	private static void zip(File dir, ZipOutputStream out, String prefix) throws Exception {
839 		File[] files = dir.listFiles();
840 		for (File f : files) {
841 			if (f.isFile()) {
842 				BufferedInputStream bis = null;
843 				try {
844 					bis = new BufferedInputStream(new FileInputStream(f));
845 					ZipEntry entry = new ZipEntry(prefix + f.getName());
846 					out.putNextEntry(entry);
847 					int count;
848 					byte data[] = new byte[8192];
849 					while ((count = bis.read(data)) != -1) {
850 						out.write(data, 0, count);
851 					}
852 					bis.close();
853 				} finally {
854 					if (bis != null)
855 						bis.close();
856 				}
857 
858 			} else {
859 				zip(f, out, prefix + f.getName() + "/");
860 			}
861 		}
862 	}
863 
zip(File workingDir, File zipFile)864 	public static void zip(File workingDir, File zipFile) {
865 		zip(workingDir, zipFile, null);
866 	}
867 
zip(File workingDir, File zipFile, String prefix)868 	public static void zip(File workingDir, File zipFile, String prefix) {
869 		if (!workingDir.isDirectory())
870 			return;
871 
872 		if (prefix == null)
873 			prefix = "";
874 
875 		ZipOutputStream out = null;
876 		try {
877 			out = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipFile)));
878 			zip(workingDir, out, prefix);
879 		} catch (Exception e) {
880 
881 		} finally {
882 			if (out != null)
883 				try {
884 					out.close();
885 				} catch (IOException e) {
886 				}
887 		}
888 
889 	 }
890 	/**
891 	 * Get an unique name under the specified directory
892 	 * @param dir
893 	 * @param prefix
894 	 * @param suffix
895 	 * @return
896 	 */
getUniqueFile(File dir, String prefix, String suffix)897 	public static File getUniqueFile(File dir, String prefix, String suffix) {
898 		String name = prefix + "." + FILENAME_FORMAT.format(new Date()) + ".";
899 		for (int i = 0; i < Integer.MAX_VALUE; i++) {
900 			File file = new File(dir, name + i + suffix);
901 			if (!file.exists()) {
902 				return file;
903 			}
904 		}
905 
906 		return null;
907 	}
908 
909 	/**
910 	 * Get an unique name under the specified directory
911 	 * @param dir
912 	 * @param prefix
913 	 * @param suffix
914 	 * @return
915 	 */
getUniqueFile(String dir, String prefix, String suffix)916 	public static File getUniqueFile(String dir, String prefix, String suffix) {
917 		return getUniqueFile(new File(dir), prefix, suffix);
918 	}
919 
920 	/**
921 	 * Download a file from a url to the local file system
922 	 * @param urlString
923 	 * @param output
924 	 * @return
925 	 */
download(String urlString, File output)926 	public static File download(String urlString, File output) {
927 		return download(urlString, output, false);
928 	}
929 
download(String urlString, File output, boolean usetimestamp)930 	public static File download(String urlString, File output, boolean usetimestamp) {
931 		return download(urlString, output, false, null);
932 	}
933 
934 	/**
935 	 * Download a file from a url to the local file system
936 	 * @param urlString
937 	 * @param output
938 	 * @param usetimestamp
939 	 * @return
940 	 */
download(String urlString, File output, boolean usetimestamp, boolean[] skip)941 	public static File download(String urlString, File output, boolean usetimestamp, boolean[] skip) {
942 		InputStream in = null;
943 		OutputStream out = null;
944 		try {
945 			URI url = new URI(urlString);
946 			URLConnection urlConnection = url.toURL().openConnection();
947 			int totalSize = urlConnection.getContentLength();
948 			in = urlConnection.getInputStream();
949 			if (output.isDirectory())
950 				output = new File(output, new File(url.getPath()).getName());
951 			output.getParentFile().mkdirs();
952 			if (usetimestamp && output.exists()) {
953 				if (output.lastModified() == urlConnection.getLastModified()) {
954 					log.info(MessageFormat.format(" Skip! Download {0} -> {1}", urlString, output));
955 					if (skip != null && skip.length > 0)
956 						skip[0] = true;
957 					return output;
958 				}
959 			}
960 
961 			out = new FileOutputStream(output);
962 			byte[] buffer = new byte[1024 * 100]; // 100k
963 			int count = 0;
964 			int totalCount = 0;
965 			int progress = 0;
966 			while ((count = in.read(buffer)) > 0) {
967 				out.write(buffer, 0, count);
968 				totalCount += count;
969 
970 				if (totalSize > 0) {
971 					int nowProgress = totalCount * 10 / totalSize;
972 					if (nowProgress > progress) {
973 						progress = nowProgress;
974 					}
975 				}
976 
977 			}
978 			out.close();
979 			if (urlConnection.getLastModified() >= 0)
980 				output.setLastModified(urlConnection.getLastModified());
981 			log.info(MessageFormat.format("OK! Download {0} -> {1}", urlString, output));
982 			if (skip != null && skip.length > 0)
983 				skip[0] = false;
984 			return output;
985 		} catch (Exception e) {
986 			log.log(Level.SEVERE, MessageFormat.format("Fail! Download {0} -> {1}", urlString, output), e);
987 			return null;
988 		} finally {
989 			if (in != null)
990 				try {
991 					in.close();
992 				} catch (IOException e) {
993 				}
994 			if (out != null)
995 				try {
996 					out.close();
997 				} catch (IOException e) {
998 
999 				}
1000 		}
1001 	}
1002 
1003 
1004 	/**
1005 	 * Convert a file path to URL like "file:///dir/some.file"
1006 	 * @param file
1007 	 * @return
1008 	 */
getUrl(File file)1009 	public static String getUrl(File file) {
1010 		try {
1011 			String url = file.getCanonicalFile().toURI().toASCIIString();
1012 			return url.replace("file:/", "file:///");
1013 		} catch(Exception e) {
1014 
1015 		}
1016 
1017 		return null;
1018 	}
1019 
1020 
1021 	/**
1022 	 * Convert a file path to URL like "file:///dir/some.file"
1023 	 * @param file
1024 	 * @return
1025 	 */
getUrl(String path)1026 	public static String getUrl(String path) {
1027 		return getUrl(new File(path));
1028 	}
1029 
1030 	/**
1031 	 * Check if the given address is valid URL
1032 	 * @param address
1033 	 * @return
1034 	 */
isUrl(String address)1035 	public static boolean isUrl(String address) {
1036 		if (address == null)
1037 			return false;
1038 		try {
1039 			new URL(address);
1040 			return true;
1041 		} catch (MalformedURLException e) {
1042 			return false;
1043 		}
1044 
1045 	}
1046 }
1047