summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorTom Tromey <tromey@redhat.com>2006-05-14 20:38:32 +0000
committerTom Tromey <tromey@redhat.com>2006-05-14 20:38:32 +0000
commit192554e63278ffff52e9eb985e8f9fae33b9638e (patch)
treecd9159103b5977c98435371714ac79a0a170e23d /tools
parent682bd33d1c4b61637d1d27781e601276cf27912c (diff)
downloadclasspath-192554e63278ffff52e9eb985e8f9fae33b9638e.tar.gz
PR classpath/27514:
* gnu/java/net/IndexListParser.java (JAR_INDEX_FILE): Renamed. Now constant. (JAR_INDEX_VERSION_KEY): Likewise. (IndexListParser): Updated. (getVersionInfo): Likewise. * tools/gnu/classpath/tools/jar/Indexer.java: New file. * tools/gnu/classpath/tools/jar/Action.java (run): Now throws OptionException. * tools/gnu/classpath/tools/jar/Main.java (initializeParser): Handle -i. (ModeOption): New constructor. (parsed): Updated. Use setArchiveFile. (setArchiveFile): New method. (run): Handle no-argument case. (main): Emit --help message on option error. * tools/gnu/classpath/tools/jar/Updater.java (inputJar): New field. (createManifest): New method. (run): Updated. Throws OptionException. Correctly copy zip entry. * tools/gnu/classpath/tools/jar/Creator.java (createManifest): New method. (writeManifest): Removed. (outputStream): Now a JarOutputStream. (writeCommandLineEntries): Changed parameters. Updated callers. (run): Throws OptionException. * java/util/jar/JarOutputStream.java (putNextEntry): Typo fix. * java/util/jar/Manifest.java (read): Typo fix.
Diffstat (limited to 'tools')
-rw-r--r--tools/gnu/classpath/tools/jar/Action.java5
-rw-r--r--tools/gnu/classpath/tools/jar/Creator.java74
-rw-r--r--tools/gnu/classpath/tools/jar/Indexer.java148
-rw-r--r--tools/gnu/classpath/tools/jar/Main.java32
-rw-r--r--tools/gnu/classpath/tools/jar/Updater.java36
5 files changed, 242 insertions, 53 deletions
diff --git a/tools/gnu/classpath/tools/jar/Action.java b/tools/gnu/classpath/tools/jar/Action.java
index fea60f797..b6398936d 100644
--- a/tools/gnu/classpath/tools/jar/Action.java
+++ b/tools/gnu/classpath/tools/jar/Action.java
@@ -38,6 +38,8 @@
package gnu.classpath.tools.jar;
+import gnu.classpath.tools.getopt.OptionException;
+
import java.io.IOException;
public abstract class Action
@@ -46,5 +48,6 @@ public abstract class Action
{
}
- public abstract void run(Main parameters) throws IOException;
+ public abstract void run(Main parameters)
+ throws IOException, OptionException;
}
diff --git a/tools/gnu/classpath/tools/jar/Creator.java b/tools/gnu/classpath/tools/jar/Creator.java
index 8a5d387a0..caf093b77 100644
--- a/tools/gnu/classpath/tools/jar/Creator.java
+++ b/tools/gnu/classpath/tools/jar/Creator.java
@@ -38,10 +38,9 @@
package gnu.classpath.tools.jar;
-import gnu.classpath.SystemProperties;
+import gnu.classpath.tools.getopt.OptionException;
import java.io.BufferedOutputStream;
-import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
@@ -52,15 +51,19 @@ import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
+import java.util.jar.JarFile;
+import java.util.jar.JarOutputStream;
+import java.util.jar.Manifest;
import java.util.zip.CRC32;
import java.util.zip.ZipEntry;
-import java.util.zip.ZipOutputStream;
public class Creator
extends Action
{
- ZipOutputStream outputStream;
+ JarOutputStream outputStream;
HashSet writtenItems = new HashSet();
+ // The manifest to use, or null if we don't want a manifest.
+ Manifest manifest;
private long copyFile(CRC32 crc, InputStream is, OutputStream output)
throws IOException
@@ -172,13 +175,12 @@ public class Creator
return allEntries;
}
- private void writeCommandLineEntries(Main parameters, ZipOutputStream os)
+ private void writeCommandLineEntries(Main parameters)
throws IOException
{
- outputStream = os;
- outputStream.setMethod(parameters.storageMode);
-
- writeManifest(parameters);
+ // We've already written the manifest, make sure to mark it.
+ writtenItems.add("META-INF/");
+ writtenItems.add(JarFile.MANIFEST_NAME);
ArrayList allEntries = getAllEntries(parameters);
Iterator it = allEntries.iterator();
@@ -189,53 +191,47 @@ public class Creator
}
}
- protected void writeCommandLineEntries(Main parameters, File zipFile)
+ protected Manifest createManifest(Main parameters)
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.wantManifest)
+ return null;
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"));
+ InputStream contents = new FileInputStream(parameters.manifestFile);
+ return new Manifest(contents);
}
- // 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);
+ return new Manifest();
+ }
+
+ protected void writeCommandLineEntries(Main parameters, OutputStream os)
+ throws IOException
+ {
+ manifest = createManifest(parameters);
+ outputStream = new JarOutputStream(os, manifest);
+ // FIXME: in Classpath this sets the method too late for the
+ // manifest file.
+ outputStream.setMethod(parameters.storageMode);
+ writeCommandLineEntries(parameters);
}
protected void close() throws IOException
{
- // FIXME: handle index file here ...?
outputStream.finish();
outputStream.close();
}
- public void run(Main parameters) throws IOException
+ public void run(Main parameters) throws IOException, OptionException
{
if (parameters.archiveFile == null || parameters.archiveFile.equals("-"))
- writeCommandLineEntries(parameters, new ZipOutputStream(System.out));
+ writeCommandLineEntries(parameters, System.out);
else
- writeCommandLineEntries(parameters, parameters.archiveFile);
+ {
+ OutputStream os
+ = new BufferedOutputStream(new FileOutputStream(parameters.archiveFile));
+ writeCommandLineEntries(parameters, os);
+ }
close();
}
}
diff --git a/tools/gnu/classpath/tools/jar/Indexer.java b/tools/gnu/classpath/tools/jar/Indexer.java
new file mode 100644
index 000000000..62959dbf3
--- /dev/null
+++ b/tools/gnu/classpath/tools/jar/Indexer.java
@@ -0,0 +1,148 @@
+/* Indexer.java -- add index.list file to jar
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.classpath.tools.jar;
+
+import gnu.classpath.tools.getopt.OptionException;
+import gnu.java.net.IndexListParser;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.StringTokenizer;
+import java.util.jar.Attributes;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
+
+public class Indexer
+ extends Updater
+{
+ private void indexJarFile(StringBuffer result, File fileName,
+ boolean verbose)
+ throws IOException
+ {
+ if (verbose)
+ System.err.println("indexing: " + fileName);
+ JarFile jf = new JarFile(fileName);
+
+ // Index the files in this jar.
+ HashSet entries = new HashSet();
+ Enumeration e = jf.entries();
+ while (e.hasMoreElements())
+ {
+ JarEntry entry = (JarEntry) e.nextElement();
+ String name = entry.getName();
+ if (name.startsWith("META-INF/"))
+ continue;
+ int index = name.lastIndexOf('/');
+ if (index != -1)
+ name = name.substring(0, index);
+ entries.add(name);
+ }
+ if (! entries.isEmpty())
+ {
+ result.append(fileName);
+ // Any line ending will do.
+ result.append('\n');
+ Iterator i = entries.iterator();
+ while (i.hasNext())
+ {
+ result.append(i.next());
+ result.append('\n');
+ }
+ // Paragraph break.
+ result.append('\n');
+ }
+
+ // Now read pointed-to jars.
+ Manifest m = jf.getManifest();
+ if (m != null)
+ {
+ File parent = fileName.getParentFile();
+ Attributes attrs = m.getMainAttributes();
+ String jars = attrs.getValue(Attributes.Name.CLASS_PATH);
+ if (jars != null)
+ {
+ StringTokenizer st = new StringTokenizer(jars, " ");
+ while (st.hasMoreTokens())
+ {
+ String name = st.nextToken();
+ indexJarFile(result, new File(parent, name), verbose);
+ }
+ }
+ }
+
+ jf.close();
+ }
+
+ protected void writeCommandLineEntries(Main parameters, OutputStream os)
+ throws IOException
+ {
+ // This is a pretty lame design. We know the super call will
+ // only have side effects and won't actually write anything important.
+ super.writeCommandLineEntries(parameters, os);
+
+ // Now compute our index file and write it.
+ StringBuffer contents = new StringBuffer();
+ indexJarFile(contents, parameters.archiveFile, parameters.verbose);
+ if (contents.length() != 0)
+ {
+ contents.insert(0, (IndexListParser.JAR_INDEX_VERSION_KEY
+ + "1.0\n\n"));
+ ByteArrayInputStream in
+ = new ByteArrayInputStream(contents.toString().getBytes());
+ writeFile(false, in, IndexListParser.JAR_INDEX_FILE, parameters.verbose);
+ }
+ }
+
+ public void run(Main parameters) throws IOException, OptionException
+ {
+ if (! parameters.entries.isEmpty())
+ throw new OptionException("can't specify file arguments when using -i");
+ if (! parameters.wantManifest)
+ throw new OptionException("can't specify -M with -i");
+ if (parameters.manifestFile != null)
+ throw new OptionException("can't specify -m with -i");
+ super.run(parameters);
+ }
+}
diff --git a/tools/gnu/classpath/tools/jar/Main.java b/tools/gnu/classpath/tools/jar/Main.java
index bccb32ad8..757c0bc93 100644
--- a/tools/gnu/classpath/tools/jar/Main.java
+++ b/tools/gnu/classpath/tools/jar/Main.java
@@ -82,6 +82,14 @@ public class Main
/** Used only while parsing, holds the first argument for -C. */
String changedDirectory;
+ void setArchiveFile(String filename) throws OptionException
+ {
+ if (archiveFile != null)
+ throw new OptionException("archive file name already set to "
+ + archiveFile);
+ archiveFile = new File(filename);
+ }
+
class HandleFile
extends FileArgumentCallback
{
@@ -112,24 +120,36 @@ public class Main
this.mode = mode;
}
+ public ModeOption(char shortName, String description, String argName,
+ Class mode)
+ {
+ super(shortName, description, argName);
+ this.mode = mode;
+ }
+
public void parsed(String argument) throws OptionException
{
if (operationMode != null)
throw new OptionException("operation mode already specified");
operationMode = mode;
+ // We know this is only the case for -i.
+ if (argument != null)
+ setArchiveFile(argument);
}
}
private Parser initializeParser()
{
Parser p = new ClasspathToolParser("jar");
- p.setHeader("Usage: jar -ctxu [OPTIONS] jar-file [-C DIR FILE] FILE...");
+ p.setHeader("Usage: jar -ctxui [OPTIONS] jar-file [-C DIR FILE] FILE...");
OptionGroup grp = new OptionGroup("Operation mode");
grp.add(new ModeOption('c', "create a new archive", Creator.class));
grp.add(new ModeOption('x', "extract from archive", Extractor.class));
grp.add(new ModeOption('t', "list archive contents", Lister.class));
grp.add(new ModeOption('u', "update archive", Updater.class));
+ // Note that -i works in-place and explicitly requires a file name.
+ grp.add(new ModeOption('i', "compute archive index", "FILE", Indexer.class));
p.add(grp);
grp = new OptionGroup("Operation modifiers");
@@ -137,8 +157,7 @@ public class Main
{
public void parsed(String argument) throws OptionException
{
- // FIXME: error if already set.
- archiveFile = new File(argument);
+ setArchiveFile(argument);
}
});
grp.add(new Option('0', "store only; no ZIP compression")
@@ -182,7 +201,6 @@ public class Main
}
});
p.add(grp);
- // -i - need to parse classes
return p;
}
@@ -192,11 +210,11 @@ public class Main
{
Parser p = initializeParser();
// Special hack to emulate old tar-style commands.
- if (args[0].charAt(0) != '-')
+ if (args.length > 0 && args[0].charAt(0) != '-')
args[0] = '-' + args[0];
p.parse(args, new HandleFile());
if (operationMode == null)
- throw new OptionException("must specify one of -t, -c, -u, or -x");
+ throw new OptionException("must specify one of -t, -c, -u, -x, or -i");
if (changedDirectory != null)
throw new OptionException("-C argument requires both directory and filename");
Action t = (Action) operationMode.newInstance();
@@ -213,6 +231,8 @@ public class Main
catch (OptionException arg)
{
System.err.println("jar: " + arg.getMessage());
+ // FIXME: this should be pushed into the parser somehow.
+ System.err.println("Try 'jar --help' for more information");
System.exit(1);
}
catch (Exception e)
diff --git a/tools/gnu/classpath/tools/jar/Updater.java b/tools/gnu/classpath/tools/jar/Updater.java
index 161418f4c..b717507a8 100644
--- a/tools/gnu/classpath/tools/jar/Updater.java
+++ b/tools/gnu/classpath/tools/jar/Updater.java
@@ -38,31 +38,53 @@
package gnu.classpath.tools.jar;
+import gnu.classpath.tools.getopt.OptionException;
+
+import java.io.BufferedOutputStream;
import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.OutputStream;
import java.util.Enumeration;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
import java.util.zip.ZipEntry;
-import java.util.zip.ZipFile;
public class Updater
extends Creator
{
- public void run(Main parameters) throws IOException
+ JarFile inputJar;
+
+ protected Manifest createManifest(Main parameters) throws IOException
+ {
+ Manifest result = inputJar.getManifest();
+ if (result == null)
+ return super.createManifest(parameters);
+ if (parameters.manifestFile != null)
+ result.read(new FileInputStream(parameters.manifestFile));
+ return result;
+ }
+
+ public void run(Main parameters) throws IOException, OptionException
{
+ // Set this early so that createManifest can use it.
+ inputJar = new JarFile(parameters.archiveFile);
+
// Write all the new entries to a temporary file.
File tmpFile = File.createTempFile("jarcopy", null);
- writeCommandLineEntries(parameters, tmpFile);
+ OutputStream os = new BufferedOutputStream(new FileOutputStream(tmpFile));
+ writeCommandLineEntries(parameters, os);
// Now read the old file and copy extra entries to the new file.
- ZipFile zip = new ZipFile(parameters.archiveFile);
- Enumeration e = zip.entries();
+ Enumeration e = inputJar.entries();
while (e.hasMoreElements())
{
ZipEntry entry = (ZipEntry) e.nextElement();
if (writtenItems.contains(entry.getName()))
continue;
- writeFile(entry.isDirectory(), zip.getInputStream(entry),
- zip.getName(), parameters.verbose);
+ writeFile(entry.isDirectory(), inputJar.getInputStream(entry),
+ entry.getName(), parameters.verbose);
}
close();