Skip to content

Commit

Permalink
Merge branch '2.1.x' into 2.2.x
Browse files Browse the repository at this point in the history
Fixes gh-21073
  • Loading branch information
philwebb committed Apr 22, 2020
2 parents 16ac968 + c85918b commit 6bf9332
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 18 deletions.
Expand Up @@ -60,6 +60,8 @@ public class JarFile extends java.util.jar.JarFile {

private static final AsciiBytes SIGNATURE_FILE_EXTENSION = new AsciiBytes(".SF");

private final JarFile parent;

private final RandomAccessDataFile rootFile;

private final String pathFromRoot;
Expand Down Expand Up @@ -100,6 +102,27 @@ public JarFile(File file) throws IOException {
this(file, "", file, JarFileType.DIRECT);
}

/**
* Create a new JarFile copy based on a given parent.
* @param parent the parent jar
* @throws IOException if the file cannot be read
*/
JarFile(JarFile parent) throws IOException {
super(parent.rootFile.getFile());
this.parent = parent;
this.rootFile = parent.rootFile;
this.pathFromRoot = parent.pathFromRoot;
this.data = parent.data;
this.type = parent.type;
this.url = parent.url;
this.urlString = parent.urlString;
this.entries = parent.entries;
this.manifestSupplier = parent.manifestSupplier;
this.manifest = parent.manifest;
this.signed = parent.signed;
this.comment = parent.comment;
}

/**
* Private constructor used to create a new {@link JarFile} either directly or from a
* nested entry.
Expand All @@ -111,12 +134,13 @@ public JarFile(File file) throws IOException {
*/
private JarFile(RandomAccessDataFile rootFile, String pathFromRoot, RandomAccessData data, JarFileType type)
throws IOException {
this(rootFile, pathFromRoot, data, null, type, null);
this(null, rootFile, pathFromRoot, data, null, type, null);
}

private JarFile(RandomAccessDataFile rootFile, String pathFromRoot, RandomAccessData data, JarEntryFilter filter,
JarFileType type, Supplier<Manifest> manifestSupplier) throws IOException {
private JarFile(JarFile parent, RandomAccessDataFile rootFile, String pathFromRoot, RandomAccessData data,
JarEntryFilter filter, JarFileType type, Supplier<Manifest> manifestSupplier) throws IOException {
super(rootFile.getFile());
this.parent = parent;
this.rootFile = rootFile;
this.pathFromRoot = pathFromRoot;
CentralDirectoryParser parser = new CentralDirectoryParser();
Expand Down Expand Up @@ -166,6 +190,10 @@ public void visitEnd() {
};
}

JarFile getParent() {
return this.parent;
}

protected final RandomAccessDataFile getRootJarFile() {
return this.rootFile;
}
Expand Down Expand Up @@ -264,8 +292,9 @@ private JarFile createJarFileFromDirectoryEntry(JarEntry entry) throws IOExcepti
}
return null;
};
return new JarFile(this.rootFile, this.pathFromRoot + "!/" + entry.getName().substring(0, name.length() - 1),
this.data, filter, JarFileType.NESTED_DIRECTORY, this.manifestSupplier);
return new JarFile(this, this.rootFile,
this.pathFromRoot + "!/" + entry.getName().substring(0, name.length() - 1), this.data, filter,
JarFileType.NESTED_DIRECTORY, this.manifestSupplier);
}

