[cp-patches] Patch: FYI: jar updates

Tom Tromey tromey at redhat.com
Mon May 8 23:48:20 UTC 2006


I'm checking this in.

This fixes some bugs in the jar code.  Among other things it adds
manifest generation and updates NEWS.

I filed a PR for the other known bugs with jar.  In particular the -i
feature is missing and requires something like ASM or another bytecode
library -- like some of the other tools.

Tom

2006-05-08  Tom Tromey  <tromey at redhat.com>

	* tools/gnu/classpath/tools/jar/Updater.java (run): Updated.
	* tools/gnu/classpath/tools/jar/Main.java: Use javadoc for fields.
	* tools/gnu/classpath/tools/jar/Lister.java (listJar): Use
	ZipInputStream.
	(run): Updated.
	* tools/gnu/classpath/tools/jar/Extractor.java (run): Use System.err
	for verbose.
	(run): Use ZipInputStream.
	(initSet): New method.
	(shouldExtract): Likewise.
	(run): Use new methods.
	* tools/gnu/classpath/tools/jar/Creator.java
	(writeCommandLineEntries): New overload.
	(writeFile): Use System.err for verbose.
	(writeManifest): New method.
	(writtenItems): New field.
	(writeFile): Update it.
	(writeCommandLineEntries): Return void.  Call writeManifest.
	(addEntries): Don't add extra '/'.
	* NEWS: Mention jar.

Index: NEWS
===================================================================
RCS file: /cvsroot/classpath/classpath/NEWS,v
retrieving revision 1.139
diff -u -r1.139 NEWS
--- NEWS	3 May 2006 20:42:27 -0000	1.139
+++ NEWS	8 May 2006 23:49:28 -0000
@@ -1,5 +1,7 @@
 New in release 0.92
 
+* A 'jar' tool is now included.
+
 New in release 0.91 (UNRELEASED)
 
 * Experimental activation (java.rmi.activation) support, including RMI
Index: tools/gnu/classpath/tools/jar/Creator.java
===================================================================
RCS file: /cvsroot/classpath/classpath/tools/gnu/classpath/tools/jar/Creator.java,v
retrieving revision 1.1
diff -u -r1.1 Creator.java
--- tools/gnu/classpath/tools/jar/Creator.java	8 May 2006 18:38:20 -0000	1.1
+++ tools/gnu/classpath/tools/jar/Creator.java	8 May 2006 23:49:30 -0000
@@ -38,7 +38,10 @@
 
 package gnu.classpath.tools.jar;
 
+import gnu.classpath.SystemProperties;
+
 import java.io.BufferedOutputStream;
+import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileInputStream;
@@ -47,6 +50,7 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.zip.CRC32;
 import java.util.zip.ZipEntry;
@@ -56,6 +60,7 @@
     extends Action
 {
   ZipOutputStream outputStream;
+  HashSet writtenItems = new HashSet();
 
   private long copyFile(CRC32 crc, InputStream is, OutputStream output)
       throws IOException
@@ -76,8 +81,16 @@
   }
 
   protected void writeFile(boolean isDirectory, InputStream inputFile,
-                           String filename, boolean verbose) throws IOException
+                           String filename, boolean verbose)
+    throws IOException
   {
+    if (writtenItems.contains(filename))
+      {
+        if (verbose)
+          System.err.println("ignoring entry " + filename);
+        return;
+      }
+
     ByteArrayOutputStream out = new ByteArrayOutputStream();
     CRC32 crc = new CRC32();
     long size;
@@ -97,6 +110,7 @@
     outputStream.putNextEntry(entry);
     out.writeTo(outputStream);
     outputStream.closeEntry();
+    writtenItems.add(filename);
 
     if (verbose)
       {
@@ -106,7 +120,7 @@
           perc = 0;
         else
           perc = 100 - (100 * csize) / size;
-        System.out.println("adding: " + filename + " (in=" + size + ") (out="
+        System.err.println("adding: " + filename + " (in=" + size + ") (out="
                            + entry.getSize() + ") (stored " + perc + "%)");
       }
   }
@@ -140,7 +154,7 @@
         String[] files = entry.file.list();
         for (int i = 0; i < files.length; ++i)
           addEntries(result, new Entry(new File(entry.file, files[i]),
-                                       entry.name + '/' + files[i]));
+                                       entry.name + files[i]));
       }
     else
       result.add(entry);
