View Javadoc

1   package com.atlassian.core.util.zip;
2   
3   import org.apache.commons.io.IOUtils;
4   
5   import javax.annotation.Nonnull;
6   import javax.annotation.Nullable;
7   import javax.annotation.concurrent.NotThreadSafe;
8   import java.io.File;
9   import java.io.FileNotFoundException;
10  import java.io.FileOutputStream;
11  import java.io.IOException;
12  import java.io.InputStream;
13  import java.io.OutputStream;
14  import java.util.zip.ZipEntry;
15  import java.util.zip.ZipOutputStream;
16  
17  /**
18   * An utility class which allows to add multiple directories/files/entries from stream to zip archive.
19   *
20   * @since v6.4
21   */
22  @NotThreadSafe
23  public class ZipArchiver
24  {
25  
26      @Nonnull
27      private final File archiveFile;
28      @Nullable
29      private FileArchiver fileArchiver;
30      @Nullable
31      private ZipOutputStream zipOutputStream;
32  
33      public ZipArchiver(final File archiveFile)
34      {
35          this.archiveFile = archiveFile;
36      }
37  
38      /**
39       * Adds directory and all subdirectories into archive.
40       *
41       * @param folderToCompress  the directory handle to add to archive
42       * @param archiveFolderName the name which will be used as archive directory name, for example when {@code
43       *                          folderToCompress} is pointing into /home/A/B directory which contains file with path
44       *                          /home/A/B/C/file and {@code archiveFolderName} equals "archive" a result zip archive
45       *                          will contain entry: /archive/C/file
46       *
47       * @throws IOException
48       */
49      public void addFolder(final File folderToCompress, final String archiveFolderName) throws IOException
50      {
51          final FolderAppender folderAppender = new FolderAppender(getFileArchiver(), folderToCompress, archiveFolderName, archiveFile);
52          folderAppender.append();
53      }
54  
55      /**
56       * Adds directory and all subdirectories into archive.
57       *
58       * @param folderToCompress  the directory handle to add to archive
59       * @param archiveParams parameters for the files in the folder to be added the to archive
60       *
61       * @throws IOException
62       */
63      public void addFolder(final File folderToCompress, final ArchiveParams archiveParams) throws IOException
64      {
65          final FolderAppender folderAppender = new FolderAppender(getFileArchiver(), folderToCompress, archiveParams, archiveFile);
66          folderAppender.append();
67      }
68  
69      /**
70       * Adds a file to archive.
71       * @param sourceFile a file which content will be added as new entry
72       * @param targetPath a file path which will be used as entry name
73       * @throws IOException
74       */
75      public void addFile(final File sourceFile, final String targetPath) throws IOException
76      {
77          getFileArchiver().addToArchive(sourceFile, targetPath, "");
78      }
79  
80      /**
81       * Adds new entry to zip archive with name specified by {@code entryPath} parameter and with content from provided
82       * {@link java.io.InputStream}
83       * @param content stream which will be used as entry content
84       * @param entryPath will be used as entry name
85       * @throws IOException
86       */
87      public void addEntry(final InputStream content, final String entryPath) throws IOException
88      {
89          final ZipEntry entry = new ZipEntry(FilePathUtils.stripSlashes(entryPath));
90          getZipOutputStream().putNextEntry(entry);
91          try
92          {
93              IOUtils.copyLarge(content, zipOutputStream);
94          }
95          finally
96          {
97              getZipOutputStream().closeEntry();
98              IOUtils.closeQuietly(content);
99          }
100     }
101 
102     /**
103      * Creates new zipEntry and provides OutputStream to write content to given entry. Keep in mind that provided
104      * outPutStream is valid as long as no other methods creating new entry are called.
105      * @param entryName the name of zip entry
106      * @return OutputStream to write content to given entry
107      * @throws IOException
108      */
109     public OutputStream addNextEntry(final String entryName) throws IOException
110     {
111         getZipOutputStream().putNextEntry(new ZipEntry(entryName));
112         return getZipOutputStream();
113     }
114 
115     public void close() throws IOException
116     {
117         if (zipOutputStream != null)
118         {
119             zipOutputStream.closeEntry();
120             zipOutputStream.close();
121         }
122     }
123 
124     private FileArchiver getFileArchiver() throws FileNotFoundException
125     {
126         if (fileArchiver == null)
127         {
128             final ZipOutputStream zipOutputStream = getZipOutputStream();
129             fileArchiver = new FileArchiver(zipOutputStream);
130         }
131         return fileArchiver;
132     }
133 
134     private ZipOutputStream getZipOutputStream() throws FileNotFoundException
135     {
136         if(zipOutputStream == null)
137         {
138             zipOutputStream = new ZipOutputStream(new FileOutputStream(archiveFile));
139         }
140         return zipOutputStream;
141     }
142 
143 }