home *** CD-ROM | disk | FTP | other *** search
/ Chip 1998 July / Chip_1998-07_cd.bin / zkuste / JBuilder / BDK / Win / bdk_sep97.exe / _SETUP.1 / JarAccess.java < prev    next >
Encoding:
Java Source  |  1997-09-10  |  8.6 KB  |  345 lines

  1. package sun.beanbox;
  2.  
  3. import java.io.*;
  4. import java.util.*;
  5. import java.util.zip.*;
  6.  
  7. /**
  8.  * This class implements a simple utility for creating files in the JAR
  9.  * (Java Archive) file format. The JAR format is based on the ZIP file
  10.  * format, with optional meta-information stored in a MANIFEST entry.
  11.  *
  12.  * It borrows from JDK's jar tool.
  13.  */
  14.  
  15. public
  16. class JarAccess {
  17.     static final String MANIFEST = "META-INF/MANIFEST.MF";
  18.     static final char SEPARATOR = File.separatorChar;
  19.  
  20.     private File jarName;    // the (relative to WD) name of the JarFile
  21.     private File dirName;    // the (relative to WD) name of the base directory
  22.     private String beanName;    // the (relative to base) beanFileName
  23.     private String[] fileNames;    // all (relative to base) file names
  24.  
  25.     /**
  26.      * A command line interface.
  27.      * Usage is:
  28.      *    jar [-bean BeanFileName] [-dir Directory] JarName fileNames...
  29.      */
  30.  
  31.     public static void main(String args[]) {
  32.     if (args.length <= 1) {
  33.         error("not enough arguments");
  34.         usageError();
  35.     }
  36.     JarAccess tool = new JarAccess();
  37.     if (! tool.parseArgs(args)) {
  38.         usageError();
  39.     }
  40.     tool.createJarFile();
  41.     }
  42.  
  43.     /**
  44.      * Create a Jar from parsed argument data
  45.      */
  46.  
  47.     private void createJarFile() {
  48.     try {
  49.         OutputStream out = new FileOutputStream(jarName);
  50.         if ((beanName == null) && (dirName == null)) {
  51.         create(out, fileNames);
  52.         } else {
  53.         create(out, dirName, beanName, fileNames);
  54.         }
  55.     } catch (Exception ex) {
  56.         System.err.println("caught exception: "+ex);
  57.         ex.printStackTrace();
  58.         System.exit(1);
  59.     }
  60.     }
  61.  
  62.     /**
  63.      * Create a new JAR file;
  64.      * Given a base directory, a beanfilename, and a set of files names,
  65.      * these two relative to the base directory
  66.      *
  67.      * if baseDir is null, it means WD
  68.      * if beanFIle is null, it means generate no MANIFEST
  69.      *
  70.      * Generates a *non-signed* MANIFEST
  71.      */
  72.     public static void create(OutputStream out,
  73.                   File baseDir,
  74.                   String beanFile,
  75.                   String[] files)
  76.     throws IOException
  77.     {
  78.     int start = 0;
  79.     if (beanFile != null) {
  80.         start = 1;
  81.     }
  82.     JarEntrySource[] data = new JarEntrySource[files.length + start];
  83.     if (beanFile != null) {
  84.         data[0] = makeManifestEntry(beanFile);
  85.     }
  86.     for (int i = 0; i<files.length; i++) {
  87.         data[i+start] = new JarEntrySource(entryName(files[i]),
  88.                            new File(baseDir, files[i]));
  89.     }
  90.     create(out, data);
  91.     }
  92.  
  93.     /**
  94.      * An InputStream with the data about the Manifest
  95.      */
  96.     public static JarEntrySource makeManifestEntry(String beanName) {
  97.     StringBuffer s = new StringBuffer("Manifest-Version: 1.0\n");
  98.     s.append("\n");
  99.     s.append("Name: "+beanName+"\n");
  100.     s.append("Java-Bean: True\n");
  101.     s.append("\n");
  102.     return new JarEntrySource(MANIFEST,
  103.                   new StringBufferInputStream(s.toString()));
  104.     }
  105.  
  106.     /**
  107.      * Creates a new ZIP file with a bunch of files
  108.      */
  109.     public static void create(OutputStream out,
  110.                String[] files) throws IOException {
  111.     ZipOutputStream zos = new ZipOutputStream(out);
  112.     for (int i = 0; i < files.length; i++) {
  113.         addEntry(zos, new JarEntrySource(new File(files[i])));
  114.     }
  115.     zos.close();
  116.     }
  117.  
  118.       /**
  119.      * Creates a new ZIP file with a bunch of entries
  120.      */
  121.     public static void create(OutputStream out,
  122.                JarEntrySource[] entries) throws IOException {
  123.     ZipOutputStream zos = new ZipOutputStream(out);
  124.     for (int i = 0; i < entries.length; i++) {
  125.         addEntry(zos, entries[i]);
  126.     }
  127.     zos.close();
  128.     }
  129.  
  130.     private static String entryName(String name) {
  131.     name = name.replace(File.separatorChar, '/');
  132.     if (name.startsWith("/")) {
  133.         name = name.substring(1);
  134.     } else if (name.startsWith("./")) {
  135.         name = name.substring(2);
  136.     }
  137.     return name;
  138.     }
  139.  
  140.     /*
  141.      * Adds a new file entry to the ZIP output stream.
  142.      */
  143.     static void addEntry(ZipOutputStream zos,
  144.              JarEntrySource source) throws IOException {
  145.     String name = source.getName();
  146.     if (name.equals("") || name.equals(".")) {
  147.         return;
  148.     }
  149.  
  150.     //    long size = source.getLength();
  151.  
  152.     ZipEntry e = new ZipEntry(name);
  153.  
  154.     e.setTime(source.getTime());
  155.     boolean markOnly = source.isMarkOnly();
  156.  
  157.     if (markOnly) {
  158.         e.setMethod(ZipEntry.STORED);
  159.         e.setSize(0);
  160.         e.setCrc(0);
  161.     }
  162.     zos.putNextEntry(e);
  163.     if (! markOnly) {
  164.         byte[] buf = new byte[1024];
  165.         int len;
  166.         InputStream is = new BufferedInputStream(source.getInputStream());
  167.         while ((len = is.read(buf, 0, buf.length)) != -1) {
  168.         zos.write(buf, 0, len);
  169.         }
  170.         is.close();
  171.     }
  172.     zos.closeEntry();
  173.     }
  174.  
  175.     /*
  176.      * Extracts specified entries from JAR file.
  177.      */
  178.     private static void extract(InputStream in,
  179.                 String files[]) throws IOException {
  180.     ZipInputStream zis = new ZipInputStream(in);
  181.     ZipEntry e;
  182.     while ((e = zis.getNextEntry()) != null) {
  183.         if (files == null) {
  184.         extractFile(zis, e);
  185.         } else {
  186.         String name = e.getName().replace('/', File.separatorChar);
  187.         for (int i = 0; i < files.length; i++) {
  188.             if (name.startsWith(files[i])) {
  189.             extractFile(zis, e);
  190.             break;
  191.             }
  192.         }
  193.         }
  194.     }
  195.     }
  196.  
  197.     /*
  198.      * Extracts next entry from JAR file, creating directories as needed.
  199.      */
  200.     private static void extractFile(ZipInputStream zis, ZipEntry e)
  201.     throws IOException
  202.     {
  203.     File f = new File(e.getName().replace('/', File.separatorChar));
  204.     if (e.isDirectory()) {
  205.         if (!f.exists() && !f.mkdirs() || !f.isDirectory()) {
  206.         throw new IOException(f + ": could not create directory");
  207.         }
  208.     } else {
  209.         if (f.getParent() != null) {
  210.         File d = new File(f.getParent());
  211.         if (!d.exists() && !d.mkdirs() || !d.isDirectory()) {
  212.             throw new IOException(d + ": could not create directory");
  213.         }
  214.         }
  215.         OutputStream os = new FileOutputStream(f);
  216.         byte[] b = new byte[512];
  217.         int len;
  218.         while ((len = zis.read(b, 0, b.length)) != -1) {
  219.         os.write(b, 0, len);
  220.         }
  221.         zis.closeEntry();
  222.         os.close();
  223.     }
  224.     }
  225.  
  226.     /*
  227.      * Lists contents of JAR file.
  228.      */
  229.     private static void list(InputStream in, String files[])
  230.     throws IOException
  231.     {
  232.     ZipInputStream zis = new ZipInputStream(in);
  233.     ZipEntry e;
  234.     while ((e = zis.getNextEntry()) != null) {
  235.         String name = e.getName().replace('/', File.separatorChar);
  236.         /*
  237.          * In the case of a compressed (deflated) entry, the entry size
  238.          * is stored immediately following the entry data and cannot be
  239.          * determined until the entry is fully read. Therefore, we close
  240.          * the entry first before printing out its attributes.
  241.          */
  242.         zis.closeEntry();
  243.         if (files == null) {
  244.         printEntry(e);
  245.         } else {
  246.         for (int i = 0; i < files.length; i++) {
  247.             if (name.startsWith(files[i])) {
  248.             printEntry(e);
  249.             break;
  250.             }
  251.         }
  252.         }
  253.     }
  254.     }
  255.  
  256.     /*
  257.      * Prints entry information.
  258.      */
  259.     private static void printEntry(ZipEntry e)    throws IOException {
  260.     output(e.getName());
  261.     }
  262.  
  263.     /**
  264.      * Parse the arguments
  265.      */
  266.     private boolean parseArgs(String args[]) {
  267.     int l = args.length;
  268.     int i;
  269.     for (i = 0; i<l; i++) {
  270.         if (args[i].equals("-bean")) {
  271.         if (i+1 >= l) {
  272.             error("-bean option needs to be followed by an argument");
  273.             return false;
  274.         }
  275.         beanName = args[i+1];
  276.         i += 1;
  277.         } else if (args[i].equals("-dir")) {
  278.         if (i+1 >= l) {
  279.             error("-dir option needs to be followed by an argument");
  280.             return false;
  281.         }
  282.         dirName = new File(args[i+1]);
  283.         i += 1;
  284.         } else {
  285.         break;
  286.         }
  287.     }
  288.     if (i+1 >= l) {
  289.         error("not enough arguments");
  290.         return false;
  291.     }
  292.     jarName = new File(args[i]);
  293.     i += 1;
  294.     fileNames = new String[l-i];
  295.     for (int j=0; j<l-i ; j++) {
  296.         fileNames[j] = args[j+i];
  297.     }
  298.     // printArgs();
  299.     return true;
  300.     }
  301.  
  302.     /**
  303.      * Print the argumens read, for debugging
  304.      */
  305.     private void printArgs() {
  306.     System.err.println("jarName: "+jarName);
  307.     System.err.println("dirName: "+dirName);
  308.     System.err.println("beanName: "+beanName);
  309.     System.err.println("fileNames: "+fileNames);
  310.     if (fileNames != null) {
  311.         for (int i=0; i<fileNames.length; i++) {
  312.         System.err.println("fileNames["+i+"]: "+fileNames[i]);
  313.         }
  314.     }
  315.     }
  316.  
  317.     /**
  318.      * Print usage information
  319.      */
  320.     private static void usageError() {
  321.     error("Usage: JarAccess [-bean BeanFileName] [-dir Directory] jarFileName files...");
  322.     error("  Create a jar; does no object signing");
  323.     error("Options:");
  324.     error("  -bean  BeanFileName is the FileName of a Bean to be tagged");
  325.     error("  -dir   Directory is the directory from where to interpret file names");
  326.     error("         so the manifest will have relative names");
  327.     System.exit(1);
  328.     }
  329.  
  330.     /**
  331.      * Print an output message
  332.      */
  333.     protected static void output(String s) {
  334.     System.err.println(s);
  335.     }
  336.  
  337.     /**
  338.      * Print an error message
  339.      */
  340.     protected static void error(String s) {
  341.     System.err.println(s);
  342.     }
  343.  
  344. }
  345.