Skip to content

Commit 18965f2

Browse files
authored
Issue warning if PKL does not contain assets of type "text/xml" (#380)
CPL/OPL parsing continues to depend on the correct mime type in PKL, but a warning is provided if a PKL does not contain any assets of type text/xml.
1 parent e1c9cf5 commit 18965f2

File tree

6 files changed

+385
-12
lines changed

6 files changed

+385
-12
lines changed

src/main/java/com/netflix/imflibrary/app/IMPAnalyzer.java

+21-12
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,7 @@ public static Map<String, List<ErrorLogger.ErrorObject>> analyzePackage(File roo
251251
}
252252
packingListErrorLogger.addAllErrors(packingList.getErrors());
253253
Map<UUID, PayloadRecord> trackFileIDToHeaderPartitionPayLoadMap = new HashMap<>();
254+
int xmlFileCount = 0;
254255
for (PackingList.Asset asset : packingList.getAssets()) {
255256
if (asset.getType().equals(PackingList.Asset.APPLICATION_MXF_TYPE)) {
256257
URI path = assetMap.getPath(asset.getUUID());
@@ -302,11 +303,18 @@ public static Map<String, List<ErrorLogger.ErrorObject>> analyzePackage(File roo
302303
finally {
303304
errorMap.put(assetFile.getName(), trackFileErrorLogger.getErrors());
304305
}
306+
} else if (asset.getType().equals(PackingList.Asset.TEXT_XML_TYPE)) {
307+
xmlFileCount++;
305308
}
306309
}
307310

308-
List<ApplicationComposition> applicationCompositionList = analyzeApplicationCompositions( rootFile, assetMap, packingList, headerPartitionPayloadRecords, packingListErrorLogger, errorMap, trackFileIDToHeaderPartitionPayLoadMap);
311+
// issue a warning if the PKL does not contain any assets of type text/xml to help troubleshoot non-compliant mime-types for CPL/OPL
312+
if( xmlFileCount == 0) {
313+
packingListErrorLogger.addError(IMFErrorLogger.IMFErrors.ErrorCodes.IMF_PKL_ERROR,
314+
IMFErrorLogger.IMFErrors.ErrorLevels.WARNING, String.format("Packing List does not contain any assets of type \"%s\" (i.e. PKL does not contain any CPL/OPL files).", PackingList.Asset.TEXT_XML_TYPE));
315+
}
309316

317+
List<ApplicationComposition> applicationCompositionList = analyzeApplicationCompositions( rootFile, assetMap, packingList, headerPartitionPayloadRecords, packingListErrorLogger, errorMap, trackFileIDToHeaderPartitionPayLoadMap);
310318
analyzeOutputProfileLists( rootFile, assetMap, packingList, applicationCompositionList, packingListErrorLogger, errorMap);
311319

312320
} catch (IMFException e) {
@@ -366,14 +374,14 @@ public static List<OutputProfileList> analyzeOutputProfileLists(File rootFile,
366374
for (PackingList.Asset asset : packingList.getAssets()) {
367375
if (asset.getType().equals(PackingList.Asset.TEXT_XML_TYPE)) {
368376
URI path = assetMap.getPath(asset.getUUID());
369-
if( path == null) {
377+
if (path == null) {
370378
packingListErrorLogger.addError(IMFErrorLogger.IMFErrors.ErrorCodes.IMF_PKL_ERROR,
371379
IMFErrorLogger.IMFErrors.ErrorLevels.FATAL, String.format("Failed to get path for Asset with ID = %s", asset.getUUID().toString()));
372380
continue;
373381
}
374382
File assetFile = new File(rootFile, assetMap.getPath(asset.getUUID()).toString());
375383

376-
if(!assetFile.exists()) {
384+
if (!assetFile.exists()) {
377385
packingListErrorLogger.addError(IMFErrorLogger.IMFErrors.ErrorCodes.IMF_PKL_ERROR,
378386
IMFErrorLogger.IMFErrors.ErrorLevels.FATAL, String.format("Cannot find asset with path %s ID = %s", assetFile.getAbsolutePath(), asset.getUUID().toString()));
379387
continue;
@@ -384,18 +392,19 @@ public static List<OutputProfileList> analyzeOutputProfileLists(File rootFile,
384392
IMFErrorLogger imfErrorLogger = new IMFErrorLoggerImpl();
385393
try {
386394
OutputProfileList outputProfileListType = OutputProfileList.getOutputProfileListType(resourceByteRangeProvider, imfErrorLogger);
387-
if(outputProfileListType == null) {
395+
if (outputProfileListType == null) {
388396
continue;
389397
}
390398

391-
if(!outputProfileListType.getId().equals(asset.getUUID())) {
399+
if (!outputProfileListType.getId().equals(asset.getUUID())) {
392400
// ST 2067-2:2016 7.3.1: The value of the Id element shall be extracted from the asset as specified in Table 19 for the OPL asset
393401
imfErrorLogger.addError(IMFErrorLogger.IMFErrors.ErrorCodes.IMF_CPL_ERROR,
394402
IMFErrorLogger.IMFErrors.ErrorLevels.NON_FATAL, String.format("UUID %s in the OPL is not same as UUID %s of the OPL in the AssetMap", outputProfileListType.getId().toString(), asset.getUUID().toString()));
395-
} outputProfileListTypeList.add(outputProfileListType);
403+
}
404+
outputProfileListTypeList.add(outputProfileListType);
396405

397406
Optional<ApplicationComposition> optional = applicationCompositionList.stream().filter(e -> e.getUUID().equals(outputProfileListType.getCompositionPlaylistId())).findAny();
398-
if(!optional.isPresent()) {
407+
if (!optional.isPresent()) {
399408
imfErrorLogger.addError(IMFErrorLogger.IMFErrors.ErrorCodes.IMF_OPL_ERROR,
400409
IMFErrorLogger.IMFErrors.ErrorLevels.WARNING, String.format("Failed to get application composition with ID = %s for OutputProfileList with ID %s",
401410
outputProfileListType.getCompositionPlaylistId().toString(), outputProfileListType.getId().toString()));
@@ -428,14 +437,14 @@ public static List<ApplicationComposition> analyzeApplicationCompositions( File
428437
for (PackingList.Asset asset : packingList.getAssets()) {
429438
if (asset.getType().equals(PackingList.Asset.TEXT_XML_TYPE)) {
430439
URI path = assetMap.getPath(asset.getUUID());
431-
if( path == null) {
440+
if (path == null) {
432441
packingListErrorLogger.addError(IMFErrorLogger.IMFErrors.ErrorCodes.IMF_PKL_ERROR,
433442
IMFErrorLogger.IMFErrors.ErrorLevels.FATAL, String.format("Failed to get path for Asset with ID = %s", asset.getUUID().toString()));
434443
continue;
435444
}
436445
File assetFile = new File(rootFile, assetMap.getPath(asset.getUUID()).toString());
437446

438-
if(!assetFile.exists()) {
447+
if (!assetFile.exists()) {
439448
packingListErrorLogger.addError(IMFErrorLogger.IMFErrors.ErrorCodes.IMF_PKL_ERROR,
440449
IMFErrorLogger.IMFErrors.ErrorLevels.FATAL, String.format("Cannot find asset with path %s ID = %s", assetFile.getAbsolutePath(), asset.getUUID().toString()));
441450
continue;
@@ -450,10 +459,10 @@ public static List<ApplicationComposition> analyzeApplicationCompositions( File
450459

451460
try {
452461
ApplicationComposition applicationComposition = ApplicationCompositionFactory.getApplicationComposition(resourceByteRangeProvider, compositionErrorLogger);
453-
if(applicationComposition == null) {
462+
if (applicationComposition == null) {
454463
continue;
455464
}
456-
if(!applicationComposition.getUUID().equals(asset.getUUID())) {
465+
if (!applicationComposition.getUUID().equals(asset.getUUID())) {
457466
// ST 2067-2:2016 7.3.1: The value of the Id element shall be extracted from the asset as specified in Table 19 for the CPL asset
458467
compositionErrorLogger.addError(IMFErrorLogger.IMFErrors.ErrorCodes.IMF_CPL_ERROR,
459468
IMFErrorLogger.IMFErrors.ErrorLevels.NON_FATAL, String.format("UUID %s in the CPL is not same as UUID %s of the CPL in the AssetMap", applicationComposition.getUUID().toString(), asset.getUUID().toString()));
@@ -490,7 +499,7 @@ public static List<ApplicationComposition> analyzeApplicationCompositions( File
490499
.stream()
491500
.map(IMFEssenceComponentVirtualTrack::getTrackResourceIds)
492501
.flatMap(Set::stream)
493-
.map( e -> trackFileIDToHeaderPartitionPayLoadMap.get(e))
502+
.map(e -> trackFileIDToHeaderPartitionPayLoadMap.get(e))
494503
.collect(Collectors.toList());
495504
compositionConformanceErrorLogger.addAllErrors(IMPValidator.areAllVirtualTracksInCPLConformed(cplPayloadRecord, cplHeaderPartitionPayloads));
496505
}

src/test/java/com/netflix/imflibrary/app/IMPAnalyzerTest.java

+18
Original file line numberDiff line numberDiff line change
@@ -78,4 +78,22 @@ else if (e.getKey().matches("OPL.*")) {
7878
);
7979

8080
}
81+
82+
@Test
83+
public void IMPAnalyzerTestMimeTypeErrors() throws IOException
84+
{
85+
File inputFile = TestHelper.findResourceByPath("TestIMP/WrongXmlMimeTypes/");
86+
Map<String, List<ErrorLogger.ErrorObject>> errorMap = analyzePackage(inputFile);
87+
Assert.assertEquals(errorMap.size(), 2);
88+
errorMap.entrySet().stream().forEach( e ->
89+
{
90+
if (e.getKey().matches("PKL.*")) {
91+
Assert.assertEquals(e.getValue().size(), 1);
92+
Assert.assertTrue(e.getValue().get(0).getErrorDescription().contains("Packing List does not contain any assets of type"));
93+
} else {
94+
Assert.assertEquals(e.getValue().size(), 0);
95+
}
96+
}
97+
);
98+
}
8199
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<AssetMap xmlns="http://www.smpte-ra.org/schemas/429-9/2007/AM">
3+
<Id>urn:uuid:27d179c3-bf36-4c62-a2a5-d84d5750b188</Id>
4+
<AnnotationText>Untitled Project</AnnotationText>
5+
<Creator>TextEditor</Creator>
6+
<VolumeCount>1</VolumeCount>
7+
<IssueDate>2024-08-22T10:47:34</IssueDate>
8+
<Issuer>TextEditor</Issuer>
9+
<AssetList>
10+
<Asset>
11+
<Id>urn:uuid:cdbc350c-3042-4bb2-849a-43a657455adb</Id>
12+
<ChunkList>
13+
<Chunk>
14+
<Path>CPL_cdbc350c-3042-4bb2-849a-43a657455adb.xml</Path>
15+
<VolumeIndex>1</VolumeIndex>
16+
<Offset>0</Offset>
17+
<Length>12108</Length>
18+
</Chunk>
19+
</ChunkList>
20+
</Asset>
21+
<Asset>
22+
<Id>urn:uuid:d54a68ed-332e-4ddd-b163-c0317abb1e52</Id>
23+
<PackingList>true</PackingList>
24+
<ChunkList>
25+
<Chunk>
26+
<Path>PKL_d54a68ed-332e-4ddd-b163-c0317abb1e52.xml</Path>
27+
<VolumeIndex>1</VolumeIndex>
28+
<Offset>0</Offset>
29+
<Length>1715</Length>
30+
</Chunk>
31+
</ChunkList>
32+
</Asset>
33+
<Asset>
34+
<Id>urn:uuid:778f1aa6-7764-433f-9db7-f1b2c23a5b20</Id>
35+
<ChunkList>
36+
<Chunk>
37+
<Path>OPL_778f1aa6-7764-433f-9db7-f1b2c23a5b20.xml</Path>
38+
<VolumeIndex>1</VolumeIndex>
39+
<Offset>0</Offset>
40+
<Length>706</Length>
41+
</Chunk>
42+
</ChunkList>
43+
</Asset>
44+
</AssetList>
45+
</AssetMap>

0 commit comments

Comments
 (0)