private JarFile createJarFileFromFileEntry(JarEntry entry) throws IOException {
Expand Down Expand Up @@ -293,7 +322,7 @@ public int size() {
@Override
public void close() throws IOException {
super.close();
if (this.type == JarFileType.DIRECT) {
if (this.type == JarFileType.DIRECT && this.parent == null) {
this.rootFile.close();
}
}
Expand All @@ -313,10 +342,9 @@ String getUrlString() throws MalformedURLException {
*/
public URL getUrl() throws MalformedURLException {
if (this.url == null) {
Handler handler = new Handler(this);
String file = this.rootFile.getFile().toURI() + this.pathFromRoot + "!/";
file = file.replace("file:////", "file://"); // Fix UNC paths
this.url = new URL("jar", "", -1, file, handler);
this.url = new URL("jar", "", -1, file, new Handler(this));
}
return this.url;
}
Expand Down
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2019 the original author or authors.
* Copyright 2012-2020 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.
Expand Down Expand Up @@ -286,7 +286,7 @@ static JarURLConnection get(URL url, JarFile jarFile) throws IOException {
}
return NOT_FOUND_CONNECTION;
}
return new JarURLConnection(url, connectionJarFile, jarEntryName,
return new JarURLConnection(url, new JarFile(connectionJarFile), jarEntryName,
(connectionJarFile != jarFile) ? connectionJarFile::close : null);
}

Expand Down
Expand Up @@ -218,10 +218,10 @@ void getUrl() throws Exception {
URL url = this.jarFile.getUrl();
assertThat(url.toString()).isEqualTo("jar:" + this.rootJarFile.toURI() + "!/");
JarURLConnection jarURLConnection = (JarURLConnection) url.openConnection();
assertThat(jarURLConnection.getJarFile()).isSameAs(this.jarFile);
assertThat(jarURLConnection.getJarFile().getParent()).isSameAs(this.jarFile);
assertThat(jarURLConnection.getJarEntry()).isNull();
assertThat(jarURLConnection.getContentLength()).isGreaterThan(1);
assertThat(jarURLConnection.getContent()).isSameAs(this.jarFile);
assertThat(((JarFile) jarURLConnection.getContent()).getParent()).isSameAs(this.jarFile);
assertThat(jarURLConnection.getContentType()).isEqualTo("x-java/jar");
assertThat(jarURLConnection.getJarFileURL().toURI()).isEqualTo(this.rootJarFile.toURI());
}
Expand All @@ -231,7 +231,7 @@ void createEntryUrl() throws Exception {
URL url = new URL(this.jarFile.getUrl(), "1.dat");
assertThat(url.toString()).isEqualTo("jar:" + this.rootJarFile.toURI() + "!/1.dat");
JarURLConnection jarURLConnection = (JarURLConnection) url.openConnection();
assertThat(jarURLConnection.getJarFile()).isSameAs(this.jarFile);
assertThat(jarURLConnection.getJarFile().getParent()).isSameAs(this.jarFile);
assertThat(jarURLConnection.getJarEntry()).isSameAs(this.jarFile.getJarEntry("1.dat"));
assertThat(jarURLConnection.getContentLength()).isEqualTo(1);
assertThat(jarURLConnection.getContent()).isInstanceOf(InputStream.class);
Expand Down Expand Up @@ -285,7 +285,7 @@ void getNestedJarFile() throws Exception {
URL url = nestedJarFile.getUrl();
assertThat(url.toString()).isEqualTo("jar:" + this.rootJarFile.toURI() + "!/nested.jar!/");
JarURLConnection conn = (JarURLConnection) url.openConnection();
assertThat(conn.getJarFile()).isSameAs(nestedJarFile);
assertThat(conn.getJarFile().getParent()).isSameAs(nestedJarFile);
assertThat(conn.getJarFileURL().toString()).isEqualTo("jar:" + this.rootJarFile.toURI() + "!/nested.jar");
assertThat(conn.getInputStream()).isNotNull();
JarInputStream jarInputStream = new JarInputStream(conn.getInputStream());
Expand Down Expand Up @@ -314,7 +314,7 @@ void getNestedJarDirectory() throws Exception {

URL url = nestedJarFile.getUrl();
assertThat(url.toString()).isEqualTo("jar:" + this.rootJarFile.toURI() + "!/d!/");
assertThat(((JarURLConnection) url.openConnection()).getJarFile()).isSameAs(nestedJarFile);
assertThat(((JarURLConnection) url.openConnection()).getJarFile().getParent()).isSameAs(nestedJarFile);
}
}

Expand Down
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2019 the original author or authors.
* Copyright 2012-2020 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.
Expand All @@ -21,6 +21,7 @@
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.net.URL;
import java.util.zip.ZipFile;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
Expand All @@ -29,6 +30,7 @@

import org.springframework.boot.loader.TestJarCreator;
import org.springframework.boot.loader.jar.JarURLConnection.JarEntryName;
import org.springframework.test.util.ReflectionTestUtils;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
Expand Down Expand Up @@ -61,13 +63,15 @@ void tearDown() throws Exception {
@Test
void connectionToRootUsingAbsoluteUrl() throws Exception {
URL url = new URL("jar:" + this.rootJarFile.toURI().toURL() + "!/");
assertThat(JarURLConnection.get(url, this.jarFile).getContent()).isSameAs(this.jarFile);
Object content = JarURLConnection.get(url, this.jarFile).getContent();
assertThat(((JarFile) content).getParent()).isSameAs(this.jarFile);
}

@Test
void connectionToRootUsingRelativeUrl() throws Exception {
URL url = new URL("jar:file:" + getRelativePath() + "!/");
assertThat(JarURLConnection.get(url, this.jarFile).getContent()).isSameAs(this.jarFile);
Object content = JarURLConnection.get(url, this.jarFile).getContent();
assertThat(((JarFile) content).getParent()).isSameAs(this.jarFile);
}

@Test
Expand Down Expand Up @@ -220,6 +224,15 @@ void jarEntryNameWithMixtureOfEncodedAndUnencodedDoubleByteCharacters() {
.isEqualTo("\u00e1/b/\u00c7.class");
}

@Test
void openConnectionCanBeClosedWithoutClosingSourceJar() throws Exception {
URL url = new URL("jar:" + this.rootJarFile.toURI().toURL() + "!/");
JarURLConnection connection = JarURLConnection.get(url, this.jarFile);
JarFile connectionJarFile = connection.getJarFile();
connectionJarFile.close();
assertThat((Boolean) ReflectionTestUtils.getField(this.jarFile, ZipFile.class, "closeRequested")).isFalse();
}

private String getRelativePath() {
return this.rootJarFile.getPath().replace('\\', '/');
}
Expand Down

0 comments on commit 6bf9332

Please sign in to comment.