@@ -158,27 +172,59 @@
     return allEntries;
   }
 
-  protected ArrayList writeCommandLineEntries(Main parameters, File zipFile)
+  private void writeCommandLineEntries(Main parameters, ZipOutputStream os)
       throws IOException
   {
-    outputStream = new ZipOutputStream(
-                                       new BufferedOutputStream(
-                                                                new FileOutputStream(
-                                                                                     zipFile)));
+    outputStream = os;
     outputStream.setMethod(parameters.storageMode);
+
+    writeManifest(parameters);
+
     ArrayList allEntries = getAllEntries(parameters);
-    Iterator it = parameters.entries.iterator();
+    Iterator it = allEntries.iterator();
     while (it.hasNext())
       {
         Entry entry = (Entry) it.next();
         writeFile(entry.file, entry.name, parameters.verbose);
       }
-    return allEntries;
+  }
+
+  protected void writeCommandLineEntries(Main parameters, File zipFile)
+    throws IOException
+  {
+      OutputStream os = new BufferedOutputStream(new FileOutputStream(zipFile));
+      writeCommandLineEntries(parameters, new ZipOutputStream(os));
+  }
+
+  protected void writeManifest(Main parameters) throws IOException
+  {
+    File manifestFile;
+    InputStream contents;
+    if (parameters.manifestFile != null)
+      {
+        // User specified a manifest file.
+        contents = new FileInputStream(parameters.manifestFile);
+      }
+    else if (! parameters.wantManifest)
+      {
+        // User didn't want a manifest.
+        return;
+      }
+    else
+      {
+        String desc = ("Manifest-Version: 1.0\n"
+                       + "Created-By: "
+                       + SystemProperties.getProperty("java.version")
+                       + " (GNU Classpath)\n\n");
+        contents = new ByteArrayInputStream(desc.getBytes("UTF-8"));
+      }
+    // Make the META-INF directory and the manifest file.
+    writeFile(true, null, "META-INF/", parameters.verbose);
+    writeFile(false, contents, "META-INF/MANIFEST.MF", parameters.verbose);
   }
 
   protected void close() throws IOException
   {
-    // FIXME: handle manifest options here.
     // FIXME: handle index file here ...?
     outputStream.finish();
     outputStream.close();
@@ -186,7 +232,10 @@
 
   public void run(Main parameters) throws IOException
   {
-    writeCommandLineEntries(parameters, parameters.archiveFile);
+    if (parameters.archiveFile == null || parameters.archiveFile.equals("-"))
+      writeCommandLineEntries(parameters, new ZipOutputStream(System.out));
+    else
+      writeCommandLineEntries(parameters, parameters.archiveFile);
     close();
   }
 }
Index: tools/gnu/classpath/tools/jar/Extractor.java
===================================================================
RCS file: /cvsroot/classpath/classpath/tools/gnu/classpath/tools/jar/Extractor.java,v
retrieving revision 1.1
diff -u -r1.1 Extractor.java
--- tools/gnu/classpath/tools/jar/Extractor.java	8 May 2006 18:38:20 -0000	1.1
+++ tools/gnu/classpath/tools/jar/Extractor.java	8 May 2006 23:49:30 -0000
@@ -38,17 +38,25 @@
 
 package gnu.classpath.tools.jar;
 
+import java.io.BufferedInputStream;
 import java.io.File;
+import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.util.Enumeration;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
 import java.util.zip.ZipEntry;
