001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package java.util.jar;
019:
020: import java.io.ByteArrayOutputStream;
021: import java.io.IOException;
022: import java.io.InputStream;
023: import java.io.OutputStream;
024: import java.util.zip.ZipEntry;
025: import java.util.zip.ZipInputStream;
026:
027: import org.apache.harmony.archive.util.Util;
028:
029: public class JarInputStream extends ZipInputStream {
030:
031: private Manifest manifest;
032:
033: private boolean eos = false;
034:
035: private JarEntry mEntry;
036:
037: private JarEntry jarEntry;
038:
039: private boolean isMeta;
040:
041: private JarVerifier verifier;
042:
043: private OutputStream verStream;
044:
045: /**
046: * Constructs a new JarInputStream from stream
047: */
048: public JarInputStream(InputStream stream, boolean verify)
049: throws IOException {
050: super (stream);
051: if (verify) {
052: verifier = new JarVerifier("JarInputStream"); //$NON-NLS-1$
053: }
054: if ((mEntry = getNextJarEntry()) == null) {
055: return;
056: }
057: String name = Util.toASCIIUpperCase(mEntry.getName());
058: if (name.equals(JarFile.META_DIR)) {
059: mEntry = null; // modifies behavior of getNextJarEntry()
060: closeEntry();
061: mEntry = getNextJarEntry();
062: name = mEntry.getName().toUpperCase();
063: }
064: if (name.equals(JarFile.MANIFEST_NAME)) {
065: mEntry = null;
066: manifest = new Manifest(this , verify);
067: closeEntry();
068: if (verify) {
069: verifier.setManifest(manifest);
070: if (manifest != null) {
071: verifier.mainAttributesChunk = manifest
072: .getMainAttributesChunk();
073: }
074: }
075:
076: } else {
077: Attributes temp = new Attributes(3);
078: temp.map.put("hidden", null); //$NON-NLS-1$
079: mEntry.setAttributes(temp);
080: /*
081: * if not from the first entry, we will not get enough
082: * information,so no verify will be taken out.
083: */
084: verifier = null;
085: }
086: }
087:
088: public JarInputStream(InputStream stream) throws IOException {
089: this (stream, true);
090: }
091:
092: /**
093: * Returns the Manifest object associated with this JarInputStream or null
094: * if no manifest entry exists.
095: *
096: * @return java.util.jar.Manifest
097: */
098: public Manifest getManifest() {
099: return manifest;
100: }
101:
102: /**
103: * Returns the next JarEntry contained in this stream or null if no more
104: * entries are present.
105: *
106: * @return java.util.jar.JarEntry
107: * @exception java.io.IOException
108: * If an error occurs while reading the entry
109: */
110: public JarEntry getNextJarEntry() throws IOException {
111: return (JarEntry) getNextEntry();
112: }
113:
114: @Override
115: public int read(byte[] buffer, int offset, int length)
116: throws IOException {
117: if (mEntry != null) {
118: return -1;
119: }
120: int r = super .read(buffer, offset, length);
121: if (verStream != null && !eos) {
122: if (r == -1) {
123: eos = true;
124: if (verifier != null) {
125: if (isMeta) {
126: verifier.addMetaEntry(jarEntry.getName(),
127: ((ByteArrayOutputStream) verStream)
128: .toByteArray());
129: try {
130: verifier.readCertificates();
131: } catch (SecurityException e) {
132: verifier = null;
133: throw e;
134: }
135: } else {
136: verifier.verifySignatures(
137: (JarVerifier.VerifierEntry) verStream,
138: jarEntry);
139: }
140: }
141: } else {
142: verStream.write(buffer, offset, r);
143: }
144: }
145: return r;
146: }
147:
148: /**
149: * Returns the next ZipEntry contained in this stream or null if no more
150: * entries are present.
151: *
152: * @return java.util.zip.ZipEntry
153: * @exception java.io.IOException
154: * If an error occurs while reading the entry
155: */
156: @Override
157: public ZipEntry getNextEntry() throws IOException {
158: if (mEntry != null) {
159: jarEntry = mEntry;
160: mEntry = null;
161: jarEntry.setAttributes(null);
162: } else {
163: jarEntry = (JarEntry) super .getNextEntry();
164: if (jarEntry == null) {
165: return null;
166: }
167: if (verifier != null) {
168: isMeta = Util.toASCIIUpperCase(jarEntry.getName())
169: .startsWith(JarFile.META_DIR);
170: if (isMeta) {
171: verStream = new ByteArrayOutputStream();
172: } else {
173: verStream = verifier.initEntry(jarEntry.getName());
174: }
175: }
176: }
177: eos = false;
178: return jarEntry;
179: }
180:
181: @Override
182: protected ZipEntry createZipEntry(String name) {
183: JarEntry entry = new JarEntry(name);
184: if (manifest != null) {
185: entry.setAttributes(manifest.getAttributes(name));
186: }
187: return entry;
188: }
189: }
|