3030import java .util .Set ;
3131import java .util .function .Predicate ;
3232import java .util .stream .Collectors ;
33+ import java .util .stream .Stream ;
3334
3435import org .apache .commons .compress .archivers .tar .TarArchiveEntry ;
3536import org .apache .commons .compress .archivers .tar .TarArchiveInputStream ;
@@ -142,23 +143,40 @@ private static class IndexLayerArchiveFactory extends LayerArchiveFactory {
142143 private final Map <String , String > layerMediaTypes ;
143144
144145 IndexLayerArchiveFactory (Path tarFile , ImageArchiveIndex index ) throws IOException {
145- Set <String > manifestDigests = getDigests (index , this ::isManifest );
146- List <ManifestList > manifestLists = getManifestLists (tarFile , getDigests (index , this ::isManifestList ));
146+ this (tarFile , withNestedIndexes (tarFile , index ));
147+ }
148+
149+ IndexLayerArchiveFactory (Path tarFile , List <ImageArchiveIndex > indexes ) throws IOException {
150+ Set <String > manifestDigests = getDigests (indexes , this ::isManifest );
151+ Set <String > manifestListDigests = getDigests (indexes , IndexLayerArchiveFactory ::isManifestList );
152+ List <ManifestList > manifestLists = getManifestLists (tarFile , manifestListDigests );
147153 List <Manifest > manifests = getManifests (tarFile , manifestDigests , manifestLists );
148154 this .layerMediaTypes = manifests .stream ()
149155 .flatMap ((manifest ) -> manifest .getLayers ().stream ())
150- .collect (Collectors .toMap (this ::getEntryName , BlobReference ::getMediaType ));
156+ .collect (Collectors .toMap (IndexLayerArchiveFactory ::getEntryName , BlobReference ::getMediaType ));
151157 }
152158
153- private Set <String > getDigests (ImageArchiveIndex index , Predicate <BlobReference > predicate ) {
154- return index .getManifests ()
155- .stream ()
159+ private static List <ImageArchiveIndex > withNestedIndexes (Path tarFile , ImageArchiveIndex index )
160+ throws IOException {
161+ Set <String > indexDigests = getDigests (Stream .of (index ), IndexLayerArchiveFactory ::isIndex );
162+ List <ImageArchiveIndex > indexes = new ArrayList <>();
163+ indexes .add (index );
164+ indexes .addAll (getDigestMatches (tarFile , indexDigests , ImageArchiveIndex ::of ));
165+ return indexes ;
166+ }
167+
168+ private static Set <String > getDigests (List <ImageArchiveIndex > indexes , Predicate <BlobReference > predicate ) {
169+ return getDigests (indexes .stream (), predicate );
170+ }
171+
172+ private static Set <String > getDigests (Stream <ImageArchiveIndex > indexes , Predicate <BlobReference > predicate ) {
173+ return indexes .flatMap ((index ) -> index .getManifests ().stream ())
156174 .filter (predicate )
157175 .map (BlobReference ::getDigest )
158176 .collect (Collectors .toUnmodifiableSet ());
159177 }
160178
161- private List <ManifestList > getManifestLists (Path tarFile , Set <String > digests ) throws IOException {
179+ private static List <ManifestList > getManifestLists (Path tarFile , Set <String > digests ) throws IOException {
162180 return getDigestMatches (tarFile , digests , ManifestList ::of );
163181 }
164182
@@ -173,12 +191,14 @@ private List<Manifest> getManifests(Path tarFile, Set<String> manifestDigests, L
173191 return getDigestMatches (tarFile , digests , Manifest ::of );
174192 }
175193
176- private <T > List <T > getDigestMatches (Path tarFile , Set <String > digests ,
194+ private static <T > List <T > getDigestMatches (Path tarFile , Set <String > digests ,
177195 ThrowingFunction <InputStream , T > factory ) throws IOException {
178196 if (digests .isEmpty ()) {
179197 return Collections .emptyList ();
180198 }
181- Set <String > names = digests .stream ().map (this ::getEntryName ).collect (Collectors .toUnmodifiableSet ());
199+ Set <String > names = digests .stream ()
200+ .map (IndexLayerArchiveFactory ::getEntryName )
201+ .collect (Collectors .toUnmodifiableSet ());
182202 List <T > result = new ArrayList <>();
183203 try (TarArchiveInputStream tar = openTar (tarFile )) {
184204 TarArchiveEntry entry = tar .getNextTarEntry ();
@@ -197,19 +217,23 @@ private boolean isManifest(BlobReference reference) {
197217 || isJsonWithPrefix (reference .getMediaType (), "application/vnd.docker.distribution.manifest.v" );
198218 }
199219
200- private boolean isManifestList (BlobReference reference ) {
220+ private static boolean isIndex (BlobReference reference ) {
221+ return isJsonWithPrefix (reference .getMediaType (), "application/vnd.oci.image.index.v" );
222+ }
223+
224+ private static boolean isManifestList (BlobReference reference ) {
201225 return isJsonWithPrefix (reference .getMediaType (), "application/vnd.docker.distribution.manifest.list.v" );
202226 }
203227
204- private boolean isJsonWithPrefix (String mediaType , String prefix ) {
228+ private static boolean isJsonWithPrefix (String mediaType , String prefix ) {
205229 return mediaType .startsWith (prefix ) && mediaType .endsWith ("+json" );
206230 }
207231
208- private String getEntryName (BlobReference reference ) {
232+ private static String getEntryName (BlobReference reference ) {
209233 return getEntryName (reference .getDigest ());
210234 }
211235
212- private String getEntryName (String digest ) {
236+ private static String getEntryName (String digest ) {
213237 return "blobs/" + digest .replace (':' , '/' );
214238 }
215239
0 commit comments