IndexLayerArchiveFactory Class — spring-boot Architecture
Architecture documentation for the IndexLayerArchiveFactory class in ExportedImageTar.java from the spring-boot codebase.
Entity Profile
Relationship Graph
Source Code
buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/ExportedImageTar.java lines 146–264
private static class IndexLayerArchiveFactory extends LayerArchiveFactory {
private final Map<String, String> layerMediaTypes;
IndexLayerArchiveFactory(Path tarFile, ImageArchiveIndex index) throws IOException {
this(tarFile, withNestedIndexes(tarFile, index));
}
IndexLayerArchiveFactory(Path tarFile, List<ImageArchiveIndex> indexes) throws IOException {
Set<String> manifestDigests = getDigests(indexes, this::isManifest);
Set<String> manifestListDigests = getDigests(indexes, IndexLayerArchiveFactory::isManifestList);
List<ManifestList> manifestLists = getManifestLists(tarFile, manifestListDigests);
List<Manifest> manifests = getManifests(tarFile, manifestDigests, manifestLists);
this.layerMediaTypes = manifests.stream()
.flatMap((manifest) -> manifest.getLayers().stream())
.collect(Collectors.toMap(IndexLayerArchiveFactory::getEntryName, BlobReference::getMediaType));
}
private static List<ImageArchiveIndex> withNestedIndexes(Path tarFile, ImageArchiveIndex index)
throws IOException {
Set<String> indexDigests = getDigests(Stream.of(index), IndexLayerArchiveFactory::isIndex);
List<ImageArchiveIndex> indexes = new ArrayList<>();
indexes.add(index);
indexes.addAll(getDigestMatches(tarFile, indexDigests, ImageArchiveIndex::of));
return indexes;
}
private static Set<String> getDigests(List<ImageArchiveIndex> indexes, Predicate<BlobReference> predicate) {
return getDigests(indexes.stream(), predicate);
}
private static Set<String> getDigests(Stream<ImageArchiveIndex> indexes, Predicate<BlobReference> predicate) {
return indexes.flatMap((index) -> index.getManifests().stream())
.filter(predicate)
.map(BlobReference::getDigest)
.collect(Collectors.toUnmodifiableSet());
}
private static List<ManifestList> getManifestLists(Path tarFile, Set<String> digests) throws IOException {
return getDigestMatches(tarFile, digests, ManifestList::of);
}
private List<Manifest> getManifests(Path tarFile, Set<String> manifestDigests, List<ManifestList> manifestLists)
throws IOException {
Set<String> digests = new HashSet<>(manifestDigests);
manifestLists.stream()
.flatMap(ManifestList::streamManifests)
.filter(this::isManifest)
.map(BlobReference::getDigest)
.forEach(digests::add);
return getDigestMatches(tarFile, digests, Manifest::of);
}
private static <T> List<T> getDigestMatches(Path tarFile, Set<String> digests,
ThrowingFunction<InputStream, T> factory) throws IOException {
if (digests.isEmpty()) {
return Collections.emptyList();
}
Set<String> names = digests.stream()
.map(IndexLayerArchiveFactory::getEntryName)
.collect(Collectors.toUnmodifiableSet());
List<T> result = new ArrayList<>();
try (TarArchiveInputStream tar = openTar(tarFile)) {
TarArchiveEntry entry = tar.getNextEntry();
while (entry != null) {
if (names.contains(entry.getName())) {
result.add(factory.apply(tar));
}
entry = tar.getNextEntry();
}
}
return Collections.unmodifiableList(result);
}
private boolean isManifest(BlobReference reference) {
return isJsonWithPrefix(reference.getMediaType(), "application/vnd.oci.image.manifest.v")
|| isJsonWithPrefix(reference.getMediaType(), "application/vnd.docker.distribution.manifest.v");
}
private static boolean isIndex(BlobReference reference) {
return isJsonWithPrefix(reference.getMediaType(), "application/vnd.oci.image.index.v");
}
private static boolean isManifestList(BlobReference reference) {
return isJsonWithPrefix(reference.getMediaType(), "application/vnd.docker.distribution.manifest.list.v");
}
private static boolean isJsonWithPrefix(String mediaType, String prefix) {
return mediaType.startsWith(prefix) && mediaType.endsWith("+json");
}
private static String getEntryName(BlobReference reference) {
return getEntryName(reference.getDigest());
}
private static String getEntryName(String digest) {
return "blobs/" + digest.replace(':', '/');
}
@Override
@Nullable TarArchive getLayerArchive(TarArchiveInputStream tar, TarArchiveEntry entry) {
String mediaType = this.layerMediaTypes.get(entry.getName());
if (mediaType == null) {
return null;
}
return TarArchive.fromInputStream(tar, getCompression(mediaType));
}
private Compression getCompression(String mediaType) {
if (mediaType.endsWith(".tar.gzip") || mediaType.endsWith(".tar+gzip")) {
return Compression.GZIP;
}
if (mediaType.endsWith(".tar.zstd") || mediaType.endsWith(".tar+zstd")) {
return Compression.ZSTD;
}
return Compression.NONE;
}
}
Domain
Source
Analyze Your Own Codebase
Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.
Try Supermodel Free