Support flat jar layering with layertools

Update layertools to support the flat jar format. Layers are now
determined by reading the `layers.idx` file.

Closes gh-20813
This commit is contained in:
Madhura Bhave
2020-04-01 16:47:18 -07:00
committed by Phillip Webb
parent bfa04e6574
commit d61a79d90b
7 changed files with 58 additions and 64 deletions

View File

@@ -20,59 +20,52 @@ import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.NoSuchFileException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.jar.JarFile;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import org.springframework.util.Assert;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StreamUtils;
/**
* {@link Layers} implementation backed by a {@code BOOT-INF/layers.idx} file.
*
* @author Phillip Webb
* @author Madhura Bhave
*/
class IndexedLayers implements Layers {
private static final String APPLICATION_LAYER = "application";
private static final String SPRING_BOOT_APPLICATION_LAYER = "springbootapplication";
private static final Pattern LAYER_PATTERN = Pattern.compile("^BOOT-INF\\/layers\\/([a-zA-Z0-9-]+)\\/.*$");
private List<String> layers;
private MultiValueMap<String, String> layers = new LinkedMultiValueMap<>();
IndexedLayers(String indexFile) {
String[] lines = indexFile.split("\n");
this.layers = Arrays.stream(lines).map(String::trim).filter((line) -> !line.isEmpty())
.collect(Collectors.toCollection(ArrayList::new));
Arrays.stream(lines).map(String::trim).filter((line) -> !line.isEmpty()).forEach((line) -> {
String[] content = line.split(" ");
Assert.state(content.length == 2, "Layer index file is malformed");
this.layers.add(content[0], content[1]);
});
Assert.state(!this.layers.isEmpty(), "Empty layer index file loaded");
if (!this.layers.contains(APPLICATION_LAYER)) {
this.layers.add(0, SPRING_BOOT_APPLICATION_LAYER);
}
}
@Override
public Iterator<String> iterator() {
return this.layers.iterator();
return this.layers.keySet().iterator();
}
@Override
public String getLayer(ZipEntry entry) {
String name = entry.getName();
Matcher matcher = LAYER_PATTERN.matcher(name);
if (matcher.matches()) {
String layer = matcher.group(1);
Assert.state(this.layers.contains(layer), () -> "Unexpected layer '" + layer + "'");
return layer;
for (Map.Entry<String, List<String>> indexEntry : this.layers.entrySet()) {
if (indexEntry.getValue().contains(name)) {
return indexEntry.getKey();
}
}
return this.layers.contains(APPLICATION_LAYER) ? APPLICATION_LAYER : SPRING_BOOT_APPLICATION_LAYER;
throw new IllegalStateException("No layer defined in index for file '" + name + "'");
}
/**