alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (Manifest.java)

This example Java source code file (Manifest.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

created\-by, digest, file, hashtable, ioexception, jdk, manifest, manifest\-version, messageheader, name, net, network, printstream, security, string, util, vector, version, www

The Manifest.java Java example source code

/*
 * Copyright (c) 1996, 2013, 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 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 {

    /* list of headers that all pertain to a particular
     * file in the archive
     */
    private Vector<MessageHeader> entries = new Vector<>();
    private byte[] tmpbuf = new byte[512];
    /* a hashtable of entries, for fast lookup */
    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);
    }

    /**
     * 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 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 {
        // If unnamed or is a directory return immediately
        String name = mh.findValue("Name");
        if (name == null || name.endsWith("/")) {
            return;
        }


        /* 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", Base64.getMimeEncoder().encodeToString(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 = 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 = 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;
    }
}

Other Java examples (source code examples)

Here is a short list of links related to this Java Manifest.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.