mirror of
https://github.com/spring-projects/spring-boot.git
synced 2026-09-17 12:09:16 +00:00
Merge pull request #51653 from JunggiKim
Closes gh-51653 * speed-up-layer-lookup-when-extracting: Avoid scanning the whole layer index for every entry
This commit is contained in:
+17
-5
@@ -22,6 +22,7 @@ import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.NoSuchFileException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
@@ -42,11 +43,16 @@ import org.springframework.util.StringUtils;
|
||||
* @author Phillip Webb
|
||||
* @author Madhura Bhave
|
||||
* @author Moritz Halbritter
|
||||
* @author Junggi Kim
|
||||
*/
|
||||
class IndexedLayers implements Layers {
|
||||
|
||||
private final Map<String, List<String>> layers = new LinkedHashMap<>();
|
||||
|
||||
private final Map<String, String> layerByFileName = new HashMap<>();
|
||||
|
||||
private final Map<String, String> layerByDirectoryName = new LinkedHashMap<>();
|
||||
|
||||
private final String indexFileLocation;
|
||||
|
||||
IndexedLayers(String indexFile, String indexFileLocation) {
|
||||
@@ -70,6 +76,10 @@ class IndexedLayers implements Layers {
|
||||
}
|
||||
}
|
||||
Assert.state(!this.layers.isEmpty(), "Empty layer index file loaded");
|
||||
this.layers.forEach((layer, candidates) -> candidates.forEach((candidate) -> {
|
||||
Map<String, String> index = candidate.endsWith("/") ? this.layerByDirectoryName : this.layerByFileName;
|
||||
index.putIfAbsent(candidate, layer);
|
||||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -84,11 +94,13 @@ class IndexedLayers implements Layers {
|
||||
|
||||
@Override
|
||||
public String getLayer(String name) {
|
||||
for (Map.Entry<String, List<String>> entry : this.layers.entrySet()) {
|
||||
for (String candidate : entry.getValue()) {
|
||||
if (candidate.equals(name) || (candidate.endsWith("/") && name.startsWith(candidate))) {
|
||||
return entry.getKey();
|
||||
}
|
||||
String layer = this.layerByFileName.get(name);
|
||||
if (layer != null) {
|
||||
return layer;
|
||||
}
|
||||
for (Map.Entry<String, String> entry : this.layerByDirectoryName.entrySet()) {
|
||||
if (name.startsWith(entry.getKey())) {
|
||||
return entry.getValue();
|
||||
}
|
||||
}
|
||||
throw new IllegalStateException("No layer defined in index for file '" + name + "'");
|
||||
|
||||
+19
@@ -38,6 +38,7 @@ import static org.mockito.Mockito.mock;
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Madhura Bhave
|
||||
* @author Junggi Kim
|
||||
*/
|
||||
class IndexedLayersTests {
|
||||
|
||||
@@ -83,6 +84,13 @@ class IndexedLayersTests {
|
||||
assertThat(layers.getLayer(mockEntry("META-INF/a/sub/directory/and/a/file"))).isEqualTo("application");
|
||||
}
|
||||
|
||||
@Test
|
||||
void getLayerWhenNameIsInMultipleLayersReturnsFirstLayer() {
|
||||
IndexedLayers layers = new IndexedLayers(createIndexWithDuplicateName(), "BOOT-INF/classes");
|
||||
assertThat(layers.getLayer(mockEntry("BOOT-INF/lib/a.jar"))).isEqualTo("first");
|
||||
assertThat(layers.getLayer(mockEntry("META-INF/MANIFEST.MF"))).isEqualTo("first");
|
||||
}
|
||||
|
||||
@Test
|
||||
void getLayerWhenFileHasSpaceReturnsLayer() throws Exception {
|
||||
IndexedLayers layers = new IndexedLayers(getIndex(), "BOOT-INF/classes");
|
||||
@@ -102,6 +110,17 @@ class IndexedLayersTests {
|
||||
return getFile("test-layers.idx");
|
||||
}
|
||||
|
||||
private String createIndexWithDuplicateName() {
|
||||
return """
|
||||
- "first":
|
||||
- "BOOT-INF/lib/a.jar"
|
||||
- "META-INF/"
|
||||
- "second":
|
||||
- "BOOT-INF/lib/a.jar"
|
||||
- "META-INF/"
|
||||
""";
|
||||
}
|
||||
|
||||
private String getFile(String fileName) throws Exception {
|
||||
ClassPathResource resource = new ClassPathResource(fileName, getClass());
|
||||
InputStreamReader reader = new InputStreamReader(resource.getInputStream());
|
||||
|
||||
Reference in New Issue
Block a user