| 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
 | 
 | 
package sun.tools.jar;  | 
 | 
 | 
 | 
import java.io.*;  | 
 | 
import java.util.*;  | 
 | 
import java.security.*;  | 
 | 
 | 
 | 
import sun.net.www.MessageHeader;  | 
 | 
import java.util.Base64;  | 
 | 
 | 
 | 
/**  | 
 | 
 * 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 { | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    private Vector<MessageHeader> entries = new Vector<>();  | 
 | 
    private byte[] tmpbuf = new byte[512];  | 
 | 
      | 
 | 
    private Hashtable<String, MessageHeader> 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);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public Manifest(InputStream is, boolean compute) throws IOException { | 
 | 
        if (!is.markSupported()) { | 
 | 
            is = new BufferedInputStream(is);  | 
 | 
        }  | 
 | 
          | 
 | 
        while (true) { | 
 | 
            is.mark(1);  | 
 | 
            if (is.read() == -1) {  | 
 | 
                break;  | 
 | 
            }  | 
 | 
            is.reset();  | 
 | 
            MessageHeader m = new MessageHeader(is);  | 
 | 
            if (compute) { | 
 | 
                doHashes(m);  | 
 | 
            }  | 
 | 
            addEntry(m);  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
    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 tableEntries.get(name);  | 
 | 
    }  | 
 | 
 | 
 | 
    public MessageHeader entryAt(int i) { | 
 | 
        return entries.elementAt(i);  | 
 | 
    }  | 
 | 
 | 
 | 
    public Enumeration<MessageHeader> 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 { | 
 | 
          | 
 | 
        String name = mh.findValue("Name"); | 
 | 
        if (name == null || name.endsWith("/")) { | 
 | 
            return;  | 
 | 
        }  | 
 | 
 | 
 | 
 | 
 | 
          | 
 | 
        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", Base64.getMimeEncoder().encodeToString(dig.digest()));  | 
 | 
            } catch (NoSuchAlgorithmException e) { | 
 | 
                throw new JarException("Digest algorithm " + hashes[j] + | 
 | 
                                       " not available.");  | 
 | 
            } finally { | 
 | 
                is.close();  | 
 | 
            }  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
     */  | 
 | 
    public void stream(OutputStream os) throws IOException { | 
 | 
 | 
 | 
        PrintStream ps;  | 
 | 
        if (os instanceof PrintStream) { | 
 | 
            ps = (PrintStream) os;  | 
 | 
        } else { | 
 | 
            ps = new PrintStream(os);  | 
 | 
        }  | 
 | 
 | 
 | 
          | 
 | 
 | 
 | 
         */  | 
 | 
        MessageHeader globals = entries.elementAt(0);  | 
 | 
 | 
 | 
        if (globals.findValue("Manifest-Version") == null) { | 
 | 
              | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
             */  | 
 | 
            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 = entries.elementAt(i);  | 
 | 
            mh.print(ps);  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    public static boolean isManifestName(String name) { | 
 | 
 | 
 | 
          | 
 | 
        if (name.charAt(0) == '/') { | 
 | 
            name = name.substring(1, name.length());  | 
 | 
        }  | 
 | 
          | 
 | 
        name = name.toUpperCase();  | 
 | 
 | 
 | 
        if (name.equals("META-INF/MANIFEST.MF")) { | 
 | 
            return true;  | 
 | 
        }  | 
 | 
        return false;  | 
 | 
    }  | 
 | 
}  |