|
|
@ -19,18 +19,25 @@ package org.springframework.boot.loader.jar;
|
|
|
|
import java.io.File;
|
|
|
|
import java.io.File;
|
|
|
|
import java.io.FileOutputStream;
|
|
|
|
import java.io.FileOutputStream;
|
|
|
|
import java.io.IOException;
|
|
|
|
import java.io.IOException;
|
|
|
|
|
|
|
|
import java.io.InputStream;
|
|
|
|
import java.net.MalformedURLException;
|
|
|
|
import java.net.MalformedURLException;
|
|
|
|
|
|
|
|
import java.net.URL;
|
|
|
|
|
|
|
|
import java.security.Permission;
|
|
|
|
|
|
|
|
import java.util.EnumSet;
|
|
|
|
|
|
|
|
import java.util.Enumeration;
|
|
|
|
|
|
|
|
import java.util.Set;
|
|
|
|
import java.util.jar.JarOutputStream;
|
|
|
|
import java.util.jar.JarOutputStream;
|
|
|
|
|
|
|
|
import java.util.jar.Manifest;
|
|
|
|
import java.util.zip.ZipEntry;
|
|
|
|
import java.util.zip.ZipEntry;
|
|
|
|
|
|
|
|
|
|
|
|
import org.junit.jupiter.api.BeforeEach;
|
|
|
|
import org.junit.jupiter.api.BeforeEach;
|
|
|
|
import org.junit.jupiter.api.Test;
|
|
|
|
import org.junit.jupiter.api.Test;
|
|
|
|
import org.junit.jupiter.api.io.TempDir;
|
|
|
|
import org.junit.jupiter.api.io.TempDir;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import org.springframework.boot.loader.jar.JarFileWrapperTests.SpyJarFile.Call;
|
|
|
|
|
|
|
|
|
|
|
|
import static org.assertj.core.api.Assertions.assertThat;
|
|
|
|
import static org.assertj.core.api.Assertions.assertThat;
|
|
|
|
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
|
|
|
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
|
|
|
import static org.mockito.Mockito.spy;
|
|
|
|
|
|
|
|
import static org.mockito.Mockito.verify;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* Tests for {@link JarFileWrapper}.
|
|
|
|
* Tests for {@link JarFileWrapper}.
|
|
|
@ -39,13 +46,13 @@ import static org.mockito.Mockito.verify;
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
class JarFileWrapperTests {
|
|
|
|
class JarFileWrapperTests {
|
|
|
|
|
|
|
|
|
|
|
|
private JarFile parent;
|
|
|
|
private SpyJarFile parent;
|
|
|
|
|
|
|
|
|
|
|
|
private JarFileWrapper wrapper;
|
|
|
|
private JarFileWrapper wrapper;
|
|
|
|
|
|
|
|
|
|
|
|
@BeforeEach
|
|
|
|
@BeforeEach
|
|
|
|
void setup(@TempDir File temp) throws IOException {
|
|
|
|
void setup(@TempDir File temp) throws IOException {
|
|
|
|
this.parent = spy(new JarFile(createTempJar(temp)));
|
|
|
|
this.parent = new SpyJarFile(createTempJar(temp));
|
|
|
|
this.wrapper = new JarFileWrapper(this.parent);
|
|
|
|
this.wrapper = new JarFileWrapper(this.parent);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -58,68 +65,68 @@ class JarFileWrapperTests {
|
|
|
|
@Test
|
|
|
|
@Test
|
|
|
|
void getUrlDelegatesToParent() throws MalformedURLException {
|
|
|
|
void getUrlDelegatesToParent() throws MalformedURLException {
|
|
|
|
this.wrapper.getUrl();
|
|
|
|
this.wrapper.getUrl();
|
|
|
|
verify(this.parent).getUrl();
|
|
|
|
this.parent.verify(Call.GET_URL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
@Test
|
|
|
|
void getTypeDelegatesToParent() {
|
|
|
|
void getTypeDelegatesToParent() {
|
|
|
|
this.wrapper.getType();
|
|
|
|
this.wrapper.getType();
|
|
|
|
verify(this.parent).getType();
|
|
|
|
this.parent.verify(Call.GET_TYPE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
@Test
|
|
|
|
void getPermissionDelegatesToParent() {
|
|
|
|
void getPermissionDelegatesToParent() {
|
|
|
|
this.wrapper.getPermission();
|
|
|
|
this.wrapper.getPermission();
|
|
|
|
verify(this.parent).getPermission();
|
|
|
|
this.parent.verify(Call.GET_PERMISSION);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
@Test
|
|
|
|
void getManifestDelegatesToParent() throws IOException {
|
|
|
|
void getManifestDelegatesToParent() throws IOException {
|
|
|
|
this.wrapper.getManifest();
|
|
|
|
this.wrapper.getManifest();
|
|
|
|
verify(this.parent).getManifest();
|
|
|
|
this.parent.verify(Call.GET_MANIFEST);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
@Test
|
|
|
|
void entriesDelegatesToParent() {
|
|
|
|
void entriesDelegatesToParent() {
|
|
|
|
this.wrapper.entries();
|
|
|
|
this.wrapper.entries();
|
|
|
|
verify(this.parent).entries();
|
|
|
|
this.parent.verify(Call.ENTRIES);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
@Test
|
|
|
|
void getJarEntryDelegatesToParent() {
|
|
|
|
void getJarEntryDelegatesToParent() {
|
|
|
|
this.wrapper.getJarEntry("test");
|
|
|
|
this.wrapper.getJarEntry("test");
|
|
|
|
verify(this.parent).getJarEntry("test");
|
|
|
|
this.parent.verify(Call.GET_JAR_ENTRY);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
@Test
|
|
|
|
void getEntryDelegatesToParent() {
|
|
|
|
void getEntryDelegatesToParent() {
|
|
|
|
this.wrapper.getEntry("test");
|
|
|
|
this.wrapper.getEntry("test");
|
|
|
|
verify(this.parent).getEntry("test");
|
|
|
|
this.parent.verify(Call.GET_ENTRY);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
@Test
|
|
|
|
void getInputStreamDelegatesToParent() throws IOException {
|
|
|
|
void getInputStreamDelegatesToParent() throws IOException {
|
|
|
|
this.wrapper.getInputStream();
|
|
|
|
this.wrapper.getInputStream();
|
|
|
|
verify(this.parent).getInputStream();
|
|
|
|
this.parent.verify(Call.GET_INPUT_STREAM);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
@Test
|
|
|
|
void getEntryInputStreamDelegatesToParent() throws IOException {
|
|
|
|
void getEntryInputStreamDelegatesToParent() throws IOException {
|
|
|
|
ZipEntry entry = new ZipEntry("test");
|
|
|
|
ZipEntry entry = new ZipEntry("test");
|
|
|
|
this.wrapper.getInputStream(entry);
|
|
|
|
this.wrapper.getInputStream(entry);
|
|
|
|
verify(this.parent).getInputStream(entry);
|
|
|
|
this.parent.verify(Call.GET_ENTRY_INPUT_STREAM);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
@Test
|
|
|
|
void getCommentDelegatesToParent() {
|
|
|
|
void getCommentDelegatesToParent() {
|
|
|
|
this.wrapper.getComment();
|
|
|
|
this.wrapper.getComment();
|
|
|
|
verify(this.parent).getComment();
|
|
|
|
this.parent.verify(Call.GET_COMMENT);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
@Test
|
|
|
|
void sizeDelegatesToParent() {
|
|
|
|
void sizeDelegatesToParent() {
|
|
|
|
this.wrapper.size();
|
|
|
|
this.wrapper.size();
|
|
|
|
verify(this.parent).size();
|
|
|
|
this.parent.verify(Call.SIZE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
@Test
|
|
|
@ -137,4 +144,117 @@ class JarFileWrapperTests {
|
|
|
|
.isThrownBy(() -> JarFileWrapper.class.getDeclaredMethod("close"));
|
|
|
|
.isThrownBy(() -> JarFileWrapper.class.getDeclaredMethod("close"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* {@link JarFile} that we can spy (even on Java 11+)
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
static class SpyJarFile extends JarFile {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private final Set<Call> calls = EnumSet.noneOf(Call.class);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
SpyJarFile(File file) throws IOException {
|
|
|
|
|
|
|
|
super(file);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
|
|
Permission getPermission() {
|
|
|
|
|
|
|
|
mark(Call.GET_PERMISSION);
|
|
|
|
|
|
|
|
return super.getPermission();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
|
|
public Manifest getManifest() throws IOException {
|
|
|
|
|
|
|
|
mark(Call.GET_MANIFEST);
|
|
|
|
|
|
|
|
return super.getManifest();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
|
|
public Enumeration<java.util.jar.JarEntry> entries() {
|
|
|
|
|
|
|
|
mark(Call.ENTRIES);
|
|
|
|
|
|
|
|
return super.entries();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
|
|
public JarEntry getJarEntry(String name) {
|
|
|
|
|
|
|
|
mark(Call.GET_JAR_ENTRY);
|
|
|
|
|
|
|
|
return super.getJarEntry(name);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
|
|
public ZipEntry getEntry(String name) {
|
|
|
|
|
|
|
|
mark(Call.GET_ENTRY);
|
|
|
|
|
|
|
|
return super.getEntry(name);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
|
|
InputStream getInputStream() throws IOException {
|
|
|
|
|
|
|
|
mark(Call.GET_INPUT_STREAM);
|
|
|
|
|
|
|
|
return super.getInputStream();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
|
|
InputStream getInputStream(String name) throws IOException {
|
|
|
|
|
|
|
|
mark(Call.GET_ENTRY_INPUT_STREAM);
|
|
|
|
|
|
|
|
return super.getInputStream(name);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
|
|
public String getComment() {
|
|
|
|
|
|
|
|
mark(Call.GET_COMMENT);
|
|
|
|
|
|
|
|
return super.getComment();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
|
|
public int size() {
|
|
|
|
|
|
|
|
mark(Call.SIZE);
|
|
|
|
|
|
|
|
return super.size();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
|
|
public URL getUrl() throws MalformedURLException {
|
|
|
|
|
|
|
|
mark(Call.GET_URL);
|
|
|
|
|
|
|
|
return super.getUrl();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
|
|
JarFileType getType() {
|
|
|
|
|
|
|
|
mark(Call.GET_TYPE);
|
|
|
|
|
|
|
|
return super.getType();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void mark(Call call) {
|
|
|
|
|
|
|
|
this.calls.add(call);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void verify(Call call) {
|
|
|
|
|
|
|
|
assertThat(call).matches(this.calls::contains);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
enum Call {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
GET_URL,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
GET_TYPE,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
GET_PERMISSION,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
GET_MANIFEST,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ENTRIES,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
GET_JAR_ENTRY,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
GET_ENTRY,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
GET_INPUT_STREAM,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
GET_ENTRY_INPUT_STREAM,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
GET_COMMENT,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
SIZE
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|