Allow 'java -jar' to work with signed nested jars
Fix RandomAccessJarFile to correctly read certificate information as jar entries are loaded. This change allows signed nested jars to be used as JCE providers.
This commit is contained in:
parent
5c6dd52e9a
commit
6220aba983
|
|
@ -0,0 +1,60 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-2013 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed 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 org.springframework.boot.loader.data;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link RandomAccessData} implementation backed by a byte array.
|
||||||
|
*
|
||||||
|
* @author Phillip Webb
|
||||||
|
*/
|
||||||
|
public class ByteArrayRandomAccessData implements RandomAccessData {
|
||||||
|
|
||||||
|
private final byte[] bytes;
|
||||||
|
|
||||||
|
private final long offset;
|
||||||
|
|
||||||
|
private final long length;
|
||||||
|
|
||||||
|
public ByteArrayRandomAccessData(byte[] bytes) {
|
||||||
|
this(bytes, 0, (bytes == null ? 0 : bytes.length));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ByteArrayRandomAccessData(byte[] bytes, long offset, long length) {
|
||||||
|
this.bytes = (bytes == null ? new byte[0] : bytes);
|
||||||
|
this.offset = offset;
|
||||||
|
this.length = length;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InputStream getInputStream() {
|
||||||
|
return new ByteArrayInputStream(this.bytes, (int) this.offset, (int) this.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RandomAccessData getSubsection(long offset, long length) {
|
||||||
|
return new ByteArrayRandomAccessData(this.bytes, this.offset + offset, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getSize() {
|
||||||
|
return this.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -16,25 +16,25 @@
|
||||||
|
|
||||||
package org.springframework.boot.loader.jar;
|
package org.springframework.boot.loader.jar;
|
||||||
|
|
||||||
import java.util.zip.ZipEntry;
|
import java.util.jar.JarEntry;
|
||||||
|
|
||||||
import org.springframework.boot.loader.data.RandomAccessData;
|
import org.springframework.boot.loader.data.RandomAccessData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link ZipEntry} returned from a {@link RandomAccessDataZipInputStream}.
|
* A {@link JarEntry} returned from a {@link RandomAccessDataJarInputStream}.
|
||||||
*
|
*
|
||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
*/
|
*/
|
||||||
public class RandomAccessDataZipEntry extends ZipEntry {
|
public class RandomAccessDataJarEntry extends JarEntry {
|
||||||
|
|
||||||
private RandomAccessData data;
|
private RandomAccessData data;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create new {@link RandomAccessDataZipEntry} instance.
|
* Create new {@link RandomAccessDataJarEntry} instance.
|
||||||
* @param entry the underying {@link ZipEntry}
|
* @param entry the underlying {@link JarEntry}
|
||||||
* @param data the entry data
|
* @param data the entry data
|
||||||
*/
|
*/
|
||||||
public RandomAccessDataZipEntry(ZipEntry entry, RandomAccessData data) {
|
public RandomAccessDataJarEntry(JarEntry entry, RandomAccessData data) {
|
||||||
super(entry);
|
super(entry);
|
||||||
this.data = data;
|
this.data = data;
|
||||||
}
|
}
|
||||||
|
|
@ -44,6 +44,6 @@ public class RandomAccessDataZipEntry extends ZipEntry {
|
||||||
* @return the entry data
|
* @return the entry data
|
||||||
*/
|
*/
|
||||||
public RandomAccessData getData() {
|
public RandomAccessData getData() {
|
||||||
return data;
|
return this.data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -20,19 +20,19 @@ import java.io.FilterInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.PushbackInputStream;
|
import java.io.PushbackInputStream;
|
||||||
import java.util.zip.ZipEntry;
|
import java.util.jar.JarEntry;
|
||||||
import java.util.zip.ZipInputStream;
|
import java.util.jar.JarInputStream;
|
||||||
|
|
||||||
import org.springframework.boot.loader.data.RandomAccessData;
|
import org.springframework.boot.loader.data.RandomAccessData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link ZipInputStream} backed by {@link RandomAccessData}. Parsed entries provide
|
* A {@link JarInputStream} backed by {@link RandomAccessData}. Parsed entries provide
|
||||||
* access to the underlying data {@link RandomAccessData#getSubsection(long, long)
|
* access to the underlying data {@link RandomAccessData#getSubsection(long, long)
|
||||||
* subsection}.
|
* subsection}.
|
||||||
*
|
*
|
||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
*/
|
*/
|
||||||
public class RandomAccessDataZipInputStream extends ZipInputStream {
|
public class RandomAccessDataJarInputStream extends JarInputStream {
|
||||||
|
|
||||||
private RandomAccessData data;
|
private RandomAccessData data;
|
||||||
|
|
||||||
|
|
@ -41,8 +41,9 @@ public class RandomAccessDataZipInputStream extends ZipInputStream {
|
||||||
/**
|
/**
|
||||||
* Create a new {@link RandomAccessData} instance.
|
* Create a new {@link RandomAccessData} instance.
|
||||||
* @param data the source of the zip stream
|
* @param data the source of the zip stream
|
||||||
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
public RandomAccessDataZipInputStream(RandomAccessData data) {
|
public RandomAccessDataJarInputStream(RandomAccessData data) throws IOException {
|
||||||
this(data, new TrackingInputStream(data.getInputStream()));
|
this(data, new TrackingInputStream(data.getInputStream()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -51,17 +52,18 @@ public class RandomAccessDataZipInputStream extends ZipInputStream {
|
||||||
* {@link TrackingInputStream}.
|
* {@link TrackingInputStream}.
|
||||||
* @param data the source of the zip stream
|
* @param data the source of the zip stream
|
||||||
* @param trackingInputStream a tracking input stream
|
* @param trackingInputStream a tracking input stream
|
||||||
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
private RandomAccessDataZipInputStream(RandomAccessData data,
|
private RandomAccessDataJarInputStream(RandomAccessData data,
|
||||||
TrackingInputStream trackingInputStream) {
|
TrackingInputStream trackingInputStream) throws IOException {
|
||||||
super(trackingInputStream);
|
super(trackingInputStream);
|
||||||
this.data = data;
|
this.data = data;
|
||||||
this.trackingInputStream = trackingInputStream;
|
this.trackingInputStream = trackingInputStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RandomAccessDataZipEntry getNextEntry() throws IOException {
|
public RandomAccessDataJarEntry getNextEntry() throws IOException {
|
||||||
ZipEntry entry = super.getNextEntry();
|
JarEntry entry = (JarEntry) super.getNextEntry();
|
||||||
if (entry == null) {
|
if (entry == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
@ -69,7 +71,7 @@ public class RandomAccessDataZipInputStream extends ZipInputStream {
|
||||||
closeEntry();
|
closeEntry();
|
||||||
int end = getPosition();
|
int end = getPosition();
|
||||||
RandomAccessData entryData = this.data.getSubsection(start, end - start);
|
RandomAccessData entryData = this.data.getSubsection(start, end - start);
|
||||||
return new RandomAccessDataZipEntry(entry, entryData);
|
return new RandomAccessDataJarEntry(entry, entryData);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getPosition() throws IOException {
|
private int getPosition() throws IOException {
|
||||||
|
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
package org.springframework.boot.loader.jar;
|
package org.springframework.boot.loader.jar;
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.EOFException;
|
import java.io.EOFException;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
|
|
@ -31,14 +31,15 @@ import java.util.Collections;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.jar.Attributes;
|
|
||||||
import java.util.jar.JarEntry;
|
import java.util.jar.JarEntry;
|
||||||
import java.util.jar.JarFile;
|
import java.util.jar.JarFile;
|
||||||
import java.util.jar.Manifest;
|
import java.util.jar.Manifest;
|
||||||
import java.util.zip.Inflater;
|
import java.util.zip.Inflater;
|
||||||
import java.util.zip.InflaterInputStream;
|
import java.util.zip.InflaterInputStream;
|
||||||
import java.util.zip.ZipEntry;
|
import java.util.zip.ZipEntry;
|
||||||
|
import java.util.zip.ZipInputStream;
|
||||||
|
|
||||||
|
import org.springframework.boot.loader.data.ByteArrayRandomAccessData;
|
||||||
import org.springframework.boot.loader.data.RandomAccessData;
|
import org.springframework.boot.loader.data.RandomAccessData;
|
||||||
import org.springframework.boot.loader.data.RandomAccessDataFile;
|
import org.springframework.boot.loader.data.RandomAccessDataFile;
|
||||||
|
|
||||||
|
|
@ -63,6 +64,9 @@ import org.springframework.boot.loader.data.RandomAccessDataFile;
|
||||||
*/
|
*/
|
||||||
public class RandomAccessJarFile extends JarFile {
|
public class RandomAccessJarFile extends JarFile {
|
||||||
|
|
||||||
|
private static final RandomAccessData EMPTY_DATA = new ByteArrayRandomAccessData(
|
||||||
|
new byte[0]);
|
||||||
|
|
||||||
private final RandomAccessDataFile rootJarFile;
|
private final RandomAccessDataFile rootJarFile;
|
||||||
|
|
||||||
private RandomAccessData data;
|
private RandomAccessData data;
|
||||||
|
|
@ -113,19 +117,17 @@ public class RandomAccessJarFile extends JarFile {
|
||||||
this.data = data;
|
this.data = data;
|
||||||
this.size = data.getSize();
|
this.size = data.getSize();
|
||||||
|
|
||||||
RandomAccessDataZipInputStream inputStream = new RandomAccessDataZipInputStream(
|
RandomAccessDataJarInputStream inputStream = new RandomAccessDataJarInputStream(
|
||||||
data);
|
data);
|
||||||
try {
|
try {
|
||||||
RandomAccessDataZipEntry zipEntry = inputStream.getNextEntry();
|
RandomAccessDataJarEntry zipEntry = inputStream.getNextEntry();
|
||||||
while (zipEntry != null) {
|
while (zipEntry != null) {
|
||||||
addJarEntry(zipEntry, filters);
|
addJarEntry(zipEntry, filters);
|
||||||
zipEntry = inputStream.getNextEntry();
|
zipEntry = inputStream.getNextEntry();
|
||||||
}
|
}
|
||||||
this.manifest = findManifest();
|
this.manifest = inputStream.getManifest();
|
||||||
if (this.manifest != null) {
|
if (this.manifest != null) {
|
||||||
for (JarEntry containedEntry : this.entries.values()) {
|
addManifestEntries(filters);
|
||||||
((Entry) containedEntry).configure(this.manifest);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
|
|
@ -133,7 +135,36 @@ public class RandomAccessJarFile extends JarFile {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addJarEntry(RandomAccessDataZipEntry zipEntry, JarEntryFilter... filters) {
|
private void addManifestEntries(JarEntryFilter... filters) throws IOException {
|
||||||
|
|
||||||
|
Map<String, JarEntry> originalEntries = this.entries;
|
||||||
|
this.entries = new LinkedHashMap<String, JarEntry>();
|
||||||
|
|
||||||
|
ZipInputStream zipInputStream = new ZipInputStream(this.data.getInputStream());
|
||||||
|
try {
|
||||||
|
JarEntry entry;
|
||||||
|
do {
|
||||||
|
entry = new JarEntry(zipInputStream.getNextEntry());
|
||||||
|
entry.setMethod(ZipEntry.STORED);
|
||||||
|
RandomAccessData data = EMPTY_DATA;
|
||||||
|
if (MANIFEST_NAME.equals(entry.getName())) {
|
||||||
|
ByteArrayOutputStream manifestBytes = new ByteArrayOutputStream();
|
||||||
|
this.manifest.write(manifestBytes);
|
||||||
|
manifestBytes.close();
|
||||||
|
data = new ByteArrayRandomAccessData(manifestBytes.toByteArray());
|
||||||
|
}
|
||||||
|
addJarEntry(new RandomAccessDataJarEntry(entry, data), filters);
|
||||||
|
}
|
||||||
|
while (!MANIFEST_NAME.equals(entry.getName()));
|
||||||
|
|
||||||
|
this.entries.putAll(originalEntries);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
zipInputStream.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addJarEntry(RandomAccessDataJarEntry zipEntry, JarEntryFilter... filters) {
|
||||||
Entry jarEntry = new Entry(zipEntry);
|
Entry jarEntry = new Entry(zipEntry);
|
||||||
String name = zipEntry.getName();
|
String name = zipEntry.getName();
|
||||||
for (JarEntryFilter filter : filters) {
|
for (JarEntryFilter filter : filters) {
|
||||||
|
|
@ -145,16 +176,6 @@ public class RandomAccessJarFile extends JarFile {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Manifest findManifest() throws IOException {
|
|
||||||
ZipEntry manifestEntry = getEntry(MANIFEST_NAME);
|
|
||||||
if (manifestEntry != null) {
|
|
||||||
BufferedInputStream inputStream = new BufferedInputStream(
|
|
||||||
getInputStream(manifestEntry));
|
|
||||||
return new Manifest(inputStream);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected final RandomAccessDataFile getRootJarFile() {
|
protected final RandomAccessDataFile getRootJarFile() {
|
||||||
return this.rootJarFile;
|
return this.rootJarFile;
|
||||||
}
|
}
|
||||||
|
|
@ -305,17 +326,11 @@ public class RandomAccessJarFile extends JarFile {
|
||||||
|
|
||||||
private RandomAccessData entryData;
|
private RandomAccessData entryData;
|
||||||
|
|
||||||
private Attributes attributes;
|
public Entry(RandomAccessDataJarEntry entry) {
|
||||||
|
|
||||||
public Entry(RandomAccessDataZipEntry entry) {
|
|
||||||
super(entry);
|
super(entry);
|
||||||
this.entryData = entry.getData();
|
this.entryData = entry.getData();
|
||||||
}
|
}
|
||||||
|
|
||||||
void configure(Manifest manifest) {
|
|
||||||
this.attributes = manifest.getAttributes(getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
void setName(String name) {
|
void setName(String name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
@ -325,11 +340,6 @@ public class RandomAccessJarFile extends JarFile {
|
||||||
return (this.name == null ? super.getName() : this.name);
|
return (this.name == null ? super.getName() : this.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Attributes getAttributes() throws IOException {
|
|
||||||
return this.attributes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public RandomAccessData getData() {
|
public RandomAccessData getData() {
|
||||||
return this.entryData;
|
return this.entryData;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-2013 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed 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 org.springframework.boot.loader.data;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.springframework.util.FileCopyUtils;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for {@link ByteArrayRandomAccessData}.
|
||||||
|
*
|
||||||
|
* @author Phillip Webb
|
||||||
|
*/
|
||||||
|
public class ByteArrayRandomAccessDataTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetInputStream() throws Exception {
|
||||||
|
byte[] bytes = new byte[] { 0, 1, 2, 3, 4, 5 };
|
||||||
|
RandomAccessData data = new ByteArrayRandomAccessData(bytes);
|
||||||
|
assertThat(FileCopyUtils.copyToByteArray(data.getInputStream()), equalTo(bytes));
|
||||||
|
assertThat(data.getSize(), equalTo((long) bytes.length));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetSubsection() throws Exception {
|
||||||
|
byte[] bytes = new byte[] { 0, 1, 2, 3, 4, 5 };
|
||||||
|
RandomAccessData data = new ByteArrayRandomAccessData(bytes);
|
||||||
|
data = data.getSubsection(1, 4).getSubsection(1, 2);
|
||||||
|
assertThat(FileCopyUtils.copyToByteArray(data.getInputStream()),
|
||||||
|
equalTo(new byte[] { 2, 3 }));
|
||||||
|
assertThat(data.getSize(), equalTo(2L));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -32,15 +32,15 @@ import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.rules.TemporaryFolder;
|
import org.junit.rules.TemporaryFolder;
|
||||||
import org.springframework.boot.loader.data.RandomAccessDataFile;
|
import org.springframework.boot.loader.data.RandomAccessDataFile;
|
||||||
import org.springframework.boot.loader.jar.RandomAccessDataZipEntry;
|
import org.springframework.boot.loader.jar.RandomAccessDataJarEntry;
|
||||||
import org.springframework.boot.loader.jar.RandomAccessDataZipInputStream;
|
import org.springframework.boot.loader.jar.RandomAccessDataJarInputStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for {@link RandomAccessDataZipInputStream}.
|
* Tests for {@link RandomAccessDataJarInputStream}.
|
||||||
*
|
*
|
||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
*/
|
*/
|
||||||
public class RandomAccessDataZipInputStreamTests {
|
public class RandomAccessDataJarInputStreamTests {
|
||||||
|
|
||||||
@Rule
|
@Rule
|
||||||
public TemporaryFolder temporaryFolder = new TemporaryFolder();
|
public TemporaryFolder temporaryFolder = new TemporaryFolder();
|
||||||
|
|
@ -76,11 +76,11 @@ public class RandomAccessDataZipInputStreamTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void entryData() throws Exception {
|
public void entryData() throws Exception {
|
||||||
RandomAccessDataZipInputStream z = new RandomAccessDataZipInputStream(
|
RandomAccessDataJarInputStream z = new RandomAccessDataJarInputStream(
|
||||||
new RandomAccessDataFile(file));
|
new RandomAccessDataFile(file));
|
||||||
try {
|
try {
|
||||||
RandomAccessDataZipEntry entry1 = z.getNextEntry();
|
RandomAccessDataJarEntry entry1 = z.getNextEntry();
|
||||||
RandomAccessDataZipEntry entry2 = z.getNextEntry();
|
RandomAccessDataJarEntry entry2 = z.getNextEntry();
|
||||||
assertThat(entry1.getName(), equalTo("a"));
|
assertThat(entry1.getName(), equalTo("a"));
|
||||||
assertThat(entry1.getData().getSize(), equalTo(10L));
|
assertThat(entry1.getData().getSize(), equalTo(10L));
|
||||||
assertThat(entry2.getName(), equalTo("b"));
|
assertThat(entry2.getName(), equalTo("b"));
|
||||||
|
|
@ -25,6 +25,7 @@ import java.net.URL;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.jar.JarEntry;
|
import java.util.jar.JarEntry;
|
||||||
import java.util.jar.JarFile;
|
import java.util.jar.JarFile;
|
||||||
|
import java.util.jar.Manifest;
|
||||||
import java.util.zip.ZipEntry;
|
import java.util.zip.ZipEntry;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
|
|
@ -91,6 +92,13 @@ public class RandomAccessJarFileTests {
|
||||||
equalTo("j1"));
|
equalTo("j1"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getManifestEntry() throws Exception {
|
||||||
|
ZipEntry entry = this.jarFile.getJarEntry("META-INF/MANIFEST.MF");
|
||||||
|
Manifest manifest = new Manifest(this.jarFile.getInputStream(entry));
|
||||||
|
assertThat(manifest.getMainAttributes().getValue("Built-By"), equalTo("j1"));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getEntries() throws Exception {
|
public void getEntries() throws Exception {
|
||||||
Enumeration<JarEntry> entries = this.jarFile.entries();
|
Enumeration<JarEntry> entries = this.jarFile.entries();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue