1 package com.atlassian.plugin.util.zip;
2
3 import org.apache.commons.io.IOUtils;
4 import org.apache.commons.io.FileUtils;
5 import org.apache.commons.logging.Log;
6 import org.apache.commons.logging.LogFactory;
7
8 import java.io.*;
9 import java.util.zip.ZipEntry;
10 import java.util.zip.ZipInputStream;
11 import java.util.*;
12
13 public abstract class AbstractUnzipper implements Unzipper
14 {
15 protected static Log log = LogFactory.getLog(FileUnzipper.class);
16 protected File destDir;
17
18 protected File saveEntry(InputStream is, ZipEntry entry) throws IOException
19 {
20 File file = new File(destDir, entry.getName());
21
22 if (entry.isDirectory())
23 {
24 file.mkdirs();
25 }
26 else
27 {
28 File dir = new File(file.getParent());
29 dir.mkdirs();
30
31 FileOutputStream fos = null;
32 try
33 {
34 fos = new FileOutputStream(file);
35 IOUtils.copy(is, fos);
36 fos.flush();
37 }
38 catch (FileNotFoundException fnfe)
39 {
40 log.error("Error extracting a file to '" + destDir + File.separator + entry.getName() + "'. This destination is invalid for writing an extracted file stream to. ");
41 return null;
42 }
43 finally
44 {
45 IOUtils.closeQuietly(fos);
46 }
47 }
48 file.setLastModified(entry.getTime());
49
50 return file;
51 }
52
53 protected ZipEntry[] entries(ZipInputStream zis) throws IOException
54 {
55 List entries = new ArrayList();
56 try
57 {
58 ZipEntry zipEntry = zis.getNextEntry();
59 while (zipEntry != null)
60 {
61 entries.add(zipEntry);
62 zis.closeEntry();
63 zipEntry = zis.getNextEntry();
64 }
65 }
66 finally
67 {
68 IOUtils.closeQuietly(zis);
69 }
70
71 return (ZipEntry[]) entries.toArray(new ZipEntry[entries.size()]);
72 }
73
74 public void conditionalUnzip() throws IOException
75 {
76 Map<String,Long> zipContentsAndLastModified = new HashMap<String,Long>();
77
78 ZipEntry[] zipEntries = entries();
79 for (int i = 0; i < zipEntries.length; i++)
80 {
81 zipContentsAndLastModified.put(zipEntries[i].getName(), zipEntries[i].getTime());
82 }
83
84
85
86 Map<String,Long> targetDirContents = getContentsOfTargetDir(destDir);
87 if (!targetDirContents.equals(zipContentsAndLastModified))
88 {
89 FileUtils.deleteDirectory(destDir);
90 unzip();
91 }
92 else
93 {
94 if (log.isDebugEnabled())
95 log.debug("Target directory contents match zip contents. Do nothing.");
96 }
97 }
98
99 private Map<String,Long> getContentsOfTargetDir(File dir)
100 {
101
102 FilenameFilter filter = new FilenameFilter()
103 {
104 public boolean accept(File dir, String name)
105 {
106 return name.endsWith(".jar");
107 }
108 };
109
110
111 if (!dir.isDirectory())
112 {
113 return Collections.emptyMap();
114 }
115
116 Map<String,Long> targetDirContents = new HashMap<String,Long>();
117 for (File child : dir.listFiles())
118 {
119 if (log.isDebugEnabled())
120 {
121 log.debug("Examining entry in zip: "+child);
122 }
123 targetDirContents.put(child.getName(), child.lastModified());
124 }
125
126 return targetDirContents;
127 }
128 }