View Javadoc

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.slf4j.LoggerFactory;
6   import org.slf4j.Logger;
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 Logger log = LoggerFactory.getLogger(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          // If the jar contents of the directory does not match the contents of the zip
85          // The we will nuke the bundled plugins directory and re-extract.
86          Map<String,Long> targetDirContents = getContentsOfTargetDir(destDir);
87          if (!targetDirContents.equals(zipContentsAndLastModified))
88          {
89              // Note: clean, not delete, as destdir may be a symlink (PLUG-606).
90              if (destDir.exists())
91              {
92                  FileUtils.cleanDirectory(destDir);
93              }
94              unzip();
95          }
96          else
97          {
98              if (log.isDebugEnabled())
99                  log.debug("Target directory contents match zip contents. Do nothing.");
100         }
101     }
102 
103     private Map<String,Long> getContentsOfTargetDir(File dir)
104     {
105         // Create filter that lists only jars
106         FilenameFilter filter = new FilenameFilter()
107         {
108             public boolean accept(File dir, String name)
109             {
110                 return name.endsWith(".jar");
111             }
112         };
113 
114 
115         if (!dir.isDirectory())
116         {
117             return Collections.emptyMap();
118         }
119 
120         Map<String,Long> targetDirContents = new HashMap<String,Long>();
121         for (File child : dir.listFiles())
122         {
123             if (log.isDebugEnabled())
124             {
125                 log.debug("Examining entry in zip: "+child);
126             }
127             targetDirContents.put(child.getName(), child.lastModified());
128         }
129 
130         return targetDirContents;
131     }
132 }