/* * Copyright (c) 1996, 1999, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code 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 * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */package sun.tools.jar;import java.io.*;import java.util.*;import java.security.*;import sun.net.www.MessageHeader;import sun.misc.BASE64Encoder;import sun.misc.BASE64Decoder;/** * This is OBSOLETE. DO NOT USE THIS. Use java.util.jar.Manifest * instead. It has to stay here because some apps (namely HJ and HJV) * call directly into it. * * @author David Brown * @author Benjamin Renaud */public class Manifest { /* list of headers that all pertain to a particular * file in the archive */ private Vector entries = new Vector(); private byte[] tmpbuf = new byte[512]; /* a hashtable of entries, for fast lookup */ private Hashtable tableEntries = new Hashtable(); static final String[] hashes = {"SHA"}; static final byte[] EOL = {(byte)'\r', (byte)'\n'}; static final boolean debug = false; static final String VERSION = "1.0"; static final void debug(String s) { if (debug) System.out.println("man> " + s); } public Manifest() {} public Manifest(byte[] bytes) throws IOException { this(new ByteArrayInputStream(bytes), false); } public Manifest(InputStream is) throws IOException { this(is, true); } /** * Parse a manifest from a stream, optionally computing hashes * for the files. */ public Manifest(InputStream is, boolean compute) throws IOException { if (!is.markSupported()) { is = new BufferedInputStream(is); } /* do not rely on available() here! */ while (true) { is.mark(1); if (is.read() == -1) { // EOF break; } is.reset(); MessageHeader m = new MessageHeader(is); if (compute) { doHashes(m); } addEntry(m); } } /* recursively generate manifests from directory tree */ public Manifest(String[] files) throws IOException { MessageHeader globals = new MessageHeader(); globals.add("Manifest-Version", VERSION); String jdkVersion = System.getProperty("java.version"); globals.add("Created-By", "Manifest JDK "+jdkVersion); addEntry(globals); addFiles(null, files); } public void addEntry(MessageHeader entry) { entries.addElement(entry); String name = entry.findValue("Name"); debug("addEntry for name: "+name); if (name != null) { tableEntries.put(name, entry); } } public MessageHeader getEntry(String name) { return (MessageHeader) tableEntries.get(name); } public MessageHeader entryAt(int i) { return (MessageHeader) entries.elementAt(i); } public Enumeration entries() { return entries.elements(); } public void addFiles(File dir, String[] files) throws IOException { if (files == null) return; for (int i = 0; i < files.length; i++) { File file; if (dir == null) { file = new File(files[i]); } else { file = new File(dir, files[i]); } if (file.isDirectory()) { addFiles(file, file.list()); } else { addFile(file); } } } /** * File names are represented internally using "/"; * they are converted to the local format for anything else */ private final String stdToLocal(String name) { return name.replace('/', java.io.File.separatorChar); } private final String localToStd(String name) { name = name.replace(java.io.File.separatorChar, '/'); if (name.startsWith("./")) name = name.substring(2); else if (name.startsWith("/")) name = name.substring(1); return name; } public void addFile(File f) throws IOException { String stdName = localToStd(f.getPath()); if (tableEntries.get(stdName) == null) { MessageHeader mh = new MessageHeader(); mh.add("Name", stdName); addEntry(mh); } } public void doHashes(MessageHeader mh) throws IOException { // If unnamed or is a directory return immediately String name = mh.findValue("Name"); if (name == null || name.endsWith("/")) { return; } BASE64Encoder enc = new BASE64Encoder(); /* compute hashes, write over any other "Hash-Algorithms" (?) */ for (int j = 0; j < hashes.length; ++j) { InputStream is = new FileInputStream(stdToLocal(name)); try { MessageDigest dig = MessageDigest.getInstance(hashes[j]); int len; while ((len = is.read(tmpbuf, 0, tmpbuf.length)) != -1) { dig.update(tmpbuf, 0, len); } mh.set(hashes[j] + "-Digest", enc.encode(dig.digest())); } catch (NoSuchAlgorithmException e) { throw new JarException("Digest algorithm " + hashes[j] + " not available."); } finally { is.close(); } } } /* Add a manifest file at current position in a stream */ public void stream(OutputStream os) throws IOException { PrintStream ps; if (os instanceof PrintStream) { ps = (PrintStream) os; } else { ps = new PrintStream(os); } /* the first header in the file should be the global one. * It should say "Manifest-Version: x.x"; if not add it */ MessageHeader globals = (MessageHeader) entries.elementAt(0); if (globals.findValue("Manifest-Version") == null) { /* Assume this is a user-defined manifest. If it has a Name: <..> * field, then it is not global, in which case we just add our own * global Manifest-version: <version> * If the first MessageHeader has no Name: <..>, we assume it * is a global header and so prepend Manifest to it. */ String jdkVersion = System.getProperty("java.version"); if (globals.findValue("Name") == null) { globals.prepend("Manifest-Version", VERSION); globals.add("Created-By", "Manifest JDK "+jdkVersion); } else { ps.print("Manifest-Version: "+VERSION+"\r\n"+ "Created-By: "+jdkVersion+"\r\n\r\n"); } ps.flush(); } globals.print(ps); for (int i = 1; i < entries.size(); ++i) { MessageHeader mh = (MessageHeader) entries.elementAt(i); mh.print(ps); } } public static boolean isManifestName(String name) { // remove leading / if (name.charAt(0) == '/') { name = name.substring(1, name.length()); } // case insensitive name = name.toUpperCase(); if (name.equals("META-INF/MANIFEST.MF")) { return true; } return false; }}
/*
* Copyright (c) 1996, 1999, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.jar;
import java.io.*;
import java.util.*;
import java.security.*;
import sun.net.www.MessageHeader;
import sun.misc.BASE64Encoder;
import sun.misc.BASE64Decoder;
/**
* This is OBSOLETE. DO NOT USE THIS. Use java.util.jar.Manifest
* instead. It has to stay here because some apps (namely HJ and HJV)
* call directly into it.
*
* @author David Brown
* @author Benjamin Renaud
*/
public class Manifest {
/* list of headers that all pertain to a particular
* file in the archive
*/
private Vector entries = new Vector();
private byte[] tmpbuf = new byte[512];
/* a hashtable of entries, for fast lookup */
private Hashtable tableEntries = new Hashtable();
static final String[] hashes = {"SHA"};
static final byte[] EOL = {(byte)'\r', (byte)'\n'};
static final boolean debug = false;
static final String VERSION = "1.0";
static final void debug(String s) {
if (debug)
System.out.println("man> " + s);
}
public Manifest() {}
public Manifest(byte[] bytes) throws IOException {
this(new ByteArrayInputStream(bytes), false);
}
public Manifest(InputStream is) throws IOException {
this(is, true);
}
/**
* Parse a manifest from a stream, optionally computing hashes
* for the files.
*/
public Manifest(InputStream is, boolean compute) throws IOException {
if (!is.markSupported()) {
is = new BufferedInputStream(is);
}
/* do not rely on available() here! */
while (true) {
is.mark(1);
if (is.read() == -1) { // EOF
break;
}
is.reset();
MessageHeader m = new MessageHeader(is);
if (compute) {
doHashes(m);
}
addEntry(m);
}
}
/* recursively generate manifests from directory tree */
public Manifest(String[] files) throws IOException {
MessageHeader globals = new MessageHeader();
globals.add("Manifest-Version", VERSION);
String jdkVersion = System.getProperty("java.version");
globals.add("Created-By", "Manifest JDK "+jdkVersion);
addEntry(globals);
addFiles(null, files);
}
public void addEntry(MessageHeader entry) {
entries.addElement(entry);
String name = entry.findValue("Name");
debug("addEntry for name: "+name);
if (name != null) {
tableEntries.put(name, entry);
}
}
public MessageHeader getEntry(String name) {
return (MessageHeader) tableEntries.get(name);
}
public MessageHeader entryAt(int i) {
return (MessageHeader) entries.elementAt(i);
}
public Enumeration entries() {
return entries.elements();
}
public void addFiles(File dir, String[] files) throws IOException {
if (files == null)
return;
for (int i = 0; i < files.length; i++) {
File file;
if (dir == null) {
file = new File(files[i]);
} else {
file = new File(dir, files[i]);
}
if (file.isDirectory()) {
addFiles(file, file.list());
} else {
addFile(file);
}
}
}
/**
* File names are represented internally using "/";
* they are converted to the local format for anything else
*/
private final String stdToLocal(String name) {
return name.replace('/', java.io.File.separatorChar);
}
private final String localToStd(String name) {
name = name.replace(java.io.File.separatorChar, '/');
if (name.startsWith("./"))
name = name.substring(2);
else if (name.startsWith("/"))
name = name.substring(1);
return name;
}
public void addFile(File f) throws IOException {
String stdName = localToStd(f.getPath());
if (tableEntries.get(stdName) == null) {
MessageHeader mh = new MessageHeader();
mh.add("Name", stdName);
addEntry(mh);
}
}
public void doHashes(MessageHeader mh) throws IOException {
// If unnamed or is a directory return immediately
String name = mh.findValue("Name");
if (name == null || name.endsWith("/")) {
return;
}
BASE64Encoder enc = new BASE64Encoder();
/* compute hashes, write over any other "Hash-Algorithms" (?) */
for (int j = 0; j < hashes.length; ++j) {
InputStream is = new FileInputStream(stdToLocal(name));
try {
MessageDigest dig = MessageDigest.getInstance(hashes[j]);
int len;
while ((len = is.read(tmpbuf, 0, tmpbuf.length)) != -1) {
dig.update(tmpbuf, 0, len);
}
mh.set(hashes[j] + "-Digest", enc.encode(dig.digest()));
} catch (NoSuchAlgorithmException e) {
throw new JarException("Digest algorithm " + hashes[j] +
" not available.");
} finally {
is.close();
}
}
}
/* Add a manifest file at current position in a stream
*/
public void stream(OutputStream os) throws IOException {
PrintStream ps;
if (os instanceof PrintStream) {
ps = (PrintStream) os;
} else {
ps = new PrintStream(os);
}
/* the first header in the file should be the global one.
* It should say "Manifest-Version: x.x"; if not add it
*/
MessageHeader globals = (MessageHeader) entries.elementAt(0);
if (globals.findValue("Manifest-Version") == null) {
/* Assume this is a user-defined manifest. If it has a Name: <..>
* field, then it is not global, in which case we just add our own
* global Manifest-version: <version>
* If the first MessageHeader has no Name: <..>, we assume it
* is a global header and so prepend Manifest to it.
*/
String jdkVersion = System.getProperty("java.version");
if (globals.findValue("Name") == null) {
globals.prepend("Manifest-Version", VERSION);
globals.add("Created-By", "Manifest JDK "+jdkVersion);
} else {
ps.print("Manifest-Version: "+VERSION+"\r\n"+
"Created-By: "+jdkVersion+"\r\n\r\n");
}
ps.flush();
}
globals.print(ps);
for (int i = 1; i < entries.size(); ++i) {
MessageHeader mh = (MessageHeader) entries.elementAt(i);
mh.print(ps);
}
}
public static boolean isManifestName(String name) {
// remove leading /
if (name.charAt(0) == '/') {
name = name.substring(1, name.length());
}
// case insensitive
name = name.toUpperCase();
if (name.equals("META-INF/MANIFEST.MF")) {
return true;
}
return false;
}
}