/framework/src/play/libs/Files.java

https://github.com/tazmaniax/play1 · Java · 229 lines · 147 code · 20 blank · 62 comment · 26 complexity · bc22644f928472608fee1dcf2adaa2b3 MD5 · raw file

  1. package play.libs;
  2. import static org.apache.commons.io.FileUtils.copyInputStreamToFile;
  3. import java.io.File;
  4. import java.io.FileInputStream;
  5. import java.io.FileOutputStream;
  6. import java.io.IOException;
  7. import java.nio.file.NoSuchFileException;
  8. import java.nio.file.Path;
  9. import java.nio.file.Paths;
  10. import java.util.Enumeration;
  11. import java.util.zip.ZipEntry;
  12. import java.util.zip.ZipFile;
  13. import java.util.zip.ZipOutputStream;
  14. import org.apache.commons.io.FileUtils;
  15. import org.apache.commons.io.IOUtils;
  16. import play.Logger;
  17. import play.exceptions.UnexpectedException;
  18. /**
  19. * Files utils
  20. */
  21. public class Files {
  22. /**
  23. * Characters that are invalid in Windows OS file names (Unix only forbids '/' character)
  24. */
  25. public static final char[] ILLEGAL_FILENAME_CHARS = { 34, 60, 62, 124, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
  26. 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 58, 42, 63, 92, 47 };
  27. public static final char ILLEGAL_FILENAME_CHARS_REPLACE = '_';
  28. /**
  29. * Indicate if two file refers to the same one
  30. *
  31. * @param a
  32. * First file to compare
  33. * @param b
  34. * Second file to compare
  35. * @return true is file are the same
  36. */
  37. public static boolean isSameFile(File a, File b) {
  38. if (a != null && b != null) {
  39. Path aPath = null;
  40. Path bPath = null;
  41. try {
  42. aPath = Paths.get(a.getCanonicalPath());
  43. bPath = Paths.get(b.getCanonicalPath());
  44. return java.nio.file.Files.isSameFile(aPath, bPath);
  45. } catch (NoSuchFileException e) {
  46. // As the file may not exist, we only compare path
  47. return 0 == aPath.compareTo(bPath);
  48. } catch (Exception e) {
  49. Logger.error(e, "Cannot get canonical path from files");
  50. }
  51. }
  52. return false;
  53. }
  54. /**
  55. * Just copy a file
  56. *
  57. * @param from
  58. * source of the file
  59. * @param to
  60. * destination file
  61. */
  62. public static void copy(File from, File to) {
  63. if (isSameFile(from, to)) {
  64. return;
  65. }
  66. try {
  67. FileUtils.copyFile(from, to);
  68. } catch (Exception e) {
  69. throw new RuntimeException(e);
  70. }
  71. }
  72. /**
  73. * Just delete a file. If the file is a directory, it's work.
  74. *
  75. * @param file
  76. * The file to delete
  77. * @return true if and only if the file is successfully deleted; false otherwise
  78. */
  79. public static boolean delete(File file) {
  80. if (file.isDirectory()) {
  81. return deleteDirectory(file);
  82. } else {
  83. return file.delete();
  84. }
  85. }
  86. /**
  87. * Recursively delete a directory.
  88. *
  89. * @param path
  90. * Path of the directory
  91. * @return true if and only if the directory is successfully deleted; false otherwise
  92. */
  93. public static boolean deleteDirectory(File path) {
  94. if (path.exists()) {
  95. File[] files = path.listFiles();
  96. for (File file : files) {
  97. if (file.isDirectory()) {
  98. deleteDirectory(file);
  99. } else {
  100. file.delete();
  101. }
  102. }
  103. }
  104. return (path.delete());
  105. }
  106. public static boolean copyDir(File from, File to) {
  107. try {
  108. FileUtils.copyDirectory(from, to);
  109. return true;
  110. } catch (IOException e) {
  111. return false;
  112. }
  113. }
  114. public static void unzip(File from, File to) {
  115. try {
  116. String outDir = to.getCanonicalPath();
  117. try (ZipFile zipFile = new ZipFile(from)) {
  118. Enumeration<? extends ZipEntry> entries = zipFile.entries();
  119. while (entries.hasMoreElements()) {
  120. ZipEntry entry = entries.nextElement();
  121. if (entry.isDirectory()) {
  122. new File(to, entry.getName()).mkdir();
  123. continue;
  124. }
  125. File f = new File(to, entry.getName());
  126. if (!f.getCanonicalPath().startsWith(outDir)) {
  127. throw new IOException("Corrupted zip file");
  128. }
  129. f.getParentFile().mkdirs();
  130. copyInputStreamToFile(zipFile.getInputStream(entry), f);
  131. }
  132. }
  133. } catch (IOException e) {
  134. throw new RuntimeException(e);
  135. }
  136. }
  137. public static void zip(File directory, File zipFile) {
  138. try {
  139. try (FileOutputStream os = new FileOutputStream(zipFile)) {
  140. try (ZipOutputStream zos = new ZipOutputStream(os)) {
  141. zipDirectory(directory, directory, zos);
  142. }
  143. }
  144. } catch (Exception e) {
  145. throw new UnexpectedException(e);
  146. }
  147. }
  148. /**
  149. * Replace all characters that are invalid in file names on Windows or Unix operating systems with
  150. * {@link Files#ILLEGAL_FILENAME_CHARS_REPLACE} character.
  151. * <p>
  152. * This method makes sure your file name can successfully be used to write new file to disk. Invalid characters are
  153. * listed in {@link Files#ILLEGAL_FILENAME_CHARS} array.
  154. *
  155. * @param fileName
  156. * File name to sanitize
  157. * @return Sanitized file name (new String object) if found invalid characters or same string if not
  158. */
  159. public static String sanitizeFileName(String fileName) {
  160. return sanitizeFileName(fileName, ILLEGAL_FILENAME_CHARS_REPLACE);
  161. }
  162. /**
  163. * Replace all characters that are invalid in file names on Windows or Unix operating systems with passed in
  164. * character.
  165. * <p>
  166. * This method makes sure your file name can successfully be used to write new file to disk. Invalid characters are
  167. * listed in {@link Files#ILLEGAL_FILENAME_CHARS} array.
  168. *
  169. * @param fileName
  170. * File name to sanitize
  171. * @param replacement
  172. * character to use as replacement for invalid chars
  173. * @return Sanitized file name (new String object) if found invalid characters or same string if not
  174. */
  175. public static String sanitizeFileName(String fileName, char replacement) {
  176. if (fileName == null || fileName.isEmpty()) {
  177. return fileName;
  178. }
  179. char[] chars = fileName.toCharArray();
  180. boolean changed = false;
  181. for (int i = 0; i < chars.length; i++) {
  182. char c = chars[i];
  183. if (c < 128) {
  184. for (char illegal : ILLEGAL_FILENAME_CHARS) {
  185. if (c == illegal) {
  186. chars[i] = replacement;
  187. changed = true;
  188. break;
  189. }
  190. }
  191. }
  192. }
  193. return changed ? new String(chars) : fileName;
  194. }
  195. static void zipDirectory(File root, File directory, ZipOutputStream zos) throws Exception {
  196. for (File item : directory.listFiles()) {
  197. if (item.isDirectory()) {
  198. zipDirectory(root, item, zos);
  199. } else {
  200. try (FileInputStream fis = new FileInputStream(item)) {
  201. String path = item.getAbsolutePath().substring(root.getAbsolutePath().length() + 1);
  202. ZipEntry anEntry = new ZipEntry(path);
  203. zos.putNextEntry(anEntry);
  204. IOUtils.copyLarge(fis, zos);
  205. }
  206. }
  207. }
  208. }
  209. }