jdk/src/share/classes/sun/security/util/SignatureFileManifest.java
author weijun
Mon, 11 Apr 2011 10:22:17 +0800
changeset 9248 44d129a2adfa
permissions -rw-r--r--
7012160: read SF file in signed jar in streaming mode Reviewed-by: mullan
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
9248
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
     1
/*
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
     2
 * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
     4
 *
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    10
 *
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    15
 * accompanied this code).
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    16
 *
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    20
 *
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    23
 * questions.
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    24
 */
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    25
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    26
package sun.security.util;
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    27
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    28
import java.io.IOException;
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    29
import java.io.InputStream;
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    30
import java.util.Arrays;
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    31
import java.util.jar.Attributes;
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    32
import java.util.jar.Manifest;
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    33
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    34
/**
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    35
 * This class provides streaming mode reading of manifest files.
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    36
 * Used by {@link SignatureFileVerifier}.
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    37
 */
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    38
class SignatureFileManifest extends Manifest {
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    39
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    40
    /*
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    41
     * Reading a manifest into this object by calling update(byte[]) on chunks.
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    42
     * During the reading, the bytes are saved in (@code current} until a line
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    43
     * is complete and the key-value pair is saved in {@code currentAttr}. When
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    44
     * a section is complete, {@code consumeAttr} is called to merge
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    45
     * {@code currentAttr} into main attributes or a named entry.
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    46
     */
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    47
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    48
    // Internal state during update() style reading
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    49
    // 0. not in update mode
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    50
    // 1, in update mode but main attributes not completed yet
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    51
    // 2. main attributes completed, still reading the entries
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    52
    private int state = 0;
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    53
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    54
    // The partial line read
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    55
    private byte[] current;
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    56
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    57
    // Number of bytes in current
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    58
    private int currentPos = 0;
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    59
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    60
    // The current Attribute
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    61
    private Attributes currentAttr;
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    62
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    63
    /**
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    64
     * Reads a manifest in chunks.
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    65
     * <p>
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    66
     * This method must be called in a row, reading chunks from a single
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    67
     * manifest file by order. After all chunks are read, caller must call
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    68
     * {@code update(null)} to fully consume the manifest.
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    69
     * <p>
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    70
     * The entry names and attributes read will be merged in with the current
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    71
     * manifest entries. The {@link #read} method cannot be called inside a
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    72
     * row of update calls.
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    73
     * <p>
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    74
     * Along with the calls, caller can call {@link #getMainAttributes()},
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    75
     * {@link #getAttributes(java.lang.String)} or {@link #getEntries()}
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    76
     * to get already available contents. However, in order not to return
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    77
     * partial result, when the main attributes in the new manifest is not
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    78
     * consumed completely, {@link #getMainAttributes()} throws an
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    79
     * {@code IllegalStateException}. When a certain named entry is not
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    80
     * consumed completely, {@link #getAttributes(java.lang.String)}
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    81
     * returns the old {@code Attributes} for the name (if it exists).
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    82
     *
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    83
     * @param data null for last call, otherwise, feeding chunks
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    84
     * @param offset offset into data to begin read
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    85
     * @param length length of data after offset to read
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    86
     * @exception IOException if an I/O error has occurred
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    87
     * @exception IllegalStateException if {@code update(null)} is called
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    88
     * without any previous {@code update(non-null)} call
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    89
     */
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    90
    public void update(byte[] data, int offset, int length) throws IOException {
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    91
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    92
        // The last call
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    93
        if (data == null) {
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    94
            if (state == 0) {
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    95
                throw new IllegalStateException("No data to update");
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    96
            }
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    97
            // We accept manifest not ended with \n or \n\n
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    98
            if (hasLastByte()) {
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
    99
                consumeCurrent();
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   100
            }
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   101
            // We accept empty lines at the end
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   102
            if (!currentAttr.isEmpty()) {
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   103
                consumeAttr();
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   104
            }
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   105
            state = 0;  // back to non-update state
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   106
            current = null;
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   107
            currentAttr = null;
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   108
            return;
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   109
        }
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   110
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   111
        // The first call
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   112
        if (state == 0) {
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   113
            current = new byte[1024];
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   114
            currentAttr = super.getMainAttributes(); // the main attribute
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   115
            state = 1;
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   116
        }
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   117
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   118
        int end = offset + length;
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   119
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   120
        while (offset < end) {
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   121
            switch (data[offset]) {
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   122
                case '\r':
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   123
                    break;  // always skip
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   124
                case '\n':
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   125
                    if (hasLastByte() && lastByte() == '\n') {  // new section
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   126
                        consumeCurrent();
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   127
                        consumeAttr();
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   128
                        if (state == 1) {
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   129
                            state = 2;
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   130
                        }
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   131
                        currentAttr = new Attributes(2);
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   132
                    } else {
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   133
                        if (hasLastByte()) {
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   134
                            // save \n into current but do not parse,
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   135
                            // there might be a continuation later
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   136
                            ensureCapacity();
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   137
                            current[currentPos++] = data[offset];
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   138
                        } else if (state == 1) {
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   139
                            // there can be multiple empty lines between
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   140
                            // sections, but cannot be at the beginning
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   141
                            throw new IOException("invalid manifest format");
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   142
                        }
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   143
                    }
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   144
                    break;
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   145
                case ' ':
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   146
                    if (!hasLastByte()) {
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   147
                        throw new IOException("invalid manifest format");
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   148
                    } else if (lastByte() == '\n') {
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   149
                        currentPos--;   // continuation, remove last \n
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   150
                    } else {    // a very normal ' '
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   151
                        ensureCapacity();
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   152
                        current[currentPos++] = data[offset];
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   153
                    }
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   154
                    break;
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   155
                default:
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   156
                    if (hasLastByte() && lastByte() == '\n') {
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   157
                        // The start of a new pair, not continuation
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   158
                        consumeCurrent();   // the last line read
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   159
                    }
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   160
                    ensureCapacity();
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   161
                    current[currentPos++] = data[offset];
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   162
                    break;
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   163
            }
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   164
            offset++;
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   165
        }
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   166
    }
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   167
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   168
    /**
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   169
     * Returns the main Attributes for the Manifest.
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   170
     * @exception IllegalStateException the main attributes is being read
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   171
     * @return the main Attributes for the Manifest
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   172
     */
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   173
    public Attributes getMainAttributes() {
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   174
        if (state == 1) {
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   175
            throw new IllegalStateException();
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   176
        }
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   177
        return super.getMainAttributes();
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   178
    }
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   179
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   180
    /**
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   181
     * Reads the Manifest from the specified InputStream. The entry
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   182
     * names and attributes read will be merged in with the current
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   183
     * manifest entries.
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   184
     *
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   185
     * @param is the input stream
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   186
     * @exception IOException if an I/O error has occurred
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   187
     * @exception IllegalStateException if called between two {@link #update}
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   188
     * calls
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   189
     */
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   190
    public void read(InputStream is) throws IOException {
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   191
        if (state != 0) {
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   192
            throw new IllegalStateException("Cannot call read between updates");
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   193
        }
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   194
        super.read(is);
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   195
    }
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   196
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   197
    /*
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   198
     * ----------  Helper methods  -----------------
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   199
     */
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   200
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   201
    private void ensureCapacity() {
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   202
        if (currentPos >= current.length-1) {
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   203
            current = Arrays.copyOf(current, current.length*2);
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   204
        }
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   205
    }
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   206
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   207
    private boolean hasLastByte() {
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   208
        return currentPos > 0;
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   209
    }
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   210
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   211
    private byte lastByte() {
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   212
        return current[currentPos-1];
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   213
    }
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   214
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   215
    // Parse current as key:value and save into currentAttr.
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   216
    // There MUST be something inside current.
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   217
    private void consumeCurrent() throws IOException {
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   218
        // current normally has a \n end, except for the last line
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   219
        if (current[currentPos-1] == '\n') currentPos--;
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   220
        for (int i=0; i<currentPos; i++) {
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   221
            if (current[i] == ':') {
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   222
                String key = new String(current, 0, 0, i);
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   223
                i++;
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   224
                while (i < currentPos && current[i] == ' ') { i++; }
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   225
                String value = new String(current, i, currentPos-i, "UTF-8");
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   226
                currentAttr.putValue(key, value);
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   227
                currentPos = 0;
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   228
                return;
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   229
            }
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   230
        }
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   231
        throw new IOException("invalid header field");
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   232
    }
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   233
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   234
    // Merge currentAttr into Manifest
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   235
    private void consumeAttr() throws IOException {
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   236
        // Only needed for named entries. For the main attribute, key/value
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   237
        // is added into attr directly, but since getMainAttributes() throws
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   238
        // an exception, the partial data is not leaked.
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   239
        if (state != 1) {
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   240
            String name = currentAttr.getValue("Name");
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   241
            if (name != null) {
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   242
                currentAttr.remove(new Attributes.Name("Name"));
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   243
                Attributes old = getAttributes(name);
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   244
                if (old != null) old.putAll(currentAttr);
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   245
                else getEntries().put(name, currentAttr);
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   246
            } else {
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   247
                throw new IOException("invalid manifest format");
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   248
            }
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   249
        }
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   250
    }
44d129a2adfa 7012160: read SF file in signed jar in streaming mode
weijun
parents:
diff changeset
   251
}