File Input Output Java

/*******************************************************************************
 * Copyright (c) 2004, 2008 IBM Corporation.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 * IBM Corporation - initial API and implementation                                       
 *******************************************************************************/
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.util.Iterator;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.zip.GZIPInputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
/*******************************************************************************
 * * InstallJars - a utility to download and install files, Jars and Zips. * *
 * 
 * @author Barry Feigenbaum, Ph.D. *
 ******************************************************************************/
public class InstallJars {
  public static final int BLOCK_SIZE = 512;
  public static final int BLOCK_COUNT = 20;
  // *** must be a multiple of BLOCK_SIZE ***
  public static int bufferSize = 128 * (2 * BLOCK_SIZE);
  // *** need to NLS enable all user messages ***
  /**
   * Constructor. Expand, run and verbose output requested.
   */
  public InstallJars() {
    this(true, true, true, "InstallJars.properties", "cmd /c java");
  }
  /**
   * Contstructor.
   * 
   * @param expand
   *          true if the archive is t be expanded in the target
   * @param verbose
   *          true if messages are to be generated
   * @param run
   *          true if file is to be executed
   * @param propName
   *          properties file with items to install
   * @param javaParams
   *          java parameters
   */
  public InstallJars(boolean expand, boolean verbose, boolean run, String propName,
      String javaParams) {
    setExpand(expand);
    setVerbose(verbose);
    setRunMode(run);
    setPropFilename(propName);
    setJavaParams(javaParams);
  }
  protected boolean verbose;
  /**
   * Get the verbose mode state.
   * 
   * @return is in verbose mode
   */
  public boolean getVerbose() {
    return verbose;
  }
  /**
   * Set the verbose mode state.
   * 
   * @param f
   *          value
   */
  public void setVerbose(boolean f) {
    verbose = f;
  }
  protected boolean run;
  /**
   * Get the run mode state.
   * 
   * @return is in run mode
   */
  public boolean getRunMode() {
    return run;
  }
  /**
   * Set the run mode state.
   * 
   * @param f
   *          value
   */
  public void setRunMode(boolean f) {
    run = f;
  }
  protected boolean expand;
  /**
   * Get the expand mode state.
   * 
   * @return is expanded
   */
  public boolean getExpand() {
    return expand;
  }
  /**
   * Set the expand mode state.
   * 
   * @param f
   *          value
   */
  public void setExpand(boolean f) {
    expand = f;
  }
  protected String propFilename;
  /**
   * Get the propFilename mode state.
   * 
   * @return prooperty file name
   */
  public String getPropFilename() {
    return propFilename;
  }
  /**
   * Set the propFilename mode state.
   * 
   * @param name
   */
  public void setPropFilename(String name) {
    propFilename = name;
  }
  protected String javaParams = "cmd /c java";
  /**
   * Get the JavaParams mode state.
   * 
   * @return java parameters
   */
  public String getJavaParams() {
    return javaParams;
  }
  /**
   * Set the JavaParams mode state.
   * 
   * @param p
   *          value
   */
  public void setJavaParams(String p) {
    javaParams = p;
  }
  protected void print(String s) {
    if (verbose) {
      System.out.print(s);
    }
  }
  protected void println(String s) {
    if (verbose) {
      System.out.println(s);
    }
  }
  protected void println() {
    println("");
  }
  /**
   * Install based on a properties file

   * 
   * @return recommended classpath
   * @exception IOException
   *              Thrown if a JAR file access error occurs
   */
  public String install() throws IOException {
    StringBuffer classpath = new StringBuffer();
    Properties prop = new Properties();
    prop.load(new BufferedInputStream(new FileInputStream(propFilename)));
    for (Iterator i = prop.keySet().iterator(); i.hasNext();) {
      String key = (String) i.next();
      String value = prop.getProperty(key);
      String xurl = null;
      String xdir = null;
      String xcp = null;
      boolean xexpand = expand, xrun = run;
      if (value != null) {
        value = value.trim();
        if (value.length() > 0) {
          String delim = value.substring(0, 1);
          StringTokenizer st = new StringTokenizer(value.substring(1), delim);
          xurl = st.nextToken();
          xdir = (st.hasMoreTokens() ? st.nextToken() : ".").trim();
          if (xdir.length() == 0) {
            xdir = ".";
          }
          xcp = (st.hasMoreTokens() ? st.nextToken() : xdir).trim();
          if (xcp.length() == 0) {
            xcp = xdir;
          }
          classpath.append(xcp);
          classpath.append(";");
          while (st.hasMoreTokens()) {
            String xoption = st.nextToken().trim();
            if (xoption.equalsIgnoreCase("expand")) {
              xexpand = true;
            } else if (xoption.equalsIgnoreCase("noexpand")) {
              xexpand = false;
            } else if (xoption.equalsIgnoreCase("run")) {
              xrun = true;
            } else if (xoption.equalsIgnoreCase("norun")) {
              xrun = false;
            } else {
              throw new IllegalArgumentException("invalid install property - " + key + "=" + value);
            }
          }
        }
      }
      if (xurl == null || xurl.length() == 0) {
        throw new IllegalArgumentException("missing install property - " + key + "=" + value);
      }
      System.out.print("\nInstalling " + key);
      if (verbose) {
        System.out.print(" using URL=" + xurl + "; target=" + xdir + "; classpath=" + xcp + "; "
            + (xexpand ? "expand" : "noexpand") + "; " + (xrun ? "run" : "norun"));
      }
      System.out.println("...");
      installFile(xurl, xdir, xexpand, xrun);
    }
    return classpath.toString();
  }
  /**
   * Install a Zip/Jar file.
   * 
   * @param fileUrl
   *          The file/zip/jar file
   * @param targetPath
   *          root of directory or file to install into
   * @param doExpand
   * @param doRun
   * @exception IOException
   *              Thrown if a JAR file access error occurs
   */
  public void installFile(String fileUrl, String targetPath, boolean doExpand, boolean doRun)
      throws IOException {
    String targetFilename = new File(targetPath).getCanonicalPath().replace('\\', '/');
    println("Installing in " + targetFilename);
    URL url = new URL(fileUrl);
    URLConnection conn = url.openConnection();
    // System.out.println("Conn = " + conn);
    String ctype = conn.getContentType();
    println("Content type is " + ctype);
    String extension = getExtension(fileUrl);
    if (extension.equals("class")) {
      installClass(conn, targetFilename, doExpand, doRun);
      // println("Installed class file " + fileUrl + "; please run");
    } else if (extension.equalsIgnoreCase("zip")) {
      installZip(conn, targetFilename, doExpand, doRun);
      // println("Installed ZIP file " + fileUrl + "; ZIP expanded");
    } else if (extension.equalsIgnoreCase("gz")) {
      installGZip(conn, targetFilename, doExpand, doRun);
      // println("Installed GZIP file " + fileUrl + "; ZIP expanded");
    } else if (extension.equalsIgnoreCase("jar")) {
      installJar(conn, targetFilename, doExpand, doRun);
      // System.out.println("Installed JAR file " + fileUrl + "; please add to
      // CLASSPATH");
    } else {
      throw new IllegalArgumentException("Unknown extension - " + extension);
    }
  }
  public void installClass(URLConnection conn, String target, boolean doExpand, boolean doRun)
      throws IOException {
    // doExpand not used on htis type
    print("Installing class file " + target + " from " + conn.getURL().toExternalForm());
    copyStream(conn, target);
    println();
    if (doRun) {
      runTarget(target, false);
    }
  }
  protected void runTarget(String target, boolean isJar) throws IOException {
    // *** add run code ***
    if (isJar) {
      System.out.println("runTarget(" + target + "," + isJar + ") not currently implemented");
    } else {
      try {
        String name = removeExtension(getFile(target));
        String cp = "-cp " + removeFile(target);
        String command = javaParams + " " + cp + " " + name + " >" + name + ".out 2>" + name
            + ".err";
        // String command = javaParams + " " + cp + " " + name;
        System.out.println("Running " + command + "...");
        Process p = Runtime.getRuntime().exec(command);
        int rc = p.waitFor();
        System.out.println("Return code=" + rc);
      } catch (Exception e) {
        System.out.println("Exception - " + e.getMessage());
      }
    }
  }
  public void installJar(URLConnection conn, String target, boolean doExpand, boolean doRun)
      throws IOException {
    if (doExpand) {
      println("Expanding JAR file " + target + " from " + conn.getURL().toExternalForm());
      // *** may need to specialize for JAR format ***
      ZipInputStream zis = new ZipInputStream(new BufferedInputStream(conn.getInputStream(),
          BLOCK_SIZE * BLOCK_COUNT));
      int count = 0;
      prepDirs(target, true);
      try {
        while (zis.available() > 0) {
          ZipEntry ze = zis.getNextEntry();
          copyEntry(target, zis, ze);
          count++;
        }
      } finally {
        try {
          zis.close();
        } catch (IOException ioe) {
        }
      }
      println("Installed " + count + " files/directories");
    } else {
      print("Installing JAR file " + target + " from " + conn.getURL().toExternalForm());
      copyStream(conn, target);
      println();
      if (doRun) {
        runTarget(target, true);
      }
    }
  }
  public void installZip(URLConnection conn, String target, boolean doExpand, boolean doRun)
      throws IOException {
    // doRun not used on htis type
    if (doExpand) {
      String ctype = conn.getContentType();
      if (!ctype.equals("application/zip")) {
        throw new IllegalArgumentException("Unkexpected content type - " + ctype);
      }
      println("Expanding ZIP file to " + target + " from " + conn.getURL().toExternalForm());
      ZipInputStream zis = new ZipInputStream(new BufferedInputStream(conn.getInputStream(),
          BLOCK_SIZE * BLOCK_COUNT));
      int count = 0;
      prepDirs(target, true);
      try {
        for (ZipEntry ze = zis.getNextEntry(); ze != null; ze = zis.getNextEntry()) {
          copyEntry(target, zis, ze);
          // zis.closeEntry();
          count++;
        }
      } finally {
        try {
          zis.close();
        } catch (IOException ioe) {
        }
      }
      println("Installed " + count + " files/directories");
    } else {
      print("Installing ZIP file " + target + " from " + conn.getURL().toExternalForm());
      copyStream(conn, target);
      println();
    }
  }
  public void installGZip(URLConnection conn, String target, boolean doExpand, boolean doRun)
      throws IOException {
    // doRun not used on htis type
    if (doExpand) {
      String ctype = conn.getContentType();
      if (!ctype.equals("application/x-tar")) {
        throw new IllegalArgumentException("Unkexpected content type - " + ctype);
      }
      print("Expanding GZIP file to " + target + " from " + conn.getURL().toExternalForm());
      prepDirs(target, false);
      GZIPInputStream zis = new GZIPInputStream(new BufferedInputStream(conn.getInputStream(),
          BLOCK_SIZE * BLOCK_COUNT));
      try {
        // BufferedOutputStream os = new BufferedOutputStream(new
        // FileOutputStream(target), BLOCK_SIZE * BLOCK_COUNT);
        // try {
        // byte[] buf = new byte[bufferSize];
        // for (int size = zis.read(buf, 0, buf.length), count = 0;
        // size >= 0;
        // size = zis.read(buf, 0, buf.length), count++) {
        // //if (count % 4 == 0) print(".");
        // os.write(buf, 0, size);
        // }
        // }
        // finally {
        // try { os.flush(); os.close(); } catch (IOException ioe) {}
        // }
        pumpGZip(target, zis);
      } finally {
        try {
          zis.close();
        } catch (IOException ioe) {
        }
      }
      println();
    } else {
      print("Installing GZIP file " + target + " from " + conn.getURL().toExternalForm());
      copyStream(conn, target);
      println();
    }
  }
  /** Copy a zip entry. */
  protected void copyEntry(String target, ZipInputStream zis, ZipEntry ze) throws IOException {
    String name = ze.getName();
    boolean isDir = false;
    if (name.endsWith("/")) {
      name = name.substring(0, name.length() - 1);
      isDir = true;
    }
    String path = target + File.separator + name;
    path = path.replace('\\', '/');
    String mod = ze.getSize() > 0 ? ("[" + ze.getCompressedSize() + ":" + ze.getSize() + "]") : "";
    print("Expanding " + ze + mod + " to " + path);
    prepDirs(path, isDir);
    if (!isDir) {
      BufferedOutputStream os = new BufferedOutputStream(new FileOutputStream(path), BLOCK_SIZE
          * BLOCK_COUNT);
      try {
        byte[] buf = new byte[bufferSize];
        for (int size = zis.read(buf, 0, buf.length), count = 0; size >= 0; size = zis.read(buf, 0,
            buf.length), count++) {
          // if (count % 4 == 0) print(".");
          os.write(buf, 0, size);
        }
      } finally {
        try {
          os.flush();
          os.close();
        } catch (IOException ioe) {
        }
      }
    }
    println();
  }
  public void copyStream(URLConnection conn, String target) throws IOException {
    prepDirs(target, false);
    BufferedInputStream is = new BufferedInputStream(conn.getInputStream(), BLOCK_SIZE
        * BLOCK_COUNT);
    BufferedOutputStream os = new BufferedOutputStream(new FileOutputStream(target), BLOCK_SIZE
        * BLOCK_COUNT);
    byte[] buf = new byte[bufferSize];
    for (int size = is.read(buf), count = 0; size >= 0; size = is.read(buf), count++) {
      // if (count % 4 == 0) print(".");
      os.write(buf, 0, size);
    }
    os.flush();
    os.close();
    is.close();
  }
  protected static final int OFFSET_NAME = 0;
  protected static final int OFFSET_MODE = OFFSET_NAME + 100;
  protected static final int OFFSET_UID = OFFSET_MODE + 8;
  protected static final int OFFSET_GID = OFFSET_UID + 8;
  protected static final int OFFSET_SIZE = OFFSET_GID + 8;
  protected static final int OFFSET_MTIME = OFFSET_SIZE + 12;
  protected static final int OFFSET_CHKSUM = OFFSET_MTIME + 12;
  protected static final int OFFSET_TYPE = OFFSET_CHKSUM + 8;
  protected static final int OFFSET_LINKNAME = OFFSET_TYPE + 1;
  protected static final int OFFSET_MAGIC = OFFSET_LINKNAME + 100;
  protected static final int OFFSET_VERSION = OFFSET_MAGIC + 6;
  protected static final int OFFSET_UNAME = OFFSET_VERSION + 2;
  protected static final int OFFSET_GNAME = OFFSET_UNAME + 32;
  protected static final int OFFSET_DEVMAJOR = OFFSET_GNAME + 32;
  protected static final int OFFSET_DEVMINOR = OFFSET_DEVMAJOR + 8;
  protected static final int OFFSET_PREFIX = OFFSET_DEVMINOR + 8;
  protected static final int OFFSET_END = OFFSET_PREFIX + 155;
  protected static final String MAGIC = "USTAR";
  protected void pumpGZip(String target, GZIPInputStream zis) throws IOException {
    String curName = null;
    long curSize = 0, remainingSize = 0;
    char curType = 0;
    int curMajor = 0, curMinor = 0;
    boolean inFile = false;
    BufferedOutputStream curOs = null;
    int instFiles = 0, instDirs = 0;
    byte[] buf = new byte[bufferSize];
    top: while (true) {
      int loaded = loadBytes(buf, zis);
      if (loaded < 0) {
        break;
      }
      // System.out.println("pumpGZip: loaded=" + loaded);
      // process each buffer of data
      for (int index = 0; index < loaded; index += BLOCK_SIZE) {
        // System.out.println("pumpGZip: infile=" + inFile + ", remaining=" +
        // remainingSize);
        if (inFile && remainingSize > 0) { // process body part
          int xsize = Math.min((int) remainingSize, BLOCK_SIZE);
          if (curOs != null) {
            curOs.write(buf, index, xsize);
          }
          remainingSize -= xsize;
        } else { // process header block
          if (inFile) {
            inFile = false;
            if (curOs != null) {
              try {
                curOs.flush();
                curOs.close();
              } catch (IOException ioe) {
              }
              println();
            }
          }
          if (isEmptyBlock(buf, index)) { // check logical end of archive
            break top;
          }
          // System.out.println("pumpGZip: header=" + (new String(buf, 0, index,
          // 512)));
          curName = extractString(buf, index + OFFSET_NAME, 100);
          curType = extractChar(buf, index + OFFSET_TYPE);
          curSize = extractLong(buf, index + OFFSET_SIZE, 12);
          remainingSize = curSize;
          if (remainingSize > Integer.MAX_VALUE) {
            throw new IOException("entry size too large - " + remainingSize);
          }
          String mod = "";
          String magic = extractString(buf, index + OFFSET_MAGIC, 6);
          if (magic.equals(MAGIC)) {
            curName = extractString(buf, index + OFFSET_PREFIX, 155) + curName;
            extractInt(buf, index + OFFSET_VERSION, 2);
            curMajor = extractInt(buf, index + OFFSET_DEVMAJOR, 8);
            curMinor = extractInt(buf, index + OFFSET_DEVMINOR, 8);
            if (curMajor > 0 || curMinor > 0) {
              mod = "[" + curMajor + '.' + curMinor + "]";
            }
          }
          // System.out.println("pumpGZip: " +
          // magic + "," +
          // curName + "," +
          // curType + "," +
          // curSize + "," +
          // curVersion + "," +
          // curMajor + "," +
          // curMinor);
          String path = target + File.separator + curName;
          path = path.replace('\\', '/');
          curOs = null;
          if (curType == 0 || curType == '0') { // a file
            print("Copying " + curName + mod + " to " + path);
            prepDirs(path, false);
            curOs = new BufferedOutputStream(new FileOutputStream(path), BLOCK_SIZE * BLOCK_COUNT);
            inFile = true;
            instFiles++;
          } else if (curType == '1' || curType == '2') { // a link
            if (curSize > 0) {
              throw new IOException("link entries cannot have content - " + curSize);
            }
            println("Link ignored - " + curName + mod);
          } else if (curType == '5') { // a directory
            if (path.endsWith("/")) {
              path = path.substring(0, path.length() - 1);
            }
            println("Mkdir " + curName + mod + " to " + path);
            prepDirs(path, true);
            instDirs++;
          } else {
            if (curSize > 0) {
              // throw new IOException("entry type " + curType + " cannot have a
              // content - size=" + curSize);
              inFile = true;
            }
            print("Entry type " + curType + " ignored - " + curName + mod);
          }
        }
      }
    }
    println("Installed " + instFiles + " files and " + instDirs + " directories");
  }
  protected int loadBytes(byte[] buf, GZIPInputStream zis) throws IOException {
    int loaded = -1;
    for (int size = zis.read(buf, 0, buf.length), count = 0; size > 0; size = zis.read(buf, loaded,
        buf.length - loaded), count++) {
      // if (count % 4 == 0) print(".");
      // System.out.println("loadBytes: loaded=" + loaded);
      if (loaded < 0) {
        loaded = 0;
      }
      loaded += size;
    }
    return loaded;
  }
  protected boolean isEmptyBlock(byte[] buf, int index) {
    boolean r = true;
    for (int i = 0; r && i < BLOCK_SIZE; i++) {
      r = buf[index++] == 0;
    }
    // System.out.println("isEmptyBlock: " + r);
    return r;
  }
  protected char extractChar(byte[] buf, int index) throws IOException {
    return (char) buf[index];
  }
  protected int extractInt(byte[] buf, int index, int length) throws IOException {
    return (int) extractLong(buf, index, length);
  }
  protected long extractLong(byte[] buf, int index, int length) throws IOException {
    String xsize = extractString(buf, index, length);
    long v = 0;
    for (int i = 0; i < xsize.length(); i++) {
      char c = xsize.charAt(i);
      if (c != ' ') {
        if (c < '0' || c > '7') {
          throw new IOException("non-octal digit found - " + c);
        }
        v = v * 8 + (c - '0');
      }
    }
    return v;
  }
  protected String extractString(byte[] buf, int index, int length) throws IOException {
    StringBuffer sb = new StringBuffer();
    for (int i = 0, xindex = index; i < length; i++, xindex++) {
      int c = buf[xindex];
      if (c == 0) {
        break;
      }
      sb.append((char) c);
    }
    // System.out.println("extractString(" + index + "," + length + "): " +
    // sb.toString());
    return sb.toString();
  }
  protected String getFile(String name) {
    int posn = name.lastIndexOf("/");
    return posn > 0 ? name.substring(posn + 1) : name;
  }
  protected String removeFile(String name) {
    int posn = name.lastIndexOf("/");
    return posn > 0 ? name.substring(0, posn) : name;
  }
  protected String removeExtension(String name) {
    int posn1 = name.lastIndexOf("/");
    int posn2 = name.lastIndexOf(".");
    return (posn2 > 0 && posn2 > posn1) ? name.substring(0, posn2) : name;
  }
  protected String extraceFile(String name) {
    int posn = name.lastIndexOf(File.separator);
    return posn >= 0 ? name.substring(posn + 1) : null;
  }
  protected String getExtension(String name) {
    int posn = name.lastIndexOf('.');
    return posn >= 0 ? name.substring(posn + 1) : "";
  }
  protected void prepDirs(String name) {
    prepDirs(name, expand);
  }
  protected void prepDirs(String name, boolean includeLast) {
    File f = new File(includeLast ? name : removeFile(name));
    // System.out.print("(Making " + f + ")");
    f.mkdirs();
  }
  protected void printUsage() {
    println("Effective command: " + getClass().getName() + " " + propFilename
        + (expand ? " -expand" : " -noexpand") + (run ? " -run" : " -norun") + " -java \""
        + javaParams + "\"" + (verbose ? " -verbose" : " -quiet "));
  }
  /** Print command help text. */
  protected static void printHelp() {
    System.out.println();
    System.out
        .println("Usage: java "
            + InstallJars.class.getName()
            + " {propFilename} {-expand | -noexpand} {-run | -norun} {-quiet | -verbose} {-java }");
    System.out.println("Where:");
    System.out
        .println("  propFilename    path to properties file (default=InstallJars.properties)");
    System.out.println("  -expand         expand any top level JAR/ZIP/GZIP (default)");
    System.out.println("  -noexpand       do not expand any top level JAR/ZIP/GZIP");
    System.out.println("  -run            run class or JAR files (default)");
    System.out.println("  -norun          do not run class or JAR files");
    System.out.println("  -verbose        output progress messages (default)");
    System.out.println("  -quiet          suppress most messages");
    System.out.println("  -java           sets java runtime paramters");
    System.out.println();
    System.out.println("Properties file entry format: name=!url{!target{!classpath{!option}...}}");
    System.out.println("Where:");
    System.out.println("  name      name displayed while installing");
    System.out.println("  url       source of items to download and install");
    System.out.println("  target    root of install directory or file (default=.)");
    System.out
        .println("  classpath class path entry to use for this directrory or file (default=target}");
    System.out.println("  option    one of the following options: expand, noexpand, run, norun");
    System.out.println("            if omitted, the command line default is used");
    System.out.println("! is a delimiter, the first non-whitespace character is used.");
    System.out.println("Options expand and run may not apply to all types of files.");
  }
  /**
   * Main command line entry point.
   * 
   * @param args
   */
  public static void main(final String[] args) {
    if (args.length == 0) {
      printHelp();
      System.exit(0);
    }
    String propName = null;
    boolean expand = true;
    boolean verbose = true;
    boolean run = true;
    String params = "cmd /c java";
    // process arguments
    for (int i = 0; i < args.length; i++) {
      String arg = args[i];
      if (arg.charAt(0) == '-') { // switch
        arg = arg.substring(1);
        if (arg.equalsIgnoreCase("quiet")) {
          verbose = false;
        } else if (arg.equalsIgnoreCase("verbose")) {
          verbose = true;
        } else if (arg.equalsIgnoreCase("expand")) {
          expand = true;
        } else if (arg.equalsIgnoreCase("noexpand")) {
          expand = false;
        } else if (arg.equalsIgnoreCase("run")) {
          run = true;
        } else if (arg.equalsIgnoreCase("norun")) {
          run = false;
        } else if (arg.equalsIgnoreCase("java")) {
          run = false;
          if (i < args.length - 1) {
            params = args[++i];
          }
        } else {
          System.err.println("Invalid switch - " + arg);
          System.exit(1);
        }
      } else {
        if (propName == null) {
          propName = arg;
        } else {
          System.err.println("Too many parameters - " + arg);
          System.exit(1);
        }
      }
    }
    if (propName == null) {
      propName = "InstallJars.properties";
    }
    // do the install
    try {
      InstallJars ij = new InstallJars(expand, verbose, run, propName, params);
      ij.printUsage();
      String cp = ij.install();
      System.out.println("\nRecomended additions to your classpath - " + cp);
    } catch (Exception e) {
      System.err.println("\n" + e.getClass().getName() + ": " + e.getMessage());
      if (verbose) {
        e.printStackTrace(); // *** debug ***
      }
      System.exit(2);
    }
  }
}