-import java.util.zip.ZipFile;
+import java.util.zip.ZipInputStream;
 
 public class Extractor
     extends Action
 {
+  // This is a set of all the items specified on the command line.
+  // It is null if none were specified.
+  private HashSet allItems;
+
   private void copyFile(InputStream input, File output) throws IOException
   {
     FileOutputStream os = new FileOutputStream(output);
@@ -63,20 +71,68 @@
     os.close();
   }
 
+  private void initSet(ArrayList entries)
+  {
+    if (entries == null || entries.isEmpty())
+      return;
+    allItems = new HashSet();
+    Iterator it = entries.iterator();
+    while (it.hasNext())
+      {
+        Entry entry = (Entry) it.next();
+        int len = entry.name.length();
+        while (len > 0 && entry.name.charAt(len - 1) == '/')
+          --len;
+        String name = entry.name.substring(0, len);
+        allItems.add(name);
+      }
+  }
+
+  private boolean shouldExtract(String filename)
+  {
+    if (allItems == null)
+      return true;
+    while (filename.length() > 0)
+      {
+        if (allItems.contains(filename))
+          return true;
+        int index = filename.lastIndexOf('/');
+        if (index == -1)
+          break;
+        filename = filename.substring(0, index);
+      }
+    return false;
+  }
+
   public void run(Main parameters) throws IOException
   {
-    ZipFile zip = new ZipFile(parameters.archiveFile);
-    Enumeration e = zip.entries();
-    while (e.hasMoreElements())
+    // Figure out what we want to extract.
+    initSet(parameters.entries);
+    // Open the input file.
+    ZipInputStream zis;
+    File zfile = parameters.archiveFile;
+    if (zfile == null || "-".equals(zfile.getName()))
+      zis = new ZipInputStream(System.in);
+    else
       {
-        ZipEntry entry = (ZipEntry) e.nextElement();
+        InputStream ins = new BufferedInputStream(new FileInputStream(zfile));
+        zis = new ZipInputStream(ins);
+      }
+    // Extract stuff.
+    while (true)
+      {
+        ZipEntry entry = zis.getNextEntry();
+        if (entry == null)
+          break;
+        if (! shouldExtract(entry.getName()))
+          continue;
         File file = new File(entry.getName());
         if (entry.isDirectory())
           {
             if (file.mkdirs())
               {
                 if (parameters.verbose)
-                  System.out.println("  created: " + file);
+                  System.err.println("  created: " + file);
               }
             continue;
           }
@@ -85,15 +141,13 @@
         if (parent != null)
           parent.mkdirs();
 
-        InputStream input = zip.getInputStream(entry);
-        copyFile(input, file);
-        input.close();
+        copyFile(zis, file);
 
         if (parameters.verbose)
           {
-            String leader = (entry.getMethod() == ZipEntry.STORED ? " extracted"
-                                                                 : "  inflated");
-            System.out.println(leader + ": " + file);
+            String leader = (entry.getMethod() == ZipEntry.STORED
+                             ? " extracted" : "  inflated");
+            System.err.println(leader + ": " + file);
           }
       }
   }
Index: tools/gnu/classpath/tools/jar/Lister.java
===================================================================
RCS file: /cvsroot/classpath/classpath/tools/gnu/classpath/tools/jar/Lister.java,v
retrieving revision 1.1
diff -u -r1.1 Lister.java
--- tools/gnu/classpath/tools/jar/Lister.java	8 May 2006 18:38:20 -0000	1.1
+++ tools/gnu/classpath/tools/jar/Lister.java	8 May 2006 23:49:30 -0000
@@ -38,27 +38,28 @@
 
 package gnu.classpath.tools.jar;
 
+import java.io.BufferedInputStream;
 import java.io.File;
+import java.io.FileInputStream;
 import java.io.IOException;
 import java.text.MessageFormat;
 import java.util.Date;
-import java.util.Enumeration;
 import java.util.zip.ZipEntry;
-import java.util.zip.ZipFile;
+import java.util.zip.ZipInputStream;
 
 public class Lister
     extends Action
 {
-  private void listJar(File jarFile, boolean verbose) throws IOException
+  private void listJar(ZipInputStream zis, boolean verbose) throws IOException
   {
-    ZipFile zipFile = new ZipFile(jarFile);
-    Enumeration i = zipFile.entries();
     MessageFormat format = null;
     if (verbose)
       format = new MessageFormat(" {0,date,E M dd HH:mm:ss z yyyy} {1}");
-    while (i.hasMoreElements())
+    while (true)
       {
-        ZipEntry entry = (ZipEntry) i.nextElement();
+        ZipEntry entry = zis.getNextEntry();
+        if (entry == null)
+          break;
         if (verbose)
           {
             // No easy way to right-justify the size using
@@ -74,11 +75,16 @@
         else
           System.out.println(entry.getName());
       }
-    zipFile.close();
   }
 
   public void run(Main parameters) throws IOException
   {
-    listJar(parameters.archiveFile, parameters.verbose);
+    File file = parameters.archiveFile;
+    ZipInputStream zis;
+    if (file == null || "-".equals(file.getName()))
+      zis = new ZipInputStream(System.in);
+    else
+      zis = new ZipInputStream(new BufferedInputStream(new FileInputStream(file)));
+    listJar(zis, parameters.verbose);
   }
 }
Index: tools/gnu/classpath/tools/jar/Main.java
===================================================================
RCS file: /cvsroot/classpath/classpath/tools/gnu/classpath/tools/jar/Main.java,v
retrieving revision 1.1
diff -u -r1.1 Main.java
--- tools/gnu/classpath/tools/jar/Main.java	8 May 2006 18:38:20 -0000	1.1
+++ tools/gnu/classpath/tools/jar/Main.java	8 May 2006 23:49:30 -0000
@@ -52,34 +52,34 @@
 
 public class Main
 {
-  // The mode of operation. This is the class representing
-  // the action; we make a new instance before using it. It
-  // must be a subclass of Action. 'null' means the mode
-  // has not yet been set.
+  /** The mode of operation. This is the class representing
+   * the action; we make a new instance before using it. It
+   * must be a subclass of Action. 'null' means the mode
+   * has not yet been set.  */
   Class operationMode;
 
-  // The archive file name.
+  /** The archive file name.  */
   File archiveFile;
 
-  // The zip storage mode.
+  /** The zip storage mode.  */
   int storageMode = ZipOutputStream.DEFLATED;
 
-  // True if we should read file names from stdin.
+  /** True if we should read file names from stdin.  */
   boolean readNamesFromStdin = false;
 
-  // True for verbose mode.
+  /** True for verbose mode.  */
   boolean verbose = false;
 
-  // True if we want a manifest file.
+  /** True if we want a manifest file.  */
   boolean wantManifest = true;
 
-  // Name of manifest file to use.
+  /** Name of manifest file to use.  */
   File manifestFile;
 
-  // A list of Entry objects, each describing a file to write.
+  /** A list of Entry objects, each describing a file to write.  */
   ArrayList entries = new ArrayList();
 
-  // Used only while parsing.
+  /** Used only while parsing, holds the first argument for -C.  */
   String changedDirectory;
 
   class HandleFile
Index: tools/gnu/classpath/tools/jar/Updater.java
===================================================================
RCS file: /cvsroot/classpath/classpath/tools/gnu/classpath/tools/jar/Updater.java,v
retrieving revision 1.1
diff -u -r1.1 Updater.java
--- tools/gnu/classpath/tools/jar/Updater.java	8 May 2006 18:38:20 -0000	1.1
+++ tools/gnu/classpath/tools/jar/Updater.java	8 May 2006 23:49:30 -0000
@@ -40,10 +40,7 @@
 
 import java.io.File;
 import java.io.IOException;
-import java.util.ArrayList;
 import java.util.Enumeration;
-import java.util.HashSet;
-import java.util.Iterator;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipFile;
 
@@ -54,14 +51,7 @@
   {
     // Write all the new entries to a temporary file.
     File tmpFile = File.createTempFile("jarcopy", null);
-    ArrayList newEntries = writeCommandLineEntries(parameters, tmpFile);
-    HashSet set = new HashSet();
-    Iterator it = newEntries.iterator();
-    while (it.hasNext())
-      {
-        Entry entry = (Entry) it.next();
-        set.add(entry.name);
-      }
+    writeCommandLineEntries(parameters, tmpFile);
 
     // Now read the old file and copy extra entries to the new file.
     ZipFile zip = new ZipFile(parameters.archiveFile);
@@ -69,7 +59,7 @@
     while (e.hasMoreElements())
       {
         ZipEntry entry = (ZipEntry) e.nextElement();
-        if (set.contains(entry.getName()))
+        if (writtenItems.contains(entry.getName()))
           continue;
         writeFile(entry.isDirectory(), zip.getInputStream(entry),
                   zip.getName(), parameters.verbose);



More information about the Classpath-patches mailing list