emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/lang/ManifestInputStream.java
Rebasing the Inflater support on jzlib which, unlike GNU ClassPath, has correct implementation of Huffman code. Making the implementation more easily testable by turning Inflater and ZipInputStream into pure delegates. Current implementation is going to need proper long support.
2 * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
25 package org.apidesign.bck2brwsr.emul.lang;
27 import java.io.FilterInputStream;
28 import java.io.IOException;
29 import java.io.InputStream;
32 * A fast buffered input stream for parsing manifest files.
34 * Taken from java.util.jar.Manifest.FastInputStream and modified to be
35 * independent of other Manifest functionality.
37 public abstract class ManifestInputStream extends FilterInputStream {
39 private int count = 0;
42 protected ManifestInputStream(InputStream in) {
46 protected ManifestInputStream(InputStream in, int size) {
51 public int read() throws IOException {
58 return buf[pos++] & 0xff;
61 public int read(byte[] b, int off, int len) throws IOException {
62 int avail = count - pos;
64 if (len >= buf.length) {
65 return in.read(b, off, len);
76 System.arraycopy(buf, pos, b, off, len);
82 * Reads 'len' bytes from the input stream, or until an end-of-line
83 * is reached. Returns the number of bytes read.
85 public int readLine(byte[] b, int off, int len) throws IOException {
86 byte[] tbuf = this.buf;
89 int avail = count - pos;
102 int maxpos = tpos + n;
103 while (tpos < maxpos && tbuf[tpos++] != '\n') {
107 System.arraycopy(tbuf, pos, b, off, n);
111 if (tbuf[tpos - 1] == '\n') {
118 public byte peek() throws IOException {
123 return -1; // nothing left in buffer
128 public int readLine(byte[] b) throws IOException {
129 return readLine(b, 0, b.length);
132 public long skip(long n) throws IOException {
136 long avail = count - pos;
147 public int available() throws IOException {
148 return (count - pos) + in.available();
151 public void close() throws IOException {
159 private void fill() throws IOException {
161 int n = in.read(buf, 0, buf.length);
167 protected abstract String putValue(String key, String value);
169 public void readAttributes(byte[] lbuf) throws IOException {
170 ManifestInputStream is = this;
174 byte[] lastline = null;
176 while ((len = is.readLine(lbuf)) != -1) {
177 boolean lineContinued = false;
178 if (lbuf[--len] != '\n') {
179 throw new IOException("line too long");
181 if (len > 0 && lbuf[len - 1] == '\r') {
188 if (lbuf[0] == ' ') {
190 throw new IOException("misplaced continuation line");
192 lineContinued = true;
193 byte[] buf = new byte[lastline.length + len - 1];
194 System.arraycopy(lastline, 0, buf, 0, lastline.length);
195 System.arraycopy(lbuf, 1, buf, lastline.length, len - 1);
196 if (is.peek() == ' ') {
200 value = new String(buf, 0, buf.length, "UTF8");
203 while (lbuf[i++] != ':') {
205 throw new IOException("invalid header field");
208 if (lbuf[i++] != ' ') {
209 throw new IOException("invalid header field");
211 name = new String(lbuf, 0, 0, i - 2);
212 if (is.peek() == ' ') {
213 lastline = new byte[len - i];
214 System.arraycopy(lbuf, i, lastline, 0, len - i);
217 value = new String(lbuf, i, len - i, "UTF8");
220 if ((putValue(name, value) != null) && (!lineContinued)) {
221 throw new IOException("Duplicate name in Manifest: " + name + ".\n" + "Ensure that the manifest does not " + "have duplicate entries, and\n" + "that blank lines separate " + "individual sections in both your\n" + "manifest and in the META-INF/MANIFEST.MF " + "entry in the jar file.");
223 } catch (IllegalArgumentException e) {
224 throw new IOException("invalid header field name: " + name);