001/*
002 *  $Source: /cvsroot2/open/projects/jAckup/ca/bc/webarts/tools/MultiZip.java,v $
003 *  $Revision: 1.1 $  $Date: 2005-04-10 11:32:43 -0700 (Sun, 10 Apr 2005) $  $Locker:  $
004 *  Copyright 2001-2002 (C) WebARTS Design.   All rights reserved.
005 *
006 *  This program is free software; you can redistribute it and/or
007 *  modify it under the terms of the GNU General Public License
008 *  as published by the Free Software Foundation; either version 2
009 *  of the License, or any later version.
010 *
011 *  This program is distributed in the hope that it will be useful,
012 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
013 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
014 *  GNU General Public License for more details.
015 *
016 *  You should have received a copy of the GNU General Public License
017 *  along with this program; if not, write to the Free Software
018 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
019 */
020package ca.bc.webarts.tools;
021
022import ca.bc.webarts.widgets.Util;
023
024import com.aftexsw.util.bzip.BZip;
025
026import com.ice.tar.TarArchive;
027import com.ice.tar.TarEntry;
028
029import jargs.gnu.CmdLineParser;
030
031import java.io.File;
032import java.io.FileInputStream;
033import java.io.FileNotFoundException;
034import java.io.FileOutputStream;
035import java.io.IOException;
036
037import java.util.Date;
038import java.util.Vector;
039
040import java.util.zip.DataFormatException;
041import java.util.zip.DeflaterOutputStream;
042import java.util.zip.GZIPOutputStream;
043import java.util.zip.ZipEntry;
044import java.util.zip.ZipException;
045import java.util.zip.ZipOutputStream;
046
047import org.apache.log4j.Level;
048import org.apache.log4j.Logger;
049import org.apache.log4j.PropertyConfigurator;
050
051
052/**
053 *  This class creates an archive of the specified directories and/or files. <p>
054 *
055 *  Some of the features of this classes implementation of archiving:
056 *  <ul>
057 *    <li> The max size for the archive can be specified</li>
058 *    <li> Cross Platform </li>
059 *    <li> Selectable Archive format:
060 *    <ul>
061 *      <li> directory of files</li>
062 *      <li> tar </li>
063 *      <li> zip</li>
064 *      <li> tgz</li>
065 *    </ul>
066 *
067 *    <li> Selectable compression format:
068 *    <ul>
069 *      <li> none</li>
070 *      <li> zip</li>
071 *      <li> gzip</li>
072 *      <li> bzip2</li>
073 *    </ul>
074 *
075 *  </ul>
076 *  </p> Compression format is independant of the archive format.<p>
077 *
078 *  <p>
079 *
080 *  As you see this is a slightly different way of thinking of archiving - it
081 *  provides maximum latitude in choosing the style a archive. For example: it
082 *  allows the unconventional file.gz.tar format of an archive (all files are
083 *  individually compressed with gzip format and then they are collected
084 *  together into a tar archive format. Why??? its up to you. But this class
085 *  should provide the way of getting the archive you want.</p> <p>
086 *
087 *  I personally bzip2 all my files into an empty directory which then is a
088 *  staging area for making an iso-9660 image for backing onto a CDRW. </p> <p>
089 *
090 *  <b>Usage details:</b> (for full usage details...run MultiZip with no
091 *  options) <pre>
092 * java ca.bc.webarts.tools.MultiZip [options] &lt;source directory(s)/file(s)>
093 *    options:
094 *         -a dir,tar,zip         DEFAULT=zip
095 *         -c none,zip,gzip,bzip2 DEFAULT=zip
096 *         -l 0-9                 DEFAULT=9
097 *         -v                     DEFAULT=not verbose
098 *         -o filename            DEFAULT=same as input location
099 *
100 * EXAMPLE:
101 *   java MultiZip -a dir -c bzip2 -l 9 -o /home/joeBlo/staging /home/joBlo/src
102 *  </pre> <p>
103 *
104 *  <b>This tool is released with a GNU General Public License.<br>
105 *  Author: Tom Gutwin <a href="mailto:tgutwin@webarts.bc.ca">
106 *  tgutwin@webarts.bc.ca</a> <br>
107 *  Copyright &copy; 2002 <a href="http://www.webarts.bc.ca">WebARTS Design.</a>
108 *  </b></p>
109 *
110 * @author    Tom Gutwin <a href="mailto:tgutwin@webarts.bc.ca">
111 *      tgutwin@webarts.bc.ca</a>
112 */
113public class MultiZip
114{
115  /**  Constant VAR */
116  public final static short DIR_ARCHIVE = 1;
117  /**  Constant VAR */
118  public final static short TAR_ARCHIVE = 2;
119  /**  Constant VAR */
120  public final static short ZIP_ARCHIVE = 3;
121  /**  Constant VAR */
122  public final static short TGZ_ARCHIVE = 4;
123  /**  Constant VAR */
124  public final static short ZIP_COMPRESSION = 1;
125  /**  Constant VAR */
126  public final static short GZIP_COMPRESSION = 2;
127  /**  Constant VAR */
128  public final static short BZIP2_COMPRESSION = 3;
129  /**  Constant VAR */
130  public final static short NO_COMPRESSION = 4;
131  /**  Constant VAR */
132  public final static String LINE_SEPARATOR =
133      System.getProperty("line.separator");
134
135  /**  The log4j logger object. */
136  protected static Logger logger_ = Logger.getLogger(MultiZip.class.getName());
137
138  /**  A Class holder for its name (used in Logging). */
139  protected static String className_ = "MultiZip";
140
141  /**  The log4j logger config location. */
142  protected static String log4jConfigLocation_ =
143      System.getProperty("user.home") + "/dev/logs/" + className_ +
144      "Log4jConfig.txt";
145
146  /*
147   *  User settable vars from the cmdline
148   */
149  /**  Flags if the output will be verbose. **/
150  protected boolean verbose_ = false;
151
152  /**  Flags if the output will be reduced. **/
153  protected boolean quiet_ = false;
154
155  /**  Flags for no output. **/
156  protected boolean reallyQuiet_ = false;
157
158  /**  Output stream for destination zip file. **/
159  protected DeflaterOutputStream zos_ = null;
160
161  /**  The current working destination zip file. **/
162  protected File zipfile_ = null;
163
164  /**
165   * The instatited archive type.
166   * User settable. **/
167  short archiveType_ = DIR_ARCHIVE;
168  /**  Description of the Field. */
169  short compressionType_ = ZIP_COMPRESSION;
170  /**  Description of the Field. **/
171  int compressionLevel_ = 9;
172  /**  The specified output filename/dirname. **/
173  String output_ = null;
174  /**  The temp dir where the zipped files go before archiving. **/
175  String zippedOutputLocation_ = null;
176  /**  The collection of files/dirnames to include in the archive. **/
177  Vector input_ = null;
178  /**  The collection of filenames that actually got comp'd. **/
179  Vector compressedFilenames_ = new Vector();
180  /**  The collection of filenames that had errors during compression. **/
181  Vector errorFiles_ = null;
182  /**  Description of the Field **/
183  int archivefilenameCounter_ = 0;
184  /**
185   *  The maximum size in megabytes the archive will be allowed to grow to
186   *  before creating a second archive with a incremental name.
187   **/
188  int maxArchiveSize_ = 600 * 1000 * 1000;
189
190  /**  The current archive file size in bytes. **/
191  long currArchiveSize_ = 0L;
192
193  /**  Description of the Field */
194  String[] defaultExcludes_ = {"~", "SWAPPER.DAT", "#", "OldHPFS", "OldFatDisk",
195      "tmp", "Trash", "deleteme"};
196  /**  The temp dir where the zipped files go before archiving. **/
197  private String tmpDirName_ = "tmp_MultiZip";
198
199
200  /**
201   *  Default Constructor for the MultiZip object that does NO processing.
202   **/
203  MultiZip()
204  {
205    final String methodName = className_ + ": MultiZip Constructor()";
206    logger_.debug("Entering " + methodName);
207
208    logger_.debug("Exiting " + methodName);
209  }
210
211
212  /**
213   *  Constructor for the MultiZip object
214   *
215   * @param  src  An array of files to include in the zip.
216   * @param  des  Description of the Parameter
217   */
218  MultiZip(File[] src, File des)
219  {
220    final String methodName = className_ + ": MultiZip Constructor()";
221    logger_.debug("Entering " + methodName);
222
223    zipFiles(src, des);
224    logger_.debug("Exiting " + methodName);
225  }
226
227
228  /**
229   *  Constructor for the MultiZip object
230   *
231   * @param  src  a single File object to be included in the archice
232   * @param  des  The destination File for the archive.
233   */
234  MultiZip(File src, File des)
235  {
236    final String methodName = className_ + ": MultiZip Constructor()";
237    logger_.debug("Entering " + methodName);
238
239    File[] srcArray = {src};
240    zipFiles(srcArray, des);
241
242    logger_.debug("Exiting " + methodName);
243  }
244
245
246  /**
247   *  Main Entry point to run this class as an application usage: <code>
248   * MultiZip <destination file> <source directorys / files>
249   *</code>
250   *
251   * @param  args  1st arg is the destination file, 2nd arg is the source files
252   */
253  public static void main(String args[])
254  {
255    // log4j logger config
256    PropertyConfigurator.configure(log4jConfigLocation_);
257    logger_.setLevel(Level.WARN);
258    final String methodName = className_ + ": MultiZip Main(String [])";
259    logger_.debug("Entering " + methodName);
260
261    MultiZip multiZipper = new MultiZip();
262    parseCmdArgs(args, multiZipper);
263
264    multiZipper.doArchiving();
265
266    logger_.debug("Exiting " + methodName);
267  }
268
269
270  /**  Parses the cmd line args into usefule class vars. */
271  private static void printUsage()
272  {
273    final String methodName = className_ + ": printUsage()";
274    logger_.debug("Entering " + methodName);
275
276    StringBuffer usage = new StringBuffer();
277    usage.append(LINE_SEPARATOR);
278    usage.append("Java MultiZIp - Copyright 2002 - Tom B. Gutwin, WebARTS Design");
279    usage.append(LINE_SEPARATOR);
280    usage.append(LINE_SEPARATOR);
281    usage.append("Usage details:");
282    usage.append(LINE_SEPARATOR);
283    usage.append("  java ca.bc.webarts.tools.MultiZip [options] ");
284    usage.append("file/dir(s)");
285    usage.append(LINE_SEPARATOR);
286    usage.append("    options:");
287    usage.append(LINE_SEPARATOR);
288    usage.append("      -h {--help}");
289    usage.append(LINE_SEPARATOR);
290    usage.append("      -a {--archive} dir,tar,zip,tgz          DEFAULT=zip");
291    usage.append(LINE_SEPARATOR);
292    usage.append("      -c {--compression} none,zip,gzip,bzip2  DEFAULT=zip");
293    usage.append(LINE_SEPARATOR);
294    usage.append("      -l {--compressionLevel} 0-9             DEFAULT=9");
295    usage.append(LINE_SEPARATOR);
296    usage.append("      -m {--maxarchive} an_integer            DEFAULT=650");
297    usage.append(LINE_SEPARATOR);
298    usage.append("      -v {--verbose}                          ");
299    usage.append("DEFAULT=not verbose");
300    usage.append(LINE_SEPARATOR);
301    usage.append("      -q {--quiet}                            ");
302    usage.append("DEFAULT=not quiet");
303    usage.append(LINE_SEPARATOR);
304    usage.append("      -Q {--reallyQuiet}                      ");
305    usage.append("DEFAULT=not reallyQuiet");
306    usage.append(LINE_SEPARATOR);
307    usage.append("      -o {--output} filename");
308    usage.append(LINE_SEPARATOR);
309    usage.append(LINE_SEPARATOR);
310    usage.append("   EXAMPLE:");
311    usage.append(LINE_SEPARATOR);
312    usage.append("    java ca.bc.webarts.tools.MultiZip -a dir -c bzip2 -l 9 ");
313    usage.append("-o /home/joeBlo/staging /home/joBlo/src");
314    usage.append(LINE_SEPARATOR);
315    usage.append(LINE_SEPARATOR);
316    usage.append("If the destination file/directory is not specified - the ");
317    usage.append("files are compressed in the ");
318    usage.append(LINE_SEPARATOR);
319    usage.append("same dir as the specified source dir. The compressed files ");
320    usage.append("will take the associated ");
321    usage.append(LINE_SEPARATOR);
322    usage.append("file extension (gz, zip, bz2, tar).");
323    System.out.println(usage.toString());
324
325    logger_.debug("Exiting " + methodName);
326  }
327
328
329  /**
330   *  Parses the cmd line args into usefule class vars.
331   *
332   * @param  args         Description of the Parameter
333   * @param  multiZipper  Description of the Parameter
334   */
335  private static void parseCmdArgs(String args[], MultiZip multiZipper)
336  {
337    final String methodName =
338        className_ + ": parseCmdArgs(String [], MultiZip)";
339    logger_.debug("Entering " + methodName);
340
341    CmdLineParser parser = new CmdLineParser();
342    CmdLineParser.Option help = parser.addBooleanOption('h', "help");
343    CmdLineParser.Option verbose = parser.addBooleanOption('v', "verbose");
344    CmdLineParser.Option verboseDebug =
345        parser.addBooleanOption('V', "verboseDebug");
346    CmdLineParser.Option quiet = parser.addBooleanOption('q', "quiet");
347    CmdLineParser.Option reallyQuiet =
348        parser.addBooleanOption('Q', "reallyQuiet");
349    CmdLineParser.Option output = parser.addStringOption('o', "output");
350    CmdLineParser.Option archive = parser.addStringOption('a', "archive");
351    CmdLineParser.Option compression =
352        parser.addStringOption('c', "compression");
353    CmdLineParser.Option compressionLevel =
354        parser.addIntegerOption('l', "compressionLevel");
355    CmdLineParser.Option maxarchive =
356        parser.addIntegerOption('m', "maxarchive");
357
358    try
359    {
360      parser.parse(args);
361    }
362    catch (CmdLineParser.OptionException e)
363    {
364      logger_.error(e.getMessage());
365      printUsage();
366      System.exit(2);
367    }
368
369    // Extract the values entered for the various options -- if the
370    // options were not specified, the corresponding values will be
371    // null.
372    if (parser.getOptionValue(help) != null)
373    {
374      printUsage();
375    }
376    if (parser.getOptionValue(reallyQuiet) != null)
377    {
378      multiZipper.setReallyQuiet(
379          ((Boolean) parser.getOptionValue(reallyQuiet)).booleanValue());
380    }
381    if (parser.getOptionValue(quiet) != null)
382    {
383      multiZipper.setQuiet(
384          ((Boolean) parser.getOptionValue(quiet)).booleanValue());
385    }
386    if (parser.getOptionValue(verbose) != null)
387    {
388      multiZipper.setVerbose(
389          ((Boolean) parser.getOptionValue(verbose)).booleanValue());
390    }
391    if (parser.getOptionValue(verboseDebug) != null)
392    {
393      logger_.setLevel(Level.DEBUG);
394    }
395    if (parser.getOptionValue(compression) != null)
396    {
397      multiZipper.setArchiveType((String) parser.getOptionValue(compression));
398    }
399    if (parser.getOptionValue(output) != null)
400    {
401      multiZipper.setOutput((String) parser.getOptionValue(output));
402    }
403    if (parser.getOptionValue(archive) != null)
404    {
405      multiZipper.setArchiveType((String) parser.getOptionValue(archive));
406    }
407    if (parser.getOptionValue(compression) != null)
408    {
409      multiZipper.setCompressionType(
410          (String) parser.getOptionValue(compression));
411    }
412    if (parser.getOptionValue(compressionLevel) != null)
413    {
414      multiZipper.setCompressionLevel(
415          ((Integer) parser.getOptionValue(compressionLevel)).shortValue());
416    }
417    if (parser.getOptionValue(maxarchive) != null)
418    {
419      multiZipper.setMaxArchiveSize(
420          ((Integer) parser.getOptionValue(maxarchive)).shortValue());
421    }
422
423    // For testing purposes, we just print out the option values
424    logger_.debug("verbose_: " + multiZipper.getVerbose());
425    logger_.debug("quiet_: " + multiZipper.getQuiet());
426    logger_.debug("reallyQuiet_: " + multiZipper.getReallyQuiet());
427    logger_.debug("archive: " + multiZipper.getArchiveType());
428    logger_.debug("compression: " + multiZipper.getCompressionType());
429    logger_.debug("compressionLevel: " + multiZipper.getCompressionLevel());
430    logger_.debug("output: " + multiZipper.getOutput());
431    logger_.debug("maxarchive: " + multiZipper.getMaxArchiveSize());
432
433    // Extract the trailing command-line arguments in the
434    String[] otherArgs = parser.getRemainingArgs();
435    logger_.debug("remaining args: ");
436    for (int i = 0; i < otherArgs.length; ++i)
437    {
438      logger_.debug(otherArgs[i]);
439    }
440
441    if (otherArgs.length == 0)
442    {
443      // ERROR
444      logger_.error("ERROR:");
445      logger_.error("   No input files specified.");
446      printUsage();
447      System.exit(2);
448    }
449    else
450    {
451      //Input files
452      Vector tmpVector = new Vector();
453      String fileSep = System.getProperty("file.separator");
454      String userDir = System.getProperty("user.dir");
455      StringBuffer newInput = null;
456      for (short i = 0; i < otherArgs.length; ++i)
457      {
458        // first confirm we ar dealing with an absolute path
459        if (!(otherArgs[i].startsWith(fileSep) ||
460            otherArgs[i].substring(1).startsWith(":")))
461        {
462          //  it is a relative path so... construct the absolute path
463          logger_.info("Specified Input File path appears to be a relative path.");
464          newInput = new StringBuffer(userDir);
465          if (!userDir.endsWith(fileSep))
466          {
467            newInput.append(fileSep);
468          }
469          newInput.append(otherArgs[i]);
470          otherArgs[i] = Util.removeParentRelativeReference(newInput.toString());
471        }
472
473        tmpVector.add(otherArgs[i]);
474      }
475      multiZipper.setInput(tmpVector);
476    }
477
478    // now check and correct the output_ setting depending on the comp and
479    // archive types
480    if (!multiZipper.validateOutputLocation())
481    {
482      // ERROR
483      logger_.error("ERROR:");
484      logger_.error("   Output file specified in a NON-writable dir or " +
485          "incorrectly specified.");
486      printUsage();
487      System.exit(2);
488    }
489
490    logger_.debug("Exiting " + methodName);
491  }
492
493
494
495  /**
496   *  The public set method to set the zippedOutputLocation_ class field.
497   *
498   * @param  zippedOutputLocation  is the value to use to set the class field
499   *      to.
500   */
501  public void setZippedOutputLocation(String zippedOutputLocation)
502  {
503    this.zippedOutputLocation_ = zippedOutputLocation_;
504  }
505
506
507  /**
508   *  The public get method to return the zippedOutputLocation_ class field.
509   *
510   * @return    the class field: zippedOutputLocation_
511   */
512  public String getZippedOutputLocation()
513  {
514    return zippedOutputLocation_;
515  }
516
517
518  /**
519   *  The public set method to set the input_ class field.
520   *
521   * @param  input  is the value to use to set the class field to.
522   */
523  public void setInput(String[] input)
524  {
525    final String methodName = className_ + ": setInput(String [])";
526    logger_.debug("Entering " + methodName);
527
528    input_ = null;
529    input_ = new Vector();
530    if (input != null)
531    {
532      for (short i = 0; i < input.length; ++i)
533      {
534        input_.add(input[i]);
535      }
536    }
537
538    logger_.debug("Exiting " + methodName);
539  }
540
541
542  /**
543   *  The public set method to set the input_ class field.
544   *
545   * @param  input  is the Vector of valuese to use to set the class field to.
546   */
547  public void setInput(Vector input)
548  {
549    final String methodName = className_ + ": setInput(Vector)";
550    logger_.debug("Entering " + methodName);
551
552    this.input_ = input;
553
554    logger_.debug("Exiting " + methodName);
555  }
556
557
558  /**
559   *  The public get method to return the input_ class field.
560   *
561   * @return    the class field: input_
562   */
563  public Vector getInput()
564  {
565    final String methodName = className_ + ": getInput()";
566    logger_.debug("Entering " + methodName);
567
568    logger_.debug("Exiting " + methodName);
569    return input_;
570  }
571
572
573  /**
574   *  The public set method to set the output_ class field.
575   *
576   * @param  output  The new output value
577   */
578  public void setOutput(String output)
579  {
580    final String methodName = className_ + ": setOutput(String)";
581    logger_.debug("Entering " + methodName);
582
583    this.output_ = output;
584
585    logger_.debug("Exiting " + methodName);
586  }
587
588
589  /**
590   *  The public get method to return the output_ class field.
591   *
592   * @return    the class field: output_
593   */
594  public String getOutput()
595  {
596    final String methodName = className_ + ": getOutput()";
597    logger_.debug("Entering " + methodName);
598
599    logger_.debug("Exiting " + methodName);
600    return output_;
601  }
602
603
604  /**
605   *  The public set method to set the compressionType_ class field.
606   *
607   * @param  compressionType  is the value to use to set the class field to.
608   */
609  public void setCompressionType(String compressionType)
610  {
611    final String methodName = className_ + ": setCompressionType(String)";
612    logger_.debug("Entering " + methodName);
613
614    this.compressionType_ = 0;
615    if (compressionType.trim().toLowerCase().equals("zip"))
616    {
617      this.compressionType_ = ZIP_COMPRESSION;
618    }
619    else if (compressionType.trim().toLowerCase().equals("gzip"))
620    {
621      this.compressionType_ = GZIP_COMPRESSION;
622    }
623    else if (compressionType.trim().toLowerCase().equals("bzip2"))
624    {
625      this.compressionType_ = BZIP2_COMPRESSION;
626    }
627    else if (compressionType.trim().toLowerCase().equals("none"))
628    {
629      this.compressionType_ = NO_COMPRESSION;
630    }
631    else if (compressionType.trim().toLowerCase().equals("no"))
632    {
633      this.compressionType_ = NO_COMPRESSION;
634    }
635
636    logger_.debug("Exiting " + methodName);
637  }
638
639
640  /**
641   *  The public set method to set the compressionType_ class field.
642   *
643   * @param  compressionType  is the value to use to set the class field to.
644   */
645  public void setCompressionType(short compressionType)
646  {
647    final String methodName = className_ + ": setCompressionType(short)";
648    logger_.debug("Entering " + methodName);
649
650    this.compressionType_ = compressionType;
651
652    logger_.debug("Exiting " + methodName);
653  }
654
655
656  /**
657   *  The public get method to return the compressionType_ class field.
658   *
659   * @return    the class field: compressionType_
660   */
661  public short getCompressionType()
662  {
663    final String methodName = className_ + ": getCompressionType()";
664    logger_.debug("Entering " + methodName);
665
666    logger_.debug("Exiting " + methodName);
667    return compressionType_;
668  }
669
670
671  /**
672   *  The public set method to set the compressionType_ class field.
673   *
674   * @param  archiveType  The new archiveType value
675   */
676  public void setArchiveType(String archiveType)
677  {
678    final String methodName = className_ + ": setArchiveType(String)";
679    logger_.debug("Entering " + methodName);
680
681    this.archiveType_ = 0;
682    if (archiveType.trim().toLowerCase().equals("zip"))
683    {
684      this.archiveType_ = ZIP_ARCHIVE;
685    }
686    else if (archiveType.trim().toLowerCase().equals("tar"))
687    {
688      this.archiveType_ = TAR_ARCHIVE;
689    }
690    else if (archiveType.trim().toLowerCase().equals("dir"))
691    {
692      this.archiveType_ = DIR_ARCHIVE;
693    }
694    else if (archiveType.trim().toLowerCase().equals("tgz"))
695    {
696      this.archiveType_ = TGZ_ARCHIVE;
697    }
698
699    logger_.debug("Exiting " + methodName);
700  }
701
702
703  /**
704   *  The public set method to set the archiveType_ class field.
705   *
706   * @param  archiveType  is the value to use to set the class field to.
707   */
708  public void setArchiveType(short archiveType)
709  {
710    final String methodName = className_ + ": setArchiveType(short)";
711    logger_.debug("Entering " + methodName);
712
713    this.archiveType_ = archiveType_;
714
715    logger_.debug("Exiting " + methodName);
716  }
717
718
719  /**
720   *  The public get method to return the archiveType_ class field.
721   *
722   * @return    the class field: archiveType_
723   */
724  public short getArchiveType()
725  {
726    final String methodName = className_ + ": getArchiveType()";
727    logger_.debug("Entering " + methodName);
728
729    logger_.debug("Exiting " + methodName);
730    return archiveType_;
731  }
732
733
734  /**
735   *  The public set method to set the reallyQuiet_ class field.
736   *
737   * @param  reallyQuiet  is the value to use to set the class field to.
738   */
739  public void setReallyQuiet(boolean reallyQuiet)
740  {
741    final String methodName = className_ + ": setReallyQuiet(boolean)";
742    logger_.debug("Entering " + methodName);
743
744    this.reallyQuiet_ = reallyQuiet;
745    logger_.setLevel(Level.FATAL);
746
747    logger_.debug("Exiting " + methodName);
748  }
749
750
751  /**
752   *  The public get method to return the reallyQuiet_ class field.
753   *
754   * @return    the class field: reallyQuiet_
755   */
756  public boolean getReallyQuiet()
757  {
758    final String methodName = className_ + ": getReallyQuiet()";
759    logger_.debug("Entering " + methodName);
760
761    logger_.debug("Exiting " + methodName);
762    return reallyQuiet_;
763  }
764
765
766  /**
767   *  The public set method to set the verbose_ class field.
768   *
769   * @param  verbose  is the value to use to set the class field to.
770   */
771  public void setVerbose(boolean verbose)
772  {
773    final String methodName = className_ + ": setVerbose(boolean)";
774    logger_.debug("Entering " + methodName);
775
776    this.verbose_ = verbose_;
777    logger_.setLevel(Level.INFO);
778    logger_.debug("Exiting " + methodName);
779  }
780
781
782  /**
783   *  The public get method to return the verbose_ class field.
784   *
785   * @return    the class field: verbose_
786   */
787  public boolean getVerbose()
788  {
789    final String methodName = className_ + ": getVerbose()";
790    logger_.debug("Entering " + methodName);
791
792    logger_.debug("Exiting " + methodName);
793    return verbose_;
794  }
795
796
797  /**
798   *  Gets the quiet_ field. Which specifies how much user feedback is provided
799   *
800   * @return    The quiet_ value
801   */
802  public boolean getQuiet()
803  {
804    final String methodName = className_ + ": getQuiet()";
805    logger_.debug("Entering " + methodName);
806
807    logger_.debug("Exiting " + methodName);
808    return quiet_;
809  }
810
811
812  /**
813   *  Sets the quiet_ field. Which specifies how much user feedback is provided
814   *
815   * @param  quiet  The new quiet_ value
816   */
817  public void setQuiet(boolean quiet)
818  {
819    final String methodName = className_ + ": setQuiet(boolean)";
820    logger_.debug("Entering " + methodName);
821
822    this.quiet_ = quiet;
823    logger_.setLevel(Level.ERROR);
824
825    logger_.debug("Exiting " + methodName);
826  }
827
828
829  /**
830   *  Sets the maxArchiveSize_ attribute of the MultiZip object
831   *
832   * @param  maxArchiveSize  The new maxArchiveSize value
833   */
834  public void setMaxArchiveSize(int maxArchiveSize)
835  {
836    final String methodName = className_ + ": setMaxArchiveSize(int)";
837    logger_.debug("Entering " + methodName);
838
839    this.maxArchiveSize_ = maxArchiveSize;
840
841    logger_.debug("Exiting " + methodName);
842  }
843
844
845  /**
846   *  Gets the maxArchiveSize_ attribute of the MultiZip object
847   *
848   * @return    The maxArchiveSize_ value
849   */
850  public int getMaxArchiveSize()
851  {
852    final String methodName = className_ + ": getMaxArchiveSize()";
853    logger_.debug("Entering " + methodName);
854
855    logger_.debug("Exiting " + methodName);
856    return maxArchiveSize_;
857  }
858
859
860  /**
861   *  Sets the compressionLevel_ attribute of the MultiZip object
862   *
863   * @param  compressionLevel  The new compressionLevel_ value
864   */
865  public void setCompressionLevel(int compressionLevel)
866  {
867    final String methodName = className_ + ": setCompressionLevel(int)";
868    logger_.debug("Entering " + methodName);
869
870    this.compressionLevel_ = compressionLevel;
871
872    logger_.debug("Exiting " + methodName);
873  }
874
875
876  /**
877   *  Gets the compressionLevel_ attribute of the MultiZip object
878   *
879   * @return    The compressionLevel_ value
880   */
881  public int getCompressionLevel()
882  {
883    final String methodName = className_ + ": getCompressionLevel()";
884    logger_.debug("Entering " + methodName);
885    logger_.debug("Exiting " + methodName);
886    return compressionLevel_;
887  }
888
889
890  /**
891   *  Initiates and begins the archival process. It is the method to call to
892   *  start things rolling.
893   *
894   * @return    The compressionLevel_ value
895   */
896  public short doArchiving()
897  {
898    final String methodName = className_ + ": doArchiving()";
899    logger_.debug("Entering " + methodName);
900
901    short retVal = 0;
902
903    long startTime = (new Date()).getTime();
904    // Pre-recurse the dirs into a flat list of files.
905    setInput(recurseInputIntoFiles(input_));
906
907    // Check if we can do this on one step instead of two
908    if (!oneStepArchive())
909    {
910      compressFiles();
911    }
912
913    //if (!oneStepCompress())
914    //{
915      archiveFiles();
916    //}
917
918    long duration = ((new Date()).getTime() - startTime) / 1000L;
919    long minutes = duration / 60L;
920    long seconds = duration - (60L * minutes);
921    logger_.info("Time to complete: " + minutes + " min. " + seconds + " sec.");
922    logger_.debug("Exiting " + methodName);
923    return retVal;
924  }
925
926
927  /**
928   *  It simply move a compressed file to the output dir for DIR type archives.
929   *
930   * @param  source  The filename to include in the archive.
931   */
932  public void moveFileToArchive(File source)
933  {
934    final String methodName = className_ + ": moveFileToArchive(File)";
935    logger_.debug("Entering " + methodName);
936
937    if (source != null)
938    {
939      if (source.isDirectory())
940      {
941        String srcFileNames[] = source.list();
942        for (int i = 0; i < srcFileNames.length; i++)
943        {
944          logger_.info("Recursing On Dir " + source.getName());
945          moveFileToArchive(new File(source.getAbsolutePath() + File.separator +
946              srcFileNames[i]));
947        }
948      }
949      else
950      {
951        File tmpNewFile = null;
952        if (currArchiveSize_+source.length() < maxArchiveSize_ *1000000)
953        {
954          logger_.info("Moving " + source.getName() + " to \n  -->" +
955              output_ + source.getAbsolutePath() + "\n");
956          Util.ensureFolderExists(new File(output_ + source.getAbsolutePath()).
957              getParentFile());
958          tmpNewFile = new File(output_ + source.getAbsolutePath());
959          if (source.renameTo(tmpNewFile))
960            currArchiveSize_ += tmpNewFile.length();
961        }
962        else
963        {
964          // up the archive dir name
965          String oldCntr = ""+archivefilenameCounter_;
966          archivefilenameCounter_++;
967          if(archivefilenameCounter_ == 1)
968            output_ = output_ + archivefilenameCounter_;
969          else
970          {
971            // scratch off the old counter number and replace it with the new
972            output_ = output_.substring(0,output_.length()-oldCntr.length()) +
973                      archivefilenameCounter_;
974            currArchiveSize_ = 0L;
975          }
976          // now move it
977          logger_.info("Moving " + source.getName() + " to \n  -->" +
978              output_ + source.getAbsolutePath() + "\n");
979          Util.ensureFolderExists(new File(output_ + source.getAbsolutePath()).
980              getParentFile());
981          tmpNewFile = new File(output_ + source.getAbsolutePath());
982          if (source.renameTo(tmpNewFile))
983            currArchiveSize_ += tmpNewFile.length();
984        }
985      }
986    }
987
988    logger_.debug("Exiting " + methodName);
989  }
990
991
992  /**
993   *  It simply copies a compressed file to the output dir for DIR type archives
994   *
995   * @param  source  The filename to include in the archive.
996   */
997  public void copyFileToArchive(File source)
998  {
999    final String methodName = className_ + ": copyFileToArchive(File)";
1000    logger_.debug("Entering " + methodName);
1001
1002    if (source != null)
1003    {
1004      if (source.isDirectory())
1005      {
1006        String srcFileNames[] = source.list();
1007        for (int i = 0; i < srcFileNames.length; i++)
1008        {
1009          logger_.info("Recursing On Dir " + source.getName());
1010          copyFileToArchive(new File(source.getAbsolutePath() + File.separator +
1011              srcFileNames[i]));
1012        }
1013      }
1014      else
1015      {
1016        logger_.info("Copying " + source.getName() + " to \n  -->" +
1017            output_ + source.getAbsolutePath() + "\n");
1018        Util.ensureFolderExists(new File(output_ + source.getAbsolutePath()).
1019            getParentFile());
1020        File newFile = new File(output_ + source.getAbsolutePath());
1021        try
1022        {
1023          FileInputStream fis = new FileInputStream(source);
1024          FileOutputStream fos = new FileOutputStream(newFile);
1025          long bytesToRead = source.length();
1026          int bufferSize = 512;
1027          byte[] buffer = new byte[bufferSize];
1028          int amountRead = 0;
1029          for (int i = 0; i < bytesToRead; i += amountRead)
1030          {
1031            try
1032            {
1033              amountRead = fis.read(buffer);
1034              if (amountRead == -1)
1035              {
1036                break;
1037              }
1038              fos.write(buffer);
1039            }
1040            catch (java.lang.IndexOutOfBoundsException boundsEx)
1041            {
1042              logger_.error("Cannot copy file to archive:");
1043              logger_.error("  " + source.getAbsolutePath() + " --> " +
1044                  newFile.getAbsolutePath());
1045              logger_.error("   i=" + i);
1046              logger_.error("   amountRead=" + amountRead);
1047              logger_.error("   bytesToRead=" + bytesToRead);
1048              break;
1049            }
1050          }
1051          fis.close();
1052          fos.close();
1053        }
1054        catch (IOException ioEx)
1055        {
1056          logger_.error("Cannot copy file to archive:");
1057          logger_.error("  " + source.getAbsolutePath() + " --> " +
1058              newFile.getAbsolutePath());
1059        }
1060      }
1061    }
1062
1063    logger_.debug("Exiting " + methodName);
1064  }
1065
1066
1067  /**
1068   *  It simply moves all the compressed files to the output dir for DIR type
1069   *  archives.
1070   */
1071  public void moveFilesToArchive()
1072  {
1073    final String methodName = className_ + ": moveFilesToArchive()";
1074    logger_.debug("Entering " + methodName);
1075
1076    if (input_ != null)
1077    {
1078      String compExtension = "";
1079      switch (getCompressionType())
1080      {
1081          case ZIP_COMPRESSION:
1082            compExtension = ".zip";
1083            break;
1084          case GZIP_COMPRESSION:
1085            compExtension = ".gz";
1086            break;
1087          case BZIP2_COMPRESSION:
1088            compExtension = ".bz2";
1089            break;
1090          case NO_COMPRESSION:
1091            break;
1092          default:
1093      }
1094
1095      logger_.info("Begining to Move " + compressedFilenames_.size() +
1096          " Files To Archive:");
1097      File tmpFile = null;
1098      for (int i = 0; i < compressedFilenames_.size(); i++)
1099      {
1100        tmpFile = new File(((String) compressedFilenames_.elementAt(i)).trim());
1101        moveFileToArchive(tmpFile);
1102      }
1103    }
1104
1105    logger_.debug("Exiting " + methodName);
1106  }
1107
1108
1109  /**
1110   *  It simply copies the compressed files to the output dir for DIR type
1111   *  archives.
1112   */
1113  public void copyFilesToArchive()
1114  {
1115    final String methodName = className_ + ": copyFilesToArchive()";
1116    logger_.debug("Entering " + methodName);
1117
1118    if (input_ != null)
1119    {
1120      String compExtension = "";
1121      switch (getCompressionType())
1122      {
1123          case ZIP_COMPRESSION:
1124            compExtension = ".zip";
1125            break;
1126          case GZIP_COMPRESSION:
1127            compExtension = ".gz";
1128            break;
1129          case BZIP2_COMPRESSION:
1130            compExtension = ".bz2";
1131            break;
1132          case NO_COMPRESSION:
1133            break;
1134          default:
1135      }
1136
1137      logger_.info("Begining to copy " + compressedFilenames_.size() +
1138          " Files To Archive:");
1139      File tmpFile = null;
1140      for (int i = 0; i < compressedFilenames_.size(); i++)
1141      {
1142        tmpFile = new File(((String) compressedFilenames_.elementAt(i)).trim());
1143        copyFileToArchive(tmpFile);
1144      }
1145    }
1146
1147    logger_.debug("Exiting " + methodName);
1148  }
1149
1150
1151  /**  It cleans up the compressed files by deleting them */
1152  public void removeCompressedFiles()
1153  {
1154    final String methodName = className_ + ": removeCompressedFiles()";
1155    logger_.debug("Entering " + methodName);
1156
1157    if (input_ != null)
1158    {
1159      String compExtension = "";
1160      switch (getCompressionType())
1161      {
1162          case ZIP_COMPRESSION:
1163            compExtension = ".zip";
1164            break;
1165          case GZIP_COMPRESSION:
1166            compExtension = ".gz";
1167            break;
1168          case BZIP2_COMPRESSION:
1169            compExtension = ".bz2";
1170            break;
1171          case NO_COMPRESSION:
1172            break;
1173          default:
1174      }
1175
1176      logger_.info("Begining to DELETE " + compressedFilenames_.size() +
1177          " Files.");
1178      File tmpFile = null;
1179      for (int i = 0; i < compressedFilenames_.size(); i++)
1180      {
1181        tmpFile = new File(((String) compressedFilenames_.elementAt(i)).trim());
1182        tmpFile.delete();
1183      }
1184    }
1185
1186    logger_.debug("Exiting " + methodName);
1187  }
1188
1189
1190  /**
1191   *  Encapsulates the zipping of file(s) individually into the class
1192   *  zippedOutputLocation_. THIS DOES NOT collect them together into an
1193   *  archive. It simply compresses the files into a *.zip file in the
1194   *  zippedOutputLocation_ dir.
1195   *
1196   * @param  source  A Vector of Strings holding the filenames to include in the
1197   *      zipped file.
1198   */
1199  public void zipFiles(Vector source)
1200  {
1201    final String methodName = className_ + ": zipFiles(Vector)";
1202    logger_.debug("Entering " + methodName);
1203
1204    if (source != null)
1205    {
1206      File tmpFile = null;
1207      File outZip = null;
1208      StringBuffer outLocation = new StringBuffer();
1209      String fileSep = File.separator;
1210      String foPath = null;
1211      for (int i = 0; i < source.size(); i++)
1212      {
1213        tmpFile = new File((String) source.elementAt(i));
1214        if (!tmpFile.isDirectory())
1215        {
1216          foPath = tmpFile.getAbsolutePath().trim();
1217          if (zippedOutputLocation_ == null)
1218          {
1219            zippedOutputLocation_ = "";
1220          }
1221          // use the spec'd location
1222          outLocation = new StringBuffer(zippedOutputLocation_);
1223          if (!zippedOutputLocation_.endsWith(fileSep) &&
1224              !foPath.startsWith(fileSep))
1225          {
1226            outLocation.append(fileSep);
1227          }
1228          outLocation.append(foPath);
1229          outLocation.append(".zip");
1230          logger_.info("Zipping " + foPath);
1231          outZip = new File(outLocation.toString());
1232          //ensureFolderExists(outZip.getParentFile());
1233          zipFile(tmpFile, outZip);
1234          tmpFile = null;
1235          outLocation = null;
1236        }
1237        else
1238        {
1239          zipFiles(tmpFile.listFiles());
1240        }
1241      }
1242    }
1243
1244    logger_.debug("Exiting " + methodName);
1245  }
1246
1247
1248  /**
1249   *  Encapsulates the gzipping of 1 file/dir in place.
1250   *
1251   * @param  source  The file to GZIP.
1252   * @return         the new length in bytes of the zipped file
1253   */
1254  public long gzipFile(File source)
1255  {
1256    final String methodName = className_ + ": gzipFile(File)";
1257    logger_.debug("Entering " + methodName);
1258    long retVal = 0L;
1259
1260    logger_.info(" GZIPPING " + source.getName());
1261    retVal += recursiveGZip(source);
1262
1263    logger_.debug("Exiting " + methodName);
1264    return retVal;
1265  }
1266
1267
1268  /**
1269   *  Encapsulates the gzipping of file(s) individually in place. THIS DOES NOT
1270   *  collect them together into an archive. It simply compresses the files into
1271   *  a *.bz2 file in the same dir as the source.
1272   *
1273   * @param  source  The files to include in the zipped file.
1274   * @return         the new length in bytes of the zipped file
1275   */
1276  public long gzipFiles(File[] source)
1277  {
1278    final String methodName = className_ + ": gzipFiles(File[])";
1279    logger_.debug("Entering " + methodName);
1280    long retVal = 0L;
1281
1282    for (int i = 0; i < source.length; i++)
1283    {
1284      retVal += gzipFile(new File(source[i].getAbsolutePath().trim()));
1285
1286      //watch for the Archive size limit when One Step Compress.
1287
1288    }
1289
1290    logger_.debug("Exiting " + methodName);
1291    return retVal;
1292  }
1293
1294
1295  /**
1296   *  Encapsulates the gzipping of file(s) individually in place. THIS DOES NOT
1297   *  collect them together into an archive. It simply compresses the files into
1298   *  a *.zip file in the same dir as the source.
1299   *
1300   * @param  source  The filenames to include in the zipped file.
1301   * @return         the new length in bytes of the zipped file
1302   */
1303  public long gzipFiles(Vector source)
1304  {
1305    final String methodName = className_ + ": gzipFiles(Vector)";
1306    logger_.debug("Entering " + methodName);
1307    long retVal = 0L;
1308
1309    if (source != null)
1310    {
1311      File[] tmpArray = new File[source.size()];
1312      for (int i = 0; i < source.size(); i++)
1313      {
1314        tmpArray[i] = new File((String) source.elementAt(i));
1315      }
1316      retVal += gzipFiles(tmpArray);
1317    }
1318
1319    logger_.debug("Exiting " + methodName);
1320    return retVal;
1321  }
1322
1323
1324  /**
1325   *  Encapsulates the bzip2ping of file(s) individually in place. THIS DOES NOT
1326   *  collect them together into an archive. It simply compresses the files into
1327   *  a *.bz2 file in the same dir as the source.
1328   *
1329   * @param  source  The filenames to include in the zipped file.
1330   * @return         the new length in bytes of the zipped file
1331   */
1332  public long bzip2Files(Vector source)
1333  {
1334    final String methodName = className_ + ": bzip2Files(Vector)";
1335    logger_.debug("Entering " + methodName);
1336    long retVal = 0L;
1337
1338    if (source != null)
1339    {
1340      File[] tmpArray = new File[source.size()];
1341      for (int i = 0; i < source.size(); i++)
1342      {
1343        tmpArray[i] = new File((String) source.elementAt(i));
1344      }
1345      retVal += bzip2Files(tmpArray);
1346    }
1347
1348    logger_.debug("Exiting " + methodName);
1349    return retVal;
1350  }
1351
1352
1353  /**
1354   *  Encapsulates the bzip2ping of 1 file/dir in place.
1355   *
1356   * @param  source  The file to GZIP.
1357   * @return         the new length in bytes of the zipped file
1358   */
1359  public long bzip2File(File source)
1360  {
1361    final String methodName = className_ + ": bzip2File(File)";
1362    logger_.debug("Entering " + methodName);
1363    long retVal = 0L;
1364
1365    logger_.info(" BZIP2ING " + source.getAbsolutePath());
1366    retVal += recursiveBzip2(source);
1367
1368    logger_.debug("Exiting " + methodName);
1369    return retVal;
1370  }
1371
1372
1373  /**
1374   *  Encapsulates the bzip2ping of file(s) individually in place. THIS DOES NOT
1375   *  collect them together into an archive. It simply compresses the files into
1376   *  a *.bz2 file in the same dir as the source.
1377   *
1378   * @param  source  The files to include in the zipped file.
1379   * @return         the new length in bytes of the zipped file
1380   */
1381  public long bzip2Files(File[] source)
1382  {
1383    final String methodName = className_ + ": bzip2Files(File[])";
1384    logger_.debug("Entering " + methodName);
1385    long retVal = 0L;
1386
1387    for (int i = 0; i < source.length; i++)
1388    {
1389      retVal += bzip2File(new File(source[i].getAbsolutePath().trim()));
1390    }
1391
1392    logger_.debug("Exiting " + methodName);
1393    return retVal;
1394  }
1395
1396
1397  /**
1398   *  Encapsulates the zipping of an individual file into the specified
1399   *  destination file.
1400   *
1401   * @param  source       The files to include in the zipped file.
1402   * @param  destination  The destination zip file location.
1403   */
1404  public void zipFile(File source, File destination)
1405  {
1406    final String methodName = className_ + ": zipFile(File, File)";
1407    logger_.debug("Entering " + methodName);
1408
1409    File[] tmpArray = new File[1];
1410    tmpArray[0] = source;
1411    if (zos_ != null)
1412    {
1413      try
1414      {
1415        zos_.close();
1416      }
1417      catch (java.io.IOException ioe)
1418      {
1419      }
1420      zipfile_ = null;
1421    }
1422    archivefilenameCounter_ = 0;
1423    zipFiles(tmpArray, destination);
1424
1425    logger_.debug("Exiting " + methodName);
1426  }
1427
1428
1429  /**
1430   *  Encapsulates the zipping of file(s) individually into the class
1431   *  zippedOutputLocation_. THIS DOES NOT collect them together into an
1432   *  archive. It simply compresses the files into a *.zip file in the
1433   *  zippedOutputLocation_ dir.
1434   *
1435   * @param  source  The files to include in the zipped file.
1436   */
1437  public void zipFiles(File[] source)
1438  {
1439    final String methodName = className_ + ": zipFiles(File[])";
1440    logger_.debug("Entering " + methodName);
1441
1442    if (source != null)
1443    {
1444      File tmpFile = null;
1445      File outZip = null;
1446      StringBuffer outLocation = new StringBuffer();
1447      String fileSep = File.separator;
1448      String foPath = null;
1449      for (int i = 0; i < source.length; i++)
1450      {
1451        tmpFile = source[i];
1452        if (!tmpFile.isDirectory())
1453        {
1454          foPath = tmpFile.getAbsolutePath().trim();
1455          if (zippedOutputLocation_ == null)
1456          {
1457            zippedOutputLocation_ = "";
1458          }
1459          // use the spec'd location
1460          outLocation = new StringBuffer(zippedOutputLocation_);
1461          if (!zippedOutputLocation_.endsWith(fileSep) &&
1462              !foPath.startsWith(fileSep))
1463          {
1464            outLocation.append(fileSep);
1465          }
1466          outLocation.append(foPath);
1467          outLocation.append(".zip");
1468          logger_.info("Zipping " + foPath);
1469          outZip = new File(outLocation.toString());
1470          //ensureFolderExists(outZip.getParentFile());
1471          zipFile(tmpFile, outZip);
1472          tmpFile = null;
1473          outLocation = null;
1474        }
1475        else
1476        {
1477          zipFiles(tmpFile.listFiles());
1478        }
1479      }
1480    }
1481
1482    logger_.debug("Exiting " + methodName);
1483  }
1484
1485
1486  /**
1487   *  Encapsulates the zipping of 1 file individually in place. THIS DOES NOT
1488   *  collect them together into an archive. It simply compresses the files into
1489   *  a *.zip file in the same dir as the source.
1490   *
1491   * @param  source  The files to include in the zipped file.
1492   */
1493  public void zipFile(File source)
1494  {
1495    final String methodName = className_ + ": zipFiles(File)";
1496    logger_.debug("Entering " + methodName);
1497
1498    File[] tmpArray = new File[1];
1499    tmpArray[0] = source;
1500    if (zos_ != null)
1501    {
1502      try
1503      {
1504        zos_.close();
1505      }
1506      catch (java.io.IOException ioe)
1507      {
1508      }
1509      zipfile_ = null;
1510    }
1511    archivefilenameCounter_ = 0;
1512    zipFiles(tmpArray, new File(source.getAbsolutePath().trim() + ".zip"));
1513
1514    logger_.debug("Exiting " + methodName);
1515  }
1516
1517
1518  /**
1519   *  Encapsulates the zipping of file(s) into a zip archive.
1520   *
1521   * @param  source       A Vector of filenames to include in the zipped file.
1522   * @param  destination  The resultant zipped archive.
1523   */
1524  public void zipFiles(Vector source, File destination)
1525  {
1526    final String methodName = className_ + ": zipFiles(Vector, File)";
1527    logger_.debug("Entering " + methodName);
1528
1529    if (source != null)
1530    {
1531      File[] tmpArray = new File[source.size()];
1532      for (int i = 0; i < source.size(); i++)
1533      {
1534        tmpArray[i] = new File((String) source.elementAt(i));
1535      }
1536      zipFiles(tmpArray, destination);
1537    }
1538
1539    logger_.debug("Exiting " + methodName);
1540  }
1541
1542
1543  /**
1544   *  Encapsulates the zipping of file(s) into a zip archive.
1545   *
1546   * @param  source       The files to include in the zipped file.
1547   * @param  destination  The resultant zipped archive.
1548   */
1549  public void zipFiles(File[] source, File destination)
1550  {
1551    final String methodName = className_ + ": zipFiles(File[], File)";
1552    logger_.debug("Entering " + methodName);
1553
1554    boolean initOkay = false;
1555    try
1556    {
1557      long startTime = (new Date()).getTime();
1558      String destFilename = destination.getAbsolutePath();
1559      if (!destFilename.toLowerCase()
1560          .substring(destFilename.length() - 4,
1561          destFilename.length())
1562          .equalsIgnoreCase(".zip"))
1563      {
1564        destFilename += ".zip";
1565      }
1566      destination = new File(destFilename);
1567      zipfile_ = null;
1568      initOkay = initZipOutputStream(destination);
1569      //logger_.warn("Starting The ZIP Archive: " + destFilename);
1570      // String srcFileNames[] = {source.getName()};
1571      //File arrFile[] = {source};
1572      if (initOkay && source.length > 0)
1573      {
1574        for (int i = 0; i < source.length; i++)
1575        {
1576          recursiveZip(source[i]);
1577        }
1578        //Calling recursive function
1579        zos_.close();
1580
1581        long duration = ((new Date()).getTime() - startTime) / 1000L;
1582        long minutes = duration / 60L;
1583        long seconds = duration - (60L * minutes);
1584        logger_.info(destination.getName() +
1585            " file created successfully with "+source.length + " files.");
1586        logger_.info("Time to complete: " + minutes + ":" + seconds);
1587      }
1588      else
1589      {
1590        logger_.error("There is no file in the specified source.");
1591      }
1592    }
1593    catch (java.util.zip.ZipException ze)
1594    {
1595      logger_.error("Exception occured in zipping file. Details :\n" +
1596          ze.getMessage());
1597    }
1598    catch (java.io.FileNotFoundException fnfe)
1599    {
1600      logger_.error("File is missing. Details :" + fnfe.getMessage());
1601    }
1602    catch (java.io.IOException ioe)
1603    {
1604      logger_.error("Input / Output problem. Details :\n" + ioe.getMessage());
1605    }
1606
1607    logger_.debug("Exiting " + methodName);
1608  }
1609
1610
1611  /**
1612   *  Encapsulates the taring of file(s) into a TAR archive.
1613   *
1614   * @param  source     A Vector of the filenames to include in the tar file.
1615   * @param  outputTar  The tar filename.
1616   * @return            Description of the Return Value
1617   */
1618  public boolean tarFiles(Vector source, String outputTar)
1619  {
1620    final String methodName = className_ + ": tarFiles(Vector, String)";
1621    logger_.debug("Entering " + methodName);
1622
1623    boolean retVal = false;
1624    if (source != null)
1625    {
1626      String[] tmpArray = new String[source.size()];
1627      for (int i = 0; i < source.size(); i++)
1628      {
1629        tmpArray[i] = (String) (source.elementAt(i));
1630      }
1631      tarFiles(tmpArray, outputTar);
1632    }
1633    logger_.debug("Exiting " + methodName);
1634    return retVal;
1635  }
1636
1637
1638  /**
1639   *  Encapsulates the taring of the compressed Files dir into a TAR archive.
1640   *
1641   * @param  outputTar  The tar filename.
1642   * @return            Description of the Return Value
1643   */
1644  public boolean tarCompressedFilesDir(String outputTar)
1645  {
1646    final String methodName = className_ + ": tarCompressedFilesDir(String)";
1647    logger_.debug("Entering " + methodName);
1648    boolean retVal = false;
1649
1650    //int startSpot = zippedOutputLocation_.length();
1651    Vector tmpVector = new Vector();
1652    for (int j = 0; j < compressedFilenames_.size(); j++)
1653    {
1654      tmpVector.add(((String) compressedFilenames_.elementAt(j)));//.substring(startSpot));
1655    }
1656    tarFiles(tmpVector, outputTar);
1657
1658    logger_.debug("Exiting " + methodName);
1659    return retVal;
1660  }
1661
1662
1663  /**
1664   *  Encapsulates the taring of file(s) into a TAR archive.
1665   *
1666   * @param  source     The files to include in the tar file.
1667   * @param  outputTar  The tar filename.
1668   * @return            Description of the Return Value
1669   */
1670  public boolean tarFiles(String[] source, String outputTar)
1671  {
1672    final String methodName = className_ + ": tarFiles(String[], String)";
1673    logger_.debug("Entering " + methodName);
1674
1675    boolean retVal = false;
1676    if (source != null)
1677    {
1678      File tmpFile = null;
1679      try
1680      {
1681        logger_.debug("Tar Archive will be: " + outputTar);
1682        TarArchive tarArchive = new TarArchive(new FileOutputStream(outputTar));
1683
1684        String parentDir = "";
1685        TarEntry tarEntry = null;
1686        String relPath = "";
1687        String absPath = "";
1688        int tmpDirOffset = 0;
1689        for (int i = 0; i < source.length; i++)
1690        {
1691          absPath = source[i];
1692          logger_.debug("  - preparing to tar: " + absPath);
1693          relPath = Util.removeParentRelativeReference(
1694              Util.absoluteToPwdRelativePath(source[i]));
1695          absPath = Util.removeParentRelativeReference(
1696              source[i]);
1697          tmpFile = new File(absPath);
1698          logger_.debug("  - preparing to tar: " + absPath);
1699          parentDir = tmpFile.getParent();
1700          if (parentDir != null)
1701          {
1702            tmpFile = new File(parentDir);
1703            logger_.debug("  - ...Adding Directory " + parentDir);
1704            tarEntry = new TarEntry(tmpFile);
1705            tmpDirOffset = parentDir.indexOf(tmpDirName_);
1706            if (tmpDirOffset != -1)
1707            {
1708              parentDir = parentDir.substring(
1709                  tmpDirOffset + tmpDirName_.length() + 1);
1710            }
1711            logger_.debug("   ......As " + parentDir);
1712            tarEntry.setName(parentDir);
1713            tarArchive.writeEntry(tarEntry, false);
1714          }
1715          logger_.info("  ...Adding " + absPath);
1716          tmpFile = new File(absPath);
1717          tarEntry = new TarEntry(tmpFile);
1718          tmpDirOffset = absPath.indexOf(tmpDirName_);
1719          if (tmpDirOffset != -1)
1720          {
1721            relPath = absPath.substring(
1722                tmpDirOffset + tmpDirName_.length() + 1);
1723          }
1724          tarEntry.setName(relPath);
1725          logger_.debug("  - ...As " + relPath);
1726          tarArchive.writeEntry(tarEntry, false);
1727          tmpFile = null;
1728        }
1729        tarArchive.closeArchive();
1730        retVal = true;
1731      }
1732      catch (java.lang.NullPointerException npe)
1733      {
1734        logger_.error("Internal MultiZip Error. Details :", npe);
1735
1736      }
1737      catch (java.io.FileNotFoundException fnfe)
1738      {
1739        logger_.error("Cannot init File:" + outputTar +
1740            ". \nDetails :\n" + fnfe.getMessage());
1741      }
1742      catch (java.io.IOException ioEx)
1743      {
1744        logger_.error("Cannot complete the tar File:" + outputTar +
1745            ". \nDetails :", ioEx);
1746
1747      }
1748    }
1749
1750    logger_.debug("Exiting " + methodName);
1751    return retVal;
1752  }
1753
1754
1755  /**
1756   *  Compresses and saves the passed file parameter to a gzip file.
1757   *
1758   * @param  src              The File to gzip up - it can be a dir.
1759   * @return                  the new length in bytes of the zipped file
1760   * @exception  IOException  Description of the Exception
1761   */
1762  public long writeToGZip(File src)
1763    throws IOException
1764  {
1765    final String methodName = className_ + ": writeToGZip(File)";
1766    logger_.debug("Entering " + methodName);
1767    long retVal = 0L;
1768
1769    retVal = writeToGZip(src, src.getAbsolutePath().trim() + ".gz");
1770
1771    logger_.debug("Exiting " + methodName);
1772    return retVal;
1773  }
1774
1775
1776  /**
1777   *  Compresses and saves the passed file parameter to a gzip file.
1778   *
1779   * @param  src              The File to gzip up - it can be a dir.
1780   * @param  dest             The location of the gzip'd file.
1781   * @return                  the new length in bytes of the zipped file
1782   * @exception  IOException  Description of the Exception
1783   */
1784  public long writeToGZip(File src, String dest)
1785    throws IOException
1786  {
1787    final String methodName = className_ + ": writeToGZip(File, String)";
1788    logger_.debug("Entering " + methodName);
1789    long retVal = 0L;
1790
1791    // This function writes the data in to GZipoutput Stream.
1792    byte b[] = new byte[512];
1793    if (!src.isDirectory())
1794    {
1795      logger_.debug("Attempting to Init the GZip Out Stream: " + dest);
1796      File destFile = new File(dest);
1797      if (destFile != null && initGZIPOutputStream(destFile))
1798      {
1799        int len = 0;
1800        FileInputStream is = new FileInputStream(src);
1801        while ((len = is.read(b)) != -1)
1802        {
1803          ((GZIPOutputStream) zos_).write(b, 0, len);
1804        }
1805        is.close();
1806        logger_.debug("Completed GZIP : " + dest);
1807        retVal = destFile.length();
1808        compressedFilenames_.add(dest);
1809        is = null;
1810        ((GZIPOutputStream) zos_).close();
1811        zos_ = null;
1812      }
1813    }
1814
1815    logger_.debug("Exiting " + methodName);
1816    return retVal;
1817  }
1818
1819
1820  /**
1821   *  Compresses and saves the passed file parameter to a zip file.
1822   *
1823   * @param  src                        The File to zip up - it can be a dir.
1824   * @exception  DataFormatException    Description of the Exception
1825   * @exception  ZipException           Description of the Exception
1826   * @exception  FileNotFoundException  Description of the Exception
1827   * @exception  IOException            Description of the Exception
1828   */
1829  public void writeToZip(File src)
1830    throws DataFormatException, ZipException, FileNotFoundException, IOException
1831  {
1832    final String methodName = className_ + ": writeToZip(File)";
1833    logger_.debug("Entering " + methodName);
1834
1835    // This function write s the data in to Zipoutput Stream.
1836    byte b[] = new byte[512];
1837    // clean off the drive letter and '/'
1838    String entry = src.toString().trim();
1839    if (entry.startsWith(":" + File.separator, 1))
1840    {
1841      entry = src.toString().substring(3);
1842    }
1843    else if (entry.startsWith(File.separator))
1844    {
1845      entry = src.toString().substring(1);
1846    }
1847
1848    // Make sure dirs hava a trailing separator char so it is represented
1849    // in the Zip correctly
1850    if (src.isDirectory() && !entry.endsWith(File.separator))
1851    {
1852      entry += File.separator;
1853    }
1854
1855    entry = Util.tokenReplace(entry, "\\", "/");
1856    ZipEntry ze = new ZipEntry(entry);
1857    ((ZipOutputStream) zos_).putNextEntry(ze);
1858    if (!src.isDirectory())
1859    {
1860      int len = 0;
1861      FileInputStream is = new FileInputStream(src);
1862      while ((len = is.read(b)) != -1)
1863      {
1864        ((ZipOutputStream) zos_).write(b, 0, len);
1865      }
1866      compressedFilenames_.add(zipfile_.getAbsolutePath());
1867      is = null;
1868    }
1869
1870    // Provide some user feedback
1871    if (!src.isDirectory())
1872    {
1873      logger_.info(" Adding " + entry);
1874    }
1875    else
1876    {
1877      logger_.info(" Added directory " + entry);
1878    }
1879    ((ZipOutputStream) zos_).closeEntry();
1880
1881    logger_.debug("Exiting " + methodName);
1882  }
1883
1884
1885  /**
1886   *  Wrapper method to accept a dir or individual file in the passed in File
1887   *  object AND then calls the method that writes the passed file/dir to this
1888   *  MultiZip instances zip output stream. This is a recursive function. If the
1889   *  passed File object is a file then it calls the function to write to zip
1890   *  output stream. If it is a directory it gets the list of file objects in
1891   *  the child directory and recurses on them.
1892   *
1893   * @param  fo  The File object to zip up (can be an actual file or dir).
1894   * @return     the new length in bytes of the zipped file
1895   */
1896  public long recursiveGZip(File fo)
1897  {
1898    final String methodName = className_ + ": recursiveGZip(File)";
1899    logger_.debug("Entering " + methodName);
1900    long retVal = 0L;
1901
1902    if (!fo.isDirectory())
1903    {
1904      //logger_.debug("  looking at file:" + fo.getPath());
1905      try
1906      {
1907        if (!excludedFile(fo))
1908        {
1909          StringBuffer outLocation = new StringBuffer();
1910          if (zippedOutputLocation_ != null)
1911          {
1912            // use the spec'd location
1913            String fileSep = System.getProperty("file.separator");
1914            String foPath = fo.getAbsolutePath().trim().substring(42);
1915            outLocation.append(zippedOutputLocation_);
1916            if (!zippedOutputLocation_.endsWith(fileSep) &&
1917                !foPath.startsWith(fileSep))
1918            {
1919              outLocation.append(fileSep);
1920            }
1921            outLocation.append(foPath);
1922            outLocation.append(".gz");
1923            logger_.info("Gziping " + foPath + " --> " + outLocation.toString());
1924            retVal = writeToGZip(fo, outLocation.toString());
1925          }
1926          else
1927          {
1928            // zip it in place
1929            logger_.info("Gziping " + fo.getAbsolutePath().trim());
1930            retVal = writeToGZip(fo);
1931          }
1932        }
1933        else
1934        {
1935          logger_.info("Excluding File:" + fo.getAbsolutePath());
1936        }
1937      }
1938      catch (IOException ioEx)
1939      {
1940        logger_.warn("File is missing (Zipping will continue):\n" +
1941            ioEx.getMessage());
1942      }
1943    }
1944    else
1945    {
1946      logger_.debug("  looking at DIRECTORY:" + fo.getPath());
1947      // recurse the Directory
1948      if (excludedFile(fo))
1949      {
1950        logger_.info("Excluding Directory:" + fo.getAbsolutePath());
1951      }
1952      else
1953      {
1954        logger_.info("Recursing " + fo.getPath());
1955        String srcFileNames[] = fo.list();
1956        for (int i = 0; i < srcFileNames.length; i++)
1957        {
1958          retVal += recursiveGZip(new File(fo.getAbsolutePath() + File.separator +
1959              srcFileNames[i]));
1960        }
1961      }
1962    }
1963
1964    logger_.debug("Exiting " + methodName);
1965    return retVal;
1966  }
1967
1968
1969  /**
1970   *  Wrapper method to accept a dir or individual file in the passed in File
1971   *  object AND then calls the method that writes the passed file/dir to this
1972   *  MultiZip instances zip output stream. This is a recursive function. If the
1973   *  passed File object is a file then it calls the function to write to zip
1974   *  output stream. If it is a directory it gets the list of file objects in
1975   *  the child directory and recurses on them.
1976   *
1977   * @param  fo  The File object to zip up (can be an actual file or dir).
1978   * @return     the new length in bytes of the zipped file
1979   */
1980  public long recursiveBzip2(File fo)
1981  {
1982    final String methodName = className_ + ": recursiveBzip2(File)";
1983    logger_.debug("Entering " + methodName);
1984    long retVal = 0L;
1985
1986    String fullFilename = fo.getAbsolutePath().trim();
1987    if (!fo.isDirectory())
1988    {
1989      //logger_.info("Bzip2ing "+fullFilename);
1990      if (!excludedFile(fo))
1991      {
1992        StringBuffer outLocation = new StringBuffer();
1993        if (zippedOutputLocation_ != null)
1994        {
1995          // use the spec'd location
1996          String fileSep = System.getProperty("file.separator");
1997          outLocation.append(zippedOutputLocation_);
1998          if (!zippedOutputLocation_.endsWith(fileSep) &&
1999              !fullFilename.startsWith(fileSep))
2000          {
2001            outLocation.append(fileSep);
2002          }
2003          outLocation.append(fullFilename);
2004          outLocation.append(".bz2");
2005          logger_.info("Bzip2ing " + fullFilename);
2006          logger_.info("  to  " + outLocation.toString());
2007          File outFile = new File(outLocation.toString());
2008          Util.ensureFolderExists(outFile.getParentFile());
2009          try
2010          {
2011            BZip.compress(fo, outFile, 9);
2012            compressedFilenames_.add(outLocation.toString());
2013            retVal += outFile.length();
2014          }
2015          catch (java.lang.ArithmeticException mathEx)
2016          {
2017            logger_.error("BZip2 ERROR: " + fullFilename);
2018            logger_.error(mathEx.getMessage());
2019            errorFiles_.add(fullFilename);
2020          }
2021        }
2022        else
2023        {
2024          // zip it in place
2025          //logger_.info("Bzip2ing "+fullFilename);
2026          File outFile = new File(fullFilename + ".bz2");
2027          Util.ensureFolderExists(outFile.getParentFile());
2028          try
2029          {
2030            BZip.compress(fo, outFile, 9);
2031            compressedFilenames_.add(fullFilename + ".bz2");
2032            retVal += outFile.length();
2033          }
2034          catch (java.lang.ArithmeticException mathEx)
2035          {
2036            logger_.error("BZip2 ERROR: " + fullFilename);
2037            logger_.error(mathEx.getMessage());
2038          }
2039        }
2040      }
2041      else
2042      {
2043        logger_.info("Excluding File:" + fullFilename);
2044      }
2045    }
2046    else
2047    {
2048      if (excludedFile(fo))
2049      {
2050        logger_.info("Excluding Directory:" + fullFilename);
2051      }
2052      else
2053      {
2054        logger_.info("Recursing " + fo.getPath());
2055        String srcFileNames[] = fo.list();
2056        for (int i = 0; i < srcFileNames.length; i++)
2057        {
2058          retVal += recursiveBzip2(new File(fullFilename + File.separator +
2059              srcFileNames[i]));
2060        }
2061      }
2062    }
2063
2064    logger_.debug("Exiting " + methodName);
2065    return retVal;
2066  }
2067
2068
2069  /**
2070   *  Wrapper method to accept a dir or individual file in the passed in File
2071   *  object AND then calls the method that writes the passed file/dir to this
2072   *  MultiZip instances zip output stream. This is a recursive function. If the
2073   *  passed File object is a file then it calls the function to write to zip
2074   *  output stream. If it is a directory it gets the list of file objects in
2075   *  the child directory and recurses on them.
2076   *
2077   * @param  fo  The File object to zip up (can be an actual file or dir).
2078   */
2079  public void recursiveZip(File fo)
2080  {
2081    final String methodName = className_ + ": recursiveZip(File)";
2082    logger_.debug("Entering " + methodName);
2083
2084    try
2085    {
2086      // First check the Zip file size to see if it has reached the user
2087      // specified max size.
2088      if (zipfile_.length() + fo.length() > maxArchiveSize_)
2089      {
2090        logger_.info("Max Zip File Size Reached! " +
2091            "Incrementing ZipFile Name.");
2092        // reinit the stream to increment the name counter
2093        initZipOutputStream(zipfile_);
2094      }
2095
2096      try
2097      {
2098        if (!excludedFile(fo))
2099        {
2100          StringBuffer outLocation = new StringBuffer();
2101          if (zippedOutputLocation_ != null)
2102          {
2103            // use the spec'd location
2104            String fileSep = System.getProperty("file.separator");
2105            String foPath = fo.getAbsolutePath().trim();
2106            outLocation.append(zippedOutputLocation_);
2107            if (!zippedOutputLocation_.endsWith(fileSep) &&
2108                !foPath.startsWith(fileSep))
2109            {
2110              outLocation.append(fileSep);
2111            }
2112            outLocation.append(foPath);
2113            outLocation.append(".zip");
2114            //logger_.info("Zipping "+foPath);
2115            writeToZip(fo);
2116          }
2117          else
2118          {
2119            // zip it in place
2120            String foPath = fo.getAbsolutePath().trim();
2121            outLocation.append(foPath);
2122            outLocation.append(".zip");
2123            //logger_.info("Zipping "+ foPath);
2124            initZipOutputStream(new File(outLocation.toString()));
2125            writeToZip(fo);
2126          }
2127        }
2128        else
2129        {
2130          logger_.info("Excluding File:" + fo.getAbsolutePath());
2131        }
2132      }
2133      catch (java.io.FileNotFoundException fnfe)
2134      {
2135        logger_.error("File is missing (Zipping will continue):\n" +
2136            fnfe.getMessage());
2137      }
2138
2139      // Directory entries must also be included (unless we want a FLAT archive)
2140      if (fo.isDirectory())
2141      {
2142        logger_.info("Recursing " + fo.getPath());
2143        String srcFileNames[] = fo.list();
2144        for (int i = 0; i < srcFileNames.length; i++)
2145        {
2146          recursiveZip(new File(fo.getPath() + File.separator +
2147              srcFileNames[i]));
2148        }
2149      }
2150    }
2151    catch (java.util.zip.DataFormatException dfe)
2152    {
2153      logger_.error("Input data is not in proper format. Details :\n" +
2154          dfe.getMessage());
2155    }
2156    catch (java.util.zip.ZipException ze)
2157    {
2158      logger_.error("Exception occured in zipping file. Details :\n" +
2159          ze.getMessage());
2160    }
2161    catch (java.io.IOException ioe)
2162    {
2163      logger_.error("Input / Output problem. Details :\n" +
2164          ioe.getMessage());
2165    }
2166
2167    logger_.debug("Exiting " + methodName);
2168  }
2169
2170
2171  /**
2172   *  Description of the Method
2173   *
2174   * @param  fileToCheck  Description of the Parameter
2175   * @return              Description of the Return Value
2176   */
2177  protected boolean excludedFile(File fileToCheck)
2178  {
2179    final String methodName = className_ + ": excludedFile(File)";
2180    logger_.debug("Entering " + methodName);
2181
2182    boolean retVal = false;
2183
2184    retVal = excludedFile(fileToCheck.getName());
2185
2186    logger_.debug("Exiting " + methodName);
2187    return retVal;
2188  }
2189
2190
2191  /**
2192   *  Description of the Method
2193   *
2194   * @param  filename  Description of the Parameter
2195   * @return           Description of the Return Value
2196   */
2197  protected boolean excludedFile(String filename)
2198  {
2199    final String methodName = className_ + ": excludedFile(String)";
2200    logger_.debug("Entering " + methodName);
2201
2202    boolean retVal = false;
2203
2204    if (filename != null)
2205    {
2206      for (int i = 0; i < defaultExcludes_.length; i++)
2207      {
2208        if (filename.toLowerCase().endsWith(defaultExcludes_[i].toLowerCase()))
2209        {
2210          retVal = true;
2211          break;
2212        }
2213      }
2214    }
2215
2216    logger_.debug("Exiting " + methodName);
2217    return retVal;
2218  }
2219
2220
2221  /**
2222   *  Wraps the insantaition of a GZIPOutputStream.
2223   *
2224   * @param  fos              Description of the Parameter
2225   * @return                  Description of the Return Value
2226   * @exception  IOException  Description of the Exception
2227   */
2228  protected GZIPOutputStream createGZIPOutputStream(FileOutputStream fos)
2229    throws IOException
2230  {
2231    final String methodName = className_ +
2232        ": createGZIPOutputStream(FileOutputStream)";
2233    logger_.debug("Entering " + methodName);
2234
2235    GZIPOutputStream retVal = null;
2236    retVal = new GZIPOutputStream(fos);
2237
2238    logger_.debug("Exiting " + methodName);
2239    return retVal;
2240  }
2241
2242
2243  /**
2244   *  Wraps the insantaition of a ZipOutputStream.
2245   *
2246   * @param  fos  Description of the Parameter
2247   * @return      Description of the Return Value
2248   */
2249  protected ZipOutputStream createZipOutputStream(FileOutputStream fos)
2250  {
2251    final String methodName = className_ +
2252        ": createZipOutputStream(FileOutputStream)";
2253    logger_.debug("Entering " + methodName);
2254
2255    logger_.debug("Exiting " + methodName);
2256    return new ZipOutputStream(fos);
2257  }
2258
2259
2260  /**
2261   *  Creates a GZip type archive output stream and assigns it to the class
2262   *  zipfile_ var. This method automatically
2263   *
2264   * @param  destZipFile  the base Zip filename (in File format) to create
2265   * @return              Success or failure
2266   */
2267  protected boolean initGZIPOutputStream(File destZipFile)
2268  {
2269    final String methodName = className_ + ": initGZIPOutputStream(File)";
2270    logger_.debug("Entering " + methodName);
2271
2272    boolean retVal = (destZipFile != null);
2273    // avoid nullPEx
2274
2275    if (retVal)
2276    {
2277      // Attempt to open the stream
2278      try
2279      {
2280        zipfile_ = new File(destZipFile.getAbsolutePath());
2281        logger_.debug("Creating Folder: " +
2282            zipfile_.getParent());
2283        Util.ensureFolderExists(zipfile_.getParentFile());
2284        logger_.debug("Creating FileOutputStream Object for " +
2285            zipfile_.getAbsolutePath());
2286
2287        FileOutputStream fos = new FileOutputStream(zipfile_);
2288        zos_ = createGZIPOutputStream(fos);
2289        if (zos_ == null)
2290        {
2291          retVal = false;
2292        }
2293        zipfile_ = null;
2294      }
2295      catch (java.lang.NullPointerException npe)
2296      {
2297        logger_.error("Internal MultiZip Error. Details :\n" +
2298            npe.getMessage());
2299        retVal = false;
2300      }
2301      catch (java.io.FileNotFoundException fnfe)
2302      {
2303        logger_.error("Cannot init File:" + destZipFile.getAbsolutePath() +
2304            ". \nDetails :\n" + fnfe.getMessage());
2305        //fnfe.printStackTrace();
2306        //System.exit(2);
2307        retVal = false;
2308      }
2309      catch (java.io.IOException ioEx)
2310      {
2311        logger_.error("Cannot init File:" + destZipFile.getAbsolutePath() +
2312            ". \nDetails :\n" + ioEx.getMessage());
2313        retVal = false;
2314      }
2315    }
2316
2317    logger_.debug("Exiting " + methodName);
2318    return retVal;
2319  }
2320
2321
2322  /**
2323   *  Creates a Zip type archive output stream and assigns it to the class
2324   *  zipfile_ var. This method automatically increments the filename if the zip
2325   *  archive is larger than the max archive size set in this class. It also
2326   *  will ensure ther output location exists.
2327   *
2328   * @param  destZipFile  the base Zip filename (in File format) to create
2329   * @return              Success or failure
2330   */
2331  protected boolean initZipOutputStream(File destZipFile)
2332  {
2333    final String methodName = className_ + ": initZipOutputStream(File)";
2334    logger_.debug("Entering " + methodName);
2335
2336    boolean retVal = (destZipFile != null);
2337    // avoid nullPEx
2338
2339    if (retVal)
2340    {
2341      String newName = destZipFile.getAbsolutePath().trim();
2342      int endOffset = 5;
2343
2344      if (archivefilenameCounter_ > 0)
2345      {
2346        if (archivefilenameCounter_ == 1)
2347        {
2348          endOffset = 4;
2349        }
2350        newName = newName.substring(0, newName.length() - endOffset) +
2351            archivefilenameCounter_ + ".zip";
2352        try
2353        {
2354          if (zos_ != null)
2355          {
2356            zos_.close();
2357          }
2358        }
2359        catch (java.io.IOException ioe)
2360        {
2361          logger_.error("Input/Output problem attempting to close the " +
2362              "zipfile " + destZipFile.getAbsolutePath().trim() +
2363              ". \nDetails :\n" + ioe.getMessage());
2364          retVal = false;
2365        }
2366      }
2367
2368      // Attempt to open the stream
2369      try
2370      {
2371        archivefilenameCounter_++;
2372        zipfile_ = new File(newName);
2373
2374        logger_.debug("Creating Folder: " +
2375            zipfile_.getParent());
2376        Util.ensureFolderExists(zipfile_.getParentFile());
2377        logger_.debug("Creating FileOutputStream Object for " +
2378            zipfile_);
2379
2380        FileOutputStream fos = new FileOutputStream(zipfile_);
2381        zos_ = createZipOutputStream(fos);
2382        if (zos_ == null)
2383        {
2384          retVal = false;
2385        }
2386        else
2387        {
2388          ((ZipOutputStream) zos_).setLevel(getCompressionLevel());
2389        }
2390        //zipfile_ = null;
2391      }
2392      catch (java.lang.NullPointerException npe)
2393      {
2394        logger_.error("Internal MultiZip Error. Details :\n" + npe.getMessage());
2395        retVal = false;
2396      }
2397      catch (java.io.FileNotFoundException fnfe)
2398      {
2399        logger_.error("Cannot init File:" + newName + ". \nDetails :\n" +
2400            fnfe.getMessage());
2401        retVal = false;
2402      }
2403    }
2404
2405    logger_.debug("Exiting " + methodName);
2406    return retVal;
2407  }
2408
2409
2410  /**
2411   *  Using the class output_, compressionType_ and archiveType_, this method
2412   *  validates that a valid and writable output location/file was specified.
2413   *
2414   * @return    boolean valid or not
2415   */
2416  private boolean validateOutputLocation()
2417  {
2418    final String methodName =
2419        className_ + ": validateOutputLocation()";
2420    logger_.debug("Entering " + methodName);
2421    boolean retVal = true;
2422
2423    if (archiveType_ == (DIR_ARCHIVE))
2424    {
2425      logger_.debug("Validating the DIR Archive:: " + output_);
2426      if (output_ != null && !output_.equals(""))
2427      {
2428        // first confirm we ar dealing with an absolute path
2429        String fileSep = System.getProperty("file.separator");
2430        if (!(output_.startsWith(fileSep) ||
2431            output_.substring(1).startsWith(":")))
2432        {
2433          //  it is a relative path so... construct the absolute path
2434          logger_.info("Specified output path appears to be a relative path.");
2435          String userDir = System.getProperty("user.dir");
2436          StringBuffer newOutput = new StringBuffer(userDir);
2437          if (!userDir.endsWith(fileSep))
2438          {
2439            newOutput.append(fileSep);
2440          }
2441          newOutput.append(output_);
2442          output_ = newOutput.toString();
2443          logger_.info("   ... using the following Absolute path: " + output_);
2444        }
2445        // check that output_ is a dir and is writable
2446        File outFile = new File(output_);
2447        if (!outFile.isDirectory())
2448        {
2449          retVal = false;
2450        }
2451        else
2452        {
2453          // it is a dir so do a test write into it.
2454          try
2455          {
2456            logger_.debug("Testing the output dir: " + output_);
2457            File tmpFile = File.createTempFile("MZP", "", outFile);
2458            tmpFile.delete();
2459            tmpFile = null;
2460
2461            File tmpOutputFile = new File(outFile.getParent() + fileSep + tmpDirName_);
2462            //tmpOutputFile.deleteOnExit();
2463            Util.ensureFolderExists(tmpOutputFile);
2464            logger_.debug("DIR Archive will get its comp files from the dir:");
2465            zippedOutputLocation_ = tmpOutputFile.getAbsolutePath();
2466            logger_.debug(zippedOutputLocation_);
2467            currArchiveSize_ = Util.dirSize(outFile.getAbsolutePath(), true);
2468          }
2469          catch (Exception ex)
2470          {
2471            logger_.fatal("Cannot write into specified output directory.");
2472            logger_.fatal(ex.getMessage());
2473            retVal = false;
2474          }
2475        }
2476      }
2477      else
2478      {
2479        // write to the inputfile location
2480        zippedOutputLocation_ = null;
2481      }
2482    }
2483    else if (archiveType_ == (TAR_ARCHIVE))
2484    {
2485      if (output_ != null && !output_.equals(""))
2486      {
2487        // first confirm we are dealing with an absolute path
2488        String fileSep = System.getProperty("file.separator");
2489        if (!(output_.startsWith(fileSep) ||
2490            output_.substring(1).startsWith(":")))
2491        {
2492          //  it is a relative path so... construct the absolute path
2493          logger_.info("Specified output path appears to be a relative path.");
2494          String userDir = System.getProperty("user.dir");
2495          StringBuffer newOutput = new StringBuffer(userDir);
2496          if (!userDir.endsWith(fileSep))
2497          {
2498            newOutput.append(fileSep);
2499          }
2500          newOutput.append(output_);
2501          output_ = newOutput.toString();
2502          logger_.info("   ... using the following Absolute path: " + output_);
2503        }
2504
2505        // check that output_ is a NOT A DIR and it is in a writable dir
2506        File outFile = new File(output_);
2507        if (outFile.isDirectory())
2508        {
2509          retVal = false;
2510        }
2511        else
2512        {
2513          if (!output_.endsWith(".tar"))
2514          {
2515            output_ += ".tar";
2516          }
2517          try
2518          {
2519            File tmpOutputFile = new File(outFile.getParent() + fileSep + tmpDirName_);
2520            //tmpOutputFile.deleteOnExit();
2521            Util.ensureFolderExists(tmpOutputFile);
2522            logger_.debug("Tar Archive will get its comp files from the dir:");
2523            zippedOutputLocation_ = tmpOutputFile.getAbsolutePath();
2524            logger_.debug(zippedOutputLocation_);
2525          }
2526          catch (Exception ex)
2527          {
2528            logger_.error("Cannot create a tmp dir in specified output dir.");
2529            logger_.error(ex.getMessage());
2530            zippedOutputLocation_ = null;
2531          }
2532        }
2533      }
2534      else
2535      {
2536        //ERROR Need a tar file location
2537        retVal = false;
2538      }
2539    }
2540    else if (archiveType_ == (ZIP_ARCHIVE))
2541    {
2542      if (output_ != null && !output_.equals(""))
2543      {
2544        // check that output_ is a NOT A DIR and it is in a writable dir
2545        File outFile = new File(output_);
2546        logger_.debug("Testing the output filename: " + output_);
2547        if (outFile.isDirectory())// || !outFile.canWrite())
2548        {
2549          logger_.debug(output_ +" is unusable.");
2550          retVal = false;
2551        }
2552        else
2553        {
2554          if (!output_.endsWith(".zip"))
2555          {
2556            output_ += ".zip";
2557          }
2558          logger_.debug(output_ +" is usable!");
2559          retVal = true;
2560          zippedOutputLocation_ = null;
2561        }
2562      }
2563      else
2564      {
2565        //ERROR Need a zip file location
2566        logger_.debug("An output archive location must be specified.");
2567        retVal = false;
2568      }
2569    }
2570    else if (archiveType_ == (TGZ_ARCHIVE))
2571    {
2572      if (output_ != null && !output_.equals(""))
2573      {
2574        // check that output_ is a NOT A DIR and it is in a writable dir
2575        File outFile = new File(output_);
2576        if (outFile.isDirectory() || !outFile.canWrite())
2577        {
2578          retVal = false;
2579        }
2580        else
2581        {
2582          if (!output_.endsWith(".tar"))
2583          {
2584            output_ += ".tar";
2585            zippedOutputLocation_ = null;
2586          }
2587        }
2588      }
2589      else
2590      {
2591        //ERROR Need a file location
2592        retVal = false;
2593      }
2594    }
2595
2596    logger_.debug("Exiting " + methodName);
2597    return retVal;
2598  }
2599
2600
2601  /**
2602   *  Runs through the input Vector and recurses any dirs into the contained
2603   *  names.
2604   *
2605   * @param  input  Description of the Parameter
2606   * @return        The resultant/parsed Vector of Filnames.
2607   */
2608  private Vector recurseInputIntoFiles(Vector input)
2609  {
2610    final String methodName = className_ + ": recurseInputIntoFiles()";
2611    logger_.debug("Entering " + methodName);
2612
2613    Vector retVal = new Vector();
2614    Vector tmpVector = null;
2615    String[] tmpArray = null;
2616    String currElement;
2617    File currFile = null;
2618    if (input != null)
2619    {
2620      String fileSep = File.separator;
2621      String userDir = System.getProperty("user.dir");
2622      StringBuffer newOutput;
2623      if (!userDir.endsWith(fileSep))
2624      {
2625        userDir += fileSep;
2626      }
2627      for (int i = 0; i < input.size(); i++)
2628      {
2629        currElement = ((String) input.elementAt(i)).trim();
2630
2631        // first confirm we are dealing with an absolute path
2632        if (!(currElement.startsWith(fileSep) ||
2633            currElement.substring(1).startsWith(":")))
2634        {
2635          //  it is a relative path so... construct the absolute path
2636          logger_.debug("Specified inputFile path appears to be a relative path.");
2637          newOutput = new StringBuffer(userDir);
2638          newOutput.append(currElement);
2639          currElement = newOutput.toString();
2640        }
2641
2642        currFile = new File(currElement);
2643        if (currFile != null)
2644        {
2645          logger_.debug("    Working on: " + currElement);
2646          if (!currFile.isDirectory())
2647          {
2648            retVal.add(currElement);
2649          }
2650          else
2651          {
2652            logger_.debug("    ...Found a DIR");
2653            tmpVector = new Vector();
2654            tmpArray = currFile.list();
2655            for (int j = 0; j < tmpArray.length; j++)
2656            {
2657              logger_.debug("    ...... " + currElement + fileSep + tmpArray[j]);
2658              if (!excludedFile(tmpArray[j]))
2659              {
2660                tmpVector.add(currElement + fileSep + tmpArray[j]);
2661              }
2662            }
2663            retVal.addAll(recurseInputIntoFiles(tmpVector));
2664          }
2665        }
2666      }
2667    }
2668
2669    logger_.debug("Exiting " + methodName);
2670    return retVal;
2671  }
2672
2673
2674  /**
2675   *  Examines the users Compression and Archive choices and looks for special
2676   *  combos that require an adjustment in some settings.
2677   *
2678   * @return    Description of the Return Value
2679   */
2680  private boolean oneStepArchive()
2681  {
2682    final String methodName = className_ + ": oneStepArchive()";
2683    logger_.debug("Entering " + methodName);
2684
2685    boolean retVal = false;
2686    // TGZ - can be done in one step
2687    if (getArchiveType() == TGZ_ARCHIVE)
2688    {
2689      setCompressionType(NO_COMPRESSION);
2690      retVal = true;
2691    }
2692    // Zip / Zip - can be done in one step
2693    else if (getCompressionType() == ZIP_COMPRESSION &&
2694        getArchiveType() == ZIP_ARCHIVE)
2695    {
2696      retVal = true;
2697    }
2698    // NONE / Zip - can be done in one step
2699    else if (getCompressionType() == NO_COMPRESSION &&
2700        getArchiveType() == ZIP_ARCHIVE)
2701    {
2702      setCompressionLevel(0);
2703      retVal = true;
2704    }
2705    // NONE / DIR - can be done in one step
2706    else if (getCompressionType() == NO_COMPRESSION &&
2707        getArchiveType() == DIR_ARCHIVE)
2708    {
2709      retVal = true;
2710    }
2711    // NONE / Dir,TAR,NONE - can be done in one step
2712    else if (getCompressionType() == NO_COMPRESSION)
2713    {
2714      retVal = true;
2715    }
2716
2717    logger_.debug("Exiting " + methodName);
2718    return retVal;
2719  }
2720
2721
2722  /**
2723   *  Examines the users Compression and Archive choices and looks for special
2724   *  combos that require an adjustment in some settings.
2725   *
2726   * @return    Description of the Return Value
2727   */
2728  private boolean oneStepCompress()
2729  {
2730    final String methodName = className_ + ": oneStepCompress()";
2731    logger_.debug("Entering " + methodName);
2732
2733    boolean retVal = false;
2734
2735    // Zip,Gzip,Bzip2 / DIR - can be done in one step
2736    if (getArchiveType() == DIR_ARCHIVE &&
2737        getCompressionType() != NO_COMPRESSION)
2738    {
2739      retVal = true;
2740    }
2741
2742    logger_.debug("Exiting " + methodName);
2743    return retVal;
2744  }
2745
2746
2747  /**
2748   *  Executes the compression of the input files..
2749   *
2750   * @return    return code
2751   */
2752  private short compressFiles()
2753  {
2754    final String methodName = className_ + ": compressFiles()";
2755    logger_.debug("Entering " + methodName);
2756
2757    short retVal = 0;
2758    switch (getCompressionType())
2759    {
2760        case ZIP_COMPRESSION:
2761          logger_.warn("Beginning to compress files with 'ZIP'.");
2762          //zipFiles(recurseInputIntoFiles(input_));
2763          zipFiles(input_);
2764          break;
2765        case GZIP_COMPRESSION:
2766          logger_.warn("Beginning to compress files with 'GZIP'.");
2767          long gzippedSize = gzipFiles(input_);
2768          logger_.warn("Compressing now Complete. " + (gzippedSize / 1000L) +
2769              "kbytes of 'GZIP' files in ");
2770          logger_.warn(output_);
2771          break;
2772        case BZIP2_COMPRESSION:
2773          logger_.warn("Beginning to compress files with 'BZIP2'.");
2774          long bzippedSize = bzip2Files(input_);
2775          logger_.warn("Compressing now Complete. " + (bzippedSize / 1000L) +
2776              "kbytes of 'BZIP2' files in ");
2777          logger_.warn(output_);
2778          break;
2779        case NO_COMPRESSION:
2780          logger_.warn("NOT compressing files.");
2781          copyFilesToArchive();
2782          break;
2783        default:
2784    }
2785
2786    logger_.debug("Exiting " + methodName);
2787    return retVal;
2788  }
2789
2790
2791  /**
2792   *  Executes the archiving of the input files.
2793   *
2794   * @return    return code
2795   */
2796  private short archiveFiles()
2797  {
2798    final String methodName = className_ + ": archiveFiles()";
2799    logger_.debug("Entering " + methodName);
2800
2801    short retVal = 0;
2802    switch (getArchiveType())
2803    {
2804        case ZIP_ARCHIVE:
2805          logger_.warn("Beginning to Archive " + compressedFilenames_.size() +
2806              " files into the following 'ZIP' style archive.");
2807          logger_.warn(output_);
2808          zipFiles(compressedFilenames_, new File(output_));
2809          break;
2810        case TAR_ARCHIVE:
2811          logger_.warn("Beginning to Archive " + compressedFilenames_.size() +
2812              " files into the following 'TAR' style archive.");
2813          logger_.warn(output_);
2814          tarFiles(compressedFilenames_, output_);//tarCompressedFilesDir(output_);
2815          if (getCompressionType() != NO_COMPRESSION)
2816          {
2817            logger_.debug("Now removing the tmp zip dir: " + zippedOutputLocation_);
2818            Util.removeDir(zippedOutputLocation_);//removeCompressedFiles();
2819          }
2820          break;
2821        case DIR_ARCHIVE:
2822          logger_.warn("Beginning to Archive " + compressedFilenames_.size() +
2823              " files into the following directory.");
2824          logger_.warn(output_);
2825          if (getCompressionType() != NO_COMPRESSION)
2826          {
2827            moveFilesToArchive();
2828          }
2829          else
2830          {
2831            copyFilesToArchive();
2832          }
2833          break;
2834        case TGZ_ARCHIVE:
2835          logger_.warn("Beginning to Archive " + compressedFilenames_.size() +
2836              " files into the following 'TGZ' style archive.");
2837          logger_.warn(output_);
2838          tarFiles(compressedFilenames_, output_);
2839          gzipFile(new File(output_));
2840          String targzFilename = output_ + ".gz";
2841          String tgzFilename = output_.substring(0, output_.lastIndexOf(".tar")) + ".tgz";
2842          (new File(targzFilename)).renameTo(new File(tgzFilename));
2843          break;
2844        default:
2845    }
2846
2847    logger_.debug("Exiting " + methodName);
2848    return retVal;
2849  }
2850}
2851