1 package com.atlassian.maven.plugins.amps.util;
2
3 import org.apache.commons.io.IOUtils;
4 import org.apache.commons.lang.StringUtils;
5
6 import java.io.File;
7 import java.io.FileInputStream;
8 import java.io.FileOutputStream;
9 import java.io.IOException;
10 import java.io.InputStream;
11 import java.io.OutputStream;
12 import java.util.Enumeration;
13 import java.util.zip.ZipEntry;
14 import java.util.zip.ZipFile;
15 import java.util.zip.ZipOutputStream;
16
17 public class ZipUtils {
18
19 public static void unzip(final File zipFile, final String destDir) throws IOException
20 {
21 unzip(zipFile, destDir, 0);
22 }
23
24 public static void unzip(final File zipFile, final String destDir, int leadingPathSegmentsToTrim) throws IOException
25 {
26 final ZipFile zip = new ZipFile(zipFile);
27 try {
28 final Enumeration<? extends ZipEntry> entries = zip.entries();
29 while (entries.hasMoreElements())
30 {
31 final ZipEntry zipEntry = entries.nextElement();
32 String zipPath = trimPathSegments(zipEntry.getName(), leadingPathSegmentsToTrim);
33 final File file = new File(destDir + "/" + zipPath);
34 if (zipEntry.isDirectory())
35 {
36 file.mkdirs();
37 continue;
38 }
39
40 if (!file.getParentFile().exists())
41 {
42 file.getParentFile().mkdirs();
43 }
44
45 InputStream is = null;
46 OutputStream fos = null;
47 try
48 {
49 is = zip.getInputStream(zipEntry);
50 fos = new FileOutputStream(file);
51 IOUtils.copy(is, fos);
52 }
53 finally
54 {
55 IOUtils.closeQuietly(is);
56 IOUtils.closeQuietly(fos);
57 }
58 file.setLastModified(zipEntry.getTime());
59 }
60 } finally {
61 try {
62 zip.close();
63 } catch (IOException e) {
64
65 }
66 }
67 }
68
69 public static void zipDir(final File zipFile, final File srcDir, final String prefix) throws IOException
70 {
71 ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFile));
72 try {
73 addZipPrefixes(srcDir, out, prefix);
74 addZipDir(srcDir, out, prefix);
75 } finally {
76
77 IOUtils.closeQuietly(out);
78 }
79 }
80
81 private static void addZipPrefixes(File dirObj, ZipOutputStream out, String prefix) throws IOException {
82
83 String entryPrefix = ensurePrefixWithSlash(dirObj, prefix);
84
85 String[] prefixes = entryPrefix.split("/");
86 String lastPrefix = "";
87 for (int i = 0; i < prefixes.length; i++) {
88 ZipEntry entry = new ZipEntry(lastPrefix + prefixes[i] + "/");
89 out.putNextEntry(entry);
90 out.closeEntry();
91
92 lastPrefix = prefixes[i] + "/";
93 }
94 }
95
96 private static void addZipDir(File dirObj, ZipOutputStream out, String prefix) throws IOException
97 {
98 File[] files = dirObj.listFiles();
99 byte[] tmpBuf = new byte[1024];
100 File currentFile;
101 String entryPrefix = ensurePrefixWithSlash(dirObj, prefix);
102 String entryName = "";
103
104 for (int i = 0; i < files.length; i++)
105 {
106 currentFile = files[i];
107 if (currentFile.isDirectory())
108 {
109 entryName = entryPrefix + currentFile.getName() + "/";
110
111
112 ZipEntry entry = new ZipEntry(entryName);
113 out.putNextEntry(entry);
114 out.closeEntry();
115
116
117 addZipDir(currentFile, out, entryName);
118 } else if (currentFile.isFile())
119 {
120
121 entryName = entryPrefix + currentFile.getName();
122 FileInputStream in = new FileInputStream(currentFile.getAbsolutePath());
123 try {
124 out.putNextEntry(new ZipEntry(entryName));
125
126 int len;
127 while ((len = in.read(tmpBuf)) > 0)
128 {
129 out.write(tmpBuf, 0, len);
130 }
131
132
133 out.closeEntry();
134 } finally {
135 IOUtils.closeQuietly(in);
136 }
137 }
138 }
139 }
140
141 private static String ensurePrefixWithSlash(File rootDir, String prefix) {
142 String entryPrefix = prefix;
143
144 if (StringUtils.isNotBlank(entryPrefix) && !entryPrefix.equals("/"))
145 {
146
147 if (entryPrefix.charAt(0) == '/')
148 {
149 entryPrefix = entryPrefix.substring(1);
150 }
151
152 if (entryPrefix.charAt(entryPrefix.length() - 1) != '/')
153 {
154 entryPrefix = entryPrefix + "/";
155 }
156 } else
157 {
158 entryPrefix = rootDir.getName() + "/";
159 }
160
161 return entryPrefix;
162 }
163
164 private static String trimPathSegments(String zipPath, final int trimLeadingPathSegments)
165 {
166 int startIndex = 0;
167 for (int i = 0; i < trimLeadingPathSegments; i++)
168 {
169 int nextSlash = zipPath.indexOf("/", startIndex);
170 if (nextSlash == -1) {
171 break;
172 } else {
173 startIndex = nextSlash+1;
174 }
175 }
176
177 return zipPath.substring(startIndex);
178 }
179
180 }