awesome assets from gffs code
[feisty_meow.git] / kona / src / org / gffs / compression / PackTar.java
1 package org.gffs.compression;
2
3 import java.io.File;
4 import java.io.FileInputStream;
5 import java.io.FileOutputStream;
6 import java.io.IOException;
7 import java.util.Iterator;
8
9 import org.apache.commons.compress.archivers.ArchiveEntry;
10 import org.apache.commons.compress.archivers.ArchiveOutputStream;
11 import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
12 import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
13 import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream;
14 import org.apache.commons.io.FileUtils;
15 import org.apache.commons.io.IOUtils;
16 import org.apache.commons.io.filefilter.IOFileFilter;
17 import org.apache.commons.io.filefilter.TrueFileFilter;
18 import org.apache.commons.logging.Log;
19 import org.apache.commons.logging.LogFactory;
20
21 public class PackTar
22 {
23         static private Log _logger = LogFactory.getLog(PackTar.class);
24
25         /**
26          * returns the "longName" with the "prefix" stripped off the front. if the name doesn't contain the prefix, then an error is thrown.
27          */
28         public static String stripOutPrefix(String prefix, String longName) throws IOException
29         {
30                 int indy = longName.indexOf(prefix, 0);
31                 if (indy < 0)
32                         throw new IOException("failure to find prefix in string, prefix=" + prefix + " and string=" + longName);
33                 return longName.substring(indy + prefix.length());
34         }
35
36         /**
37          * adds the file pointed at by "source" to the archive in "tarOut" as a compressed file. if "source" is a directory, then the directory is
38          * recursed and added. the names in the archive will be stripped of the "prefix" string before being added to the archive; for example, if
39          * the source path "/home/fred/wumpus" and the prefix string is "/home/fred/", then the files in the archive will be named "wumpus/A",
40          * "wumpus/B", etc.
41          */
42         public static void compressArchive(ArchiveOutputStream tarOut, String prefix, File source) throws IOException
43         {
44                 _logger.debug("entered into compress archive on source " + source + " prefix " + prefix + " and tarout " + tarOut);
45
46                 if (!source.exists()) {
47                         // Don't unpack into an existing directory.
48                         String msg = "Directory " + source.getAbsolutePath() + " doesn't exist yet. Cannot pack.";
49                         _logger.error(msg);
50                         throw new IOException(msg);
51                 }
52
53                 // traverse the whole tree of the directory (or just write this directly if it's a file).
54                 if (source.isFile()) {
55                         String choppedName = stripOutPrefix(prefix, source.getPath());
56                         if (_logger.isDebugEnabled())
57                                 _logger.debug("adding a file to the archive (chopped): " + choppedName);
58                         ArchiveEntry f = tarOut.createArchiveEntry(source, choppedName);
59                         tarOut.putArchiveEntry(f);
60                         IOUtils.copy(new FileInputStream(source), tarOut);
61                         tarOut.closeArchiveEntry();
62                 } else if (source.isDirectory()) {
63                         // traverse the directory tree at just this height and add everything recursively.
64
65                         if (_logger.isDebugEnabled())
66                                 _logger.debug("iterating over a directory to add its contents to the archive: " + source);
67
68                         Iterator<File> spidey = FileUtils.iterateFiles(source, new IOFileFilter()
69                         {
70                                 @Override
71                                 public boolean accept(File arg0)
72                                 {
73                                         return true;
74                                 }
75
76                                 @Override
77                                 public boolean accept(File arg0, String arg1)
78                                 {
79                                         return true;
80                                 }
81                         }, TrueFileFilter.INSTANCE);
82
83                         File item = null;
84                         while (spidey.hasNext()) {
85                                 item = spidey.next();
86
87                                 if (_logger.isTraceEnabled())
88                                         _logger.debug("recursing on item: " + item);
89
90                                 compressArchive(tarOut, prefix, item);
91                         }
92                 } else {
93                         String msg = "source is not a file or directory although it exists.  unknown how to process.";
94                         _logger.error(msg);
95                         throw new IOException(msg);
96                 }
97
98         }
99
100         /**
101          * returns the same string as presented, but ensures that the last character will be a directory separator (/).
102          */
103         public static String findAppropriatePrefix(String toChop)
104         {
105                 if (toChop.endsWith("/"))
106                         return toChop; // already ready.
107                 else
108                         return toChop + "/"; // add a slash on the end.
109         }
110
111         public synchronized static void compressTarGZ(File tarFile, File dest) throws IOException
112         {
113                 TarArchiveOutputStream tarOut = new TarArchiveOutputStream(new GzipCompressorOutputStream(new FileOutputStream(tarFile)));
114                 compressArchive(tarOut, findAppropriatePrefix(dest.getPath()), dest);
115                 tarOut.close();
116         }
117
118         public synchronized static void compressTar(File tarFile, File dest) throws IOException
119         {
120                 TarArchiveOutputStream tarOut = new TarArchiveOutputStream(new FileOutputStream(tarFile));
121                 compressArchive(tarOut, findAppropriatePrefix(dest.getPath()), dest);
122                 tarOut.close();
123         }
124
125         public synchronized static void compressZip(File zipFile, File dest) throws IOException
126         {
127                 ZipArchiveOutputStream tarOut = new ZipArchiveOutputStream(new FileOutputStream(zipFile));
128                 compressArchive(tarOut, findAppropriatePrefix(dest.getPath()), dest);
129                 tarOut.close();
130         }
131
132         static public void main(String[] args) throws Throwable
133         {
134                 // future: could use our cool code above to handle any archive type they pass.
135                 if (args.length != 2) {
136                         System.err.println("USAGE: PackTar {tar.gz file} {source location}");
137                         System.exit(1);
138                 }
139
140                 try {
141                         PackTar.compressTarGZ(new File(args[0]), new File(args[1]));
142                 } catch (Throwable t) {
143                         _logger.error("failed to compress tar file " + args[0] + " from " + args[1]);
144                         System.exit(1);
145                 }
146
147                 System.out.println("successfully compressed archive file " + args[0] + " from " + args[1]);
148         }
149
150 }