30
30
import java .util .Set ;
31
31
import java .util .function .Predicate ;
32
32
import java .util .stream .Collectors ;
33
+ import java .util .stream .Stream ;
33
34
34
35
import org .apache .commons .compress .archivers .tar .TarArchiveEntry ;
35
36
import org .apache .commons .compress .archivers .tar .TarArchiveInputStream ;
@@ -142,23 +143,40 @@ private static class IndexLayerArchiveFactory extends LayerArchiveFactory {
142
143
private final Map <String , String > layerMediaTypes ;
143
144
144
145
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 );
147
153
List <Manifest > manifests = getManifests (tarFile , manifestDigests , manifestLists );
148
154
this .layerMediaTypes = manifests .stream ()
149
155
.flatMap ((manifest ) -> manifest .getLayers ().stream ())
150
- .collect (Collectors .toMap (this ::getEntryName , BlobReference ::getMediaType ));
156
+ .collect (Collectors .toMap (IndexLayerArchiveFactory ::getEntryName , BlobReference ::getMediaType ));
151
157
}
152
158
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 ())
156
174
.filter (predicate )
157
175
.map (BlobReference ::getDigest )
158
176
.collect (Collectors .toUnmodifiableSet ());
159
177
}
160
178
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 {
162
180
return getDigestMatches (tarFile , digests , ManifestList ::of );
163
181
}
164
182
@@ -173,12 +191,14 @@ private List<Manifest> getManifests(Path tarFile, Set<String> manifestDigests, L
173
191
return getDigestMatches (tarFile , digests , Manifest ::of );
174
192
}
175
193
176
- private <T > List <T > getDigestMatches (Path tarFile , Set <String > digests ,
194
+ private static <T > List <T > getDigestMatches (Path tarFile , Set <String > digests ,
177
195
ThrowingFunction <InputStream , T > factory ) throws IOException {
178
196
if (digests .isEmpty ()) {
179
197
return Collections .emptyList ();
180
198
}
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 ());
182
202
List <T > result = new ArrayList <>();
183
203
try (TarArchiveInputStream tar = openTar (tarFile )) {
184
204
TarArchiveEntry entry = tar .getNextTarEntry ();
@@ -197,19 +217,23 @@ private boolean isManifest(BlobReference reference) {
197
217
|| isJsonWithPrefix (reference .getMediaType (), "application/vnd.docker.distribution.manifest.v" );
198
218
}
199
219
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 ) {
201
225
return isJsonWithPrefix (reference .getMediaType (), "application/vnd.docker.distribution.manifest.list.v" );
202
226
}
203
227
204
- private boolean isJsonWithPrefix (String mediaType , String prefix ) {
228
+ private static boolean isJsonWithPrefix (String mediaType , String prefix ) {
205
229
return mediaType .startsWith (prefix ) && mediaType .endsWith ("+json" );
206
230
}
207
231
208
- private String getEntryName (BlobReference reference ) {
232
+ private static String getEntryName (BlobReference reference ) {
209
233
return getEntryName (reference .getDigest ());
210
234
}
211
235
212
- private String getEntryName (String digest ) {
236
+ private static String getEntryName (String digest ) {
213
237
return "blobs/" + digest .replace (':' , '/' );
214
238
}
215
239
0 commit comments