java.util.jar.JarFile Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jtransc-rt Show documentation
Show all versions of jtransc-rt Show documentation
JVM AOT compiler currently generating JavaScript, C++, Haxe, with initial focus on Kotlin and games.
The newest version!
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package java.util.jar;
import com.jtransc.io.JTranscIoTools;
import java.io.File;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
/**
* {@code JarFile} is used to read jar entries and their associated data from
* jar files.
*
* @see JarInputStream
* @see JarEntry
*/
public class JarFile extends ZipFile {
/**
* The MANIFEST file name.
*/
public static final String MANIFEST_NAME = "META-INF/MANIFEST.MF";
// The directory containing the manifest.
static final String META_DIR = "META-INF/";
// The manifest after it has been read from the JAR.
private Manifest manifest;
// The entry for the MANIFEST.MF file before it is read.
private ZipEntry manifestEntry;
private boolean closed = false;
static final class JarFileInputStream extends FilterInputStream {
private long count;
private ZipEntry zipEntry;
private boolean done = false;
JarFileInputStream(InputStream is, ZipEntry ze) {
super(is);
zipEntry = ze;
count = zipEntry.getSize();
}
@Override
public int read() throws IOException {
if (done) {
return -1;
}
if (count > 0) {
int r = super.read();
if (r != -1) {
count--;
} else {
count = 0;
}
if (count == 0) {
done = true;
}
return r;
} else {
done = true;
return -1;
}
}
@Override
public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
if (done) {
return -1;
}
if (count > 0) {
int r = super.read(buffer, byteOffset, byteCount);
if (r != -1) {
int size = r;
if (count < size) {
size = (int) count;
}
count -= size;
} else {
count = 0;
}
if (count == 0) {
done = true;
}
return r;
} else {
done = true;
return -1;
}
}
@Override
public int available() throws IOException {
if (done) {
return 0;
}
return super.available();
}
@Override
public long skip(long byteCount) throws IOException {
return JTranscIoTools.skipByReading(this, byteCount);
}
}
/**
* Create a new {@code JarFile} using the contents of the specified file.
*
* @param file the JAR file as {@link File}.
* @throws IOException If the file cannot be read.
*/
public JarFile(File file) throws IOException {
this(file, true);
}
/**
* Create a new {@code JarFile} using the contents of the specified file.
*
* @param file the JAR file as {@link File}.
* @param verify if this JAR file is signed whether it must be verified.
* @throws IOException If the file cannot be read.
*/
public JarFile(File file, boolean verify) throws IOException {
super(file);
if (verify) {
}
readMetaEntries();
}
/**
* Create a new {@code JarFile} using the contents of file.
*
* @param file the JAR file as {@link File}.
* @param verify if this JAR filed is signed whether it must be verified.
* @param mode the mode to use, either {@link ZipFile#OPEN_READ OPEN_READ} or
* {@link ZipFile#OPEN_DELETE OPEN_DELETE}.
* @throws IOException If the file cannot be read.
*/
public JarFile(File file, boolean verify, int mode) throws IOException {
super(file, mode);
if (verify) {
}
readMetaEntries();
}
/**
* Create a new {@code JarFile} from the contents of the file specified by
* filename.
*
* @param filename the file name referring to the JAR file.
* @throws IOException if file name cannot be opened for reading.
*/
public JarFile(String filename) throws IOException {
this(filename, true);
}
/**
* Create a new {@code JarFile} from the contents of the file specified by
* {@code filename}.
*
* @param filename the file name referring to the JAR file.
* @param verify if this JAR filed is signed whether it must be verified.
* @throws IOException If file cannot be opened or read.
*/
public JarFile(String filename, boolean verify) throws IOException {
super(filename);
if (verify) {
}
readMetaEntries();
}
/**
* Return an enumeration containing the {@code JarEntrys} contained in this
* {@code JarFile}.
*
* @return the {@code Enumeration} containing the JAR entries.
* @throws IllegalStateException if this {@code JarFile} is closed.
*/
@Override
public Enumeration entries() {
class JarFileEnumerator implements Enumeration {
Enumeration extends ZipEntry> ze;
JarFile jf;
JarFileEnumerator(Enumeration extends ZipEntry> zenum, JarFile jf) {
ze = zenum;
this.jf = jf;
}
public boolean hasMoreElements() {
return ze.hasMoreElements();
}
public JarEntry nextElement() {
JarEntry je = new JarEntry(ze.nextElement());
je.parentJar = jf;
return je;
}
}
return new JarFileEnumerator(super.entries(), this);
}
/**
* Return the {@code JarEntry} specified by its name or {@code null} if no
* such entry exists.
*
* @param name the name of the entry in the JAR file.
* @return the JAR entry defined by the name.
*/
public JarEntry getJarEntry(String name) {
return (JarEntry) getEntry(name);
}
/**
* Returns the {@code Manifest} object associated with this {@code JarFile}
* or {@code null} if no MANIFEST entry exists.
*
* @return the MANIFEST.
* @throws IOException if an error occurs reading the MANIFEST file.
* @throws IllegalStateException if the jar file is closed.
* @see Manifest
*/
public Manifest getManifest() throws IOException {
if (closed) {
throw new IllegalStateException("JarFile has been closed");
}
if (manifest != null) {
return manifest;
}
try {
try (InputStream is = super.getInputStream(manifestEntry)) {
manifest = new Manifest(is, false);
}
manifestEntry = null; // Can discard the entry now.
} catch (NullPointerException e) {
manifestEntry = null;
}
return manifest;
}
/**
* Called by the JarFile constructors, this method reads the contents of the
* file's META-INF/ directory and picks out the MANIFEST.MF file and
* verifier signature files if they exist. Any signature files found are
* registered with the verifier.
*
* @throws IOException if there is a problem reading the jar file entries.
*/
private void readMetaEntries() throws IOException {
// Get all meta directory entries
ZipEntry[] metaEntries = getMetaEntriesImpl();
if (metaEntries == null) {
return;
}
boolean signed = false;
for (ZipEntry entry : metaEntries) {
String entryName = entry.getName();
// Is this the entry for META-INF/MANIFEST.MF ?
if (manifestEntry == null && entryName.equalsIgnoreCase(MANIFEST_NAME)) {
manifestEntry = entry;
// If there is no verifier then we don't need to look any further.
break;
} else {
// Is this an entry that the verifier needs?
}
}
// If there were no signature files, then no verifier work to do.
}
private static boolean endsWithIgnoreCase(String s, String suffix) {
return s.regionMatches(true, s.length() - suffix.length(), suffix, 0, suffix.length());
}
/**
* Return an {@code InputStream} for reading the decompressed contents of
* ZIP entry.
*
* @param ze the ZIP entry to be read.
* @return the input stream to read from.
* @throws IOException if an error occurred while creating the input stream.
*/
@Override
public InputStream getInputStream(ZipEntry ze) throws IOException {
if (manifestEntry != null) {
getManifest();
}
InputStream in = super.getInputStream(ze);
if (in == null) {
return null;
}
if (ze.getSize() == -1) {
return in;
}
return new JarFileInputStream(in, ze);
}
/**
* Return the {@code JarEntry} specified by name or {@code null} if no such
* entry exists.
*
* @param name the name of the entry in the JAR file.
* @return the ZIP entry extracted.
*/
@Override
public ZipEntry getEntry(String name) {
ZipEntry ze = super.getEntry(name);
if (ze == null) {
return ze;
}
JarEntry je = new JarEntry(ze);
je.parentJar = this;
return je;
}
/**
* Returns all the ZipEntry's that relate to files in the
* JAR's META-INF directory.
*
* @return the list of ZipEntry's or {@code null} if there are none.
*/
private ZipEntry[] getMetaEntriesImpl() {
List list = new ArrayList(8);
Enumeration extends ZipEntry> allEntries = entries();
while (allEntries.hasMoreElements()) {
ZipEntry ze = allEntries.nextElement();
if (ze.getName().startsWith(META_DIR)
&& ze.getName().length() > META_DIR.length()) {
list.add(ze);
}
}
if (list.size() == 0) {
return null;
}
ZipEntry[] result = new ZipEntry[list.size()];
list.toArray(result);
return result;
}
/**
* Closes this {@code JarFile}.
*
* @throws IOException if an error occurs.
*/
@Override
public void close() throws IOException {
super.close();
closed = true;
}
}