Repository: CycloneDX/cyclonedx-core-java
Pull request #264 (2023-02-02 20:52:16)

Security contact and vuln analysis time for 1.5 spec
This adds support to the Java Cyclone core to solve:

- https://github.com/CycloneDX/specification/pull/180
- https://github.com/CycloneDX/specification/issues/142

sonatype-lift[bot]: ## 🛠 Lift Auto-fix
Some of the Lift findings in this PR can be automatically fixed. You can download and apply these changes in your local project directory of your branch to review the suggestions before committing.[^1]
```bash
# Download the patch
curl https://lift.sonatype.com/api/patch/github.com/CycloneDX/cyclonedx-core-java/264.diff -o lift-autofixes.diff

# Apply the patch with git
git apply lift-autofixes.diff

# Review the changes
git diff
```
Want it all in a single command? Open a terminal in your project's directory and copy and paste the following command:
```bash
curl https://lift.sonatype.com/api/patch/github.com/CycloneDX/cyclonedx-core-java/264.diff | git apply
```
Once you're satisfied, commit and push your changes in your project.
[^1]: You can preview the patch by opening the [patch URL](https://lift.sonatype.com/api/patch/github.com/CycloneDX/cyclonedx-core-java/264.diff) in the browser.

Patch:
diff --git a/src/main/java/org/cyclonedx/model/ExternalReference.java b/src/main/java/org/cyclonedx/model/ExternalReference.java
index 56be165bd..3d78bff41 100644
--- a/src/main/java/org/cyclonedx/model/ExternalReference.java
+++ b/src/main/java/org/cyclonedx/model/ExternalReference.java
@@ -68,6 +68,8 @@ public class ExternalReference {
         BUILD_SYSTEM("build-system"),
         @JsonProperty("release-notes")
         RELEASE_NOTES("release-notes"),
+        @JsonProperty("security-contact")
+        SECURITY_CONTACT("security-contact"),
         @JsonProperty("other")
         OTHER("other");
 
diff --git a/src/main/java/org/cyclonedx/model/vulnerability/Vulnerability.java b/src/main/java/org/cyclonedx/model/vulnerability/Vulnerability.java
index e6611cfc9..c26ca41d9 100644
--- a/src/main/java/org/cyclonedx/model/vulnerability/Vulnerability.java
+++ b/src/main/java/org/cyclonedx/model/vulnerability/Vulnerability.java
@@ -579,6 +579,14 @@ public class Vulnerability
     private List<Response> responses;
     private String detail;
 
+    @JsonSerialize(using = CustomDateSerializer.class)
+    @VersionFilter(versions = {"1.0", "1.1", "1.2", "1.3", "1.4"})
+    private Date firstIssued;
+
+    @JsonSerialize(using = CustomDateSerializer.class)
+    @VersionFilter(versions = {"1.0", "1.1", "1.2", "1.3", "1.4"})
+    private Date lastUpdated;
+
     public State getState() {
       return state;
     }
@@ -613,6 +621,22 @@ public class Vulnerability
     public void setDetail(final String detail) {
       this.detail = detail;
     }
+
+    public Date getFirstIssued() {
+      return firstIssued;
+    }
+
+    public void setFirstIssued(final Date firstIssued) {
+      this.firstIssued = firstIssued;
+    }
+
+    public Date getLastUpdated() {
+      return lastUpdated;
+    }
+
+    public void setLastUpdated(final Date lastUpdated) {
+      this.lastUpdated = lastUpdated;
+    }
   }
 
   @JsonInclude(JsonInclude.Include.NON_EMPTY)
diff --git a/src/main/resources/bom-1.5.proto b/src/main/resources/bom-1.5.proto
index 6f33059f1..b36b2983c 100644
--- a/src/main/resources/bom-1.5.proto
+++ b/src/main/resources/bom-1.5.proto
@@ -638,6 +638,10 @@ message VulnerabilityAnalysis {
   repeated VulnerabilityResponse response = 3;
   // Detailed description of the impact including methods used during assessment. If a vulnerability is not exploitable, this field should include specific details on why the component or service is not impacted by this vulnerability.
   optional string detail = 4;
+  // The date and time (timestamp) when the analysis was first issued.
+  optional google.protobuf.Timestamp firstIssued = 5;
+  // The date and time (timestamp) when the analysis was last updated.
+  optional google.protobuf.Timestamp lastUpdated = 6;
 }
 
 enum ImpactAnalysisState {


Test patch:
diff --git a/src/test/java/org/cyclonedx/parsers/JsonParserTest.java b/src/test/java/org/cyclonedx/parsers/JsonParserTest.java
index 89d59108b..bfca40d0c 100644
--- a/src/test/java/org/cyclonedx/parsers/JsonParserTest.java
+++ b/src/test/java/org/cyclonedx/parsers/JsonParserTest.java
@@ -20,6 +20,7 @@ package org.cyclonedx.parsers;
 
 import org.apache.commons.io.IOUtils;
 import org.cyclonedx.CycloneDxSchema;
+import org.cyclonedx.CycloneDxSchema.Version;
 import org.cyclonedx.model.Bom;
 import org.cyclonedx.model.Component;
 import org.cyclonedx.model.Dependency;
@@ -333,9 +334,9 @@ public class JsonParserTest {
         assertEquals(1, bom.getVersion());
 
         assertMetadata(bom.getMetadata());
-        assertComponent(bom);
+        assertComponent(bom, Version.VERSION_14);
         assertServices(bom);
-        assertVulnerabilities(bom);
+        assertVulnerabilities(bom, Version.VERSION_14);
 
         // Dependencies
         assertEquals(2, bom.getDependencies().size());
@@ -354,9 +355,9 @@ public class JsonParserTest {
         assertEquals(1, bom.getVersion());
 
         assertMetadata(bom.getMetadata());
-        assertComponent(bom);
+        assertComponent(bom, Version.VERSION_15);
         assertServices(bom);
-        assertVulnerabilities(bom);
+        assertVulnerabilities(bom, Version.VERSION_15);
 
         // Dependencies
         assertEquals(2, bom.getDependencies().size());
@@ -365,7 +366,7 @@ public class JsonParserTest {
         assertEquals("pkg:npm/acme/component@1.0.0", d1.getRef());
     }
 
-    private void assertVulnerabilities(final Bom bom) {
+    private void assertVulnerabilities(final Bom bom, Version version) {
         final List<Vulnerability> vulnerabilities = bom.getVulnerabilities();
         assertEquals(1, vulnerabilities.size());
         Vulnerability vuln = vulnerabilities.get(0);
@@ -434,6 +435,15 @@ public class JsonParserTest {
             vuln.getAnalysis().getDetail());
         assertEquals("update", vuln.getAnalysis().getResponses().get(0).getResponseName());
 
+        //Vulnerability Analysis Timestamp 1.5
+        if (version != Version.VERSION_14) {
+            assertNotNull(vuln.getAnalysis().getFirstIssued());
+            assertNotNull(vuln.getAnalysis().getLastUpdated());
+        } else {
+            assertNull(vuln.getAnalysis().getFirstIssued());
+            assertNull(vuln.getAnalysis().getLastUpdated());
+        }
+
         //Affects
         assertEquals(1, vuln.getAffects().size());
         assertEquals("pkg:maven/com.acme/jackson-databind@2.9.9", vuln.getAffects().get(0).getRef());
@@ -495,7 +505,7 @@ public class JsonParserTest {
         assertEquals("http://api.partner.org/swagger", s.getExternalReferences().get(1).getUrl());
     }
 
-    private void assertComponent(final Bom bom) {
+    private void assertComponent(final Bom bom, final Version version) {
         final List<Component> components = bom.getComponents();
         assertEquals(1, components.size());
         Component component = components.get(0);
@@ -510,7 +520,15 @@ public class JsonParserTest {
         assertEquals("Acme Application", component.getSwid().getName());
         assertEquals("9.1.1", component.getSwid().getVersion());
         assertEquals("swidgen-242eb18a-503e-ca37-393b-cf156ef09691_9.1.1", component.getSwid().getTagId());
-        assertEquals(1, component.getExternalReferences().size());
+
+        if (version == Version.VERSION_14) {
+            assertEquals(1, component.getExternalReferences().size());
+        }
+        else {
+            assertEquals(2, component.getExternalReferences().size());
+            //Security Contact
+            assertSecurityContact(component.getExternalReferences().get(1));
+        }
 
         //Evidence
         assertNotNull(component.getEvidence());
@@ -521,6 +539,12 @@ public class JsonParserTest {
             component.getEvidence().getLicenseChoice().getLicenses().get(0).getUrl());
     }
 
+    private void assertSecurityContact(ExternalReference externalReference){
+        assertEquals(externalReference.getType(), ExternalReference.Type.SECURITY_CONTACT);
+        assertEquals(externalReference.getComment(), "test");
+        assertEquals(externalReference.getUrl(), "http://example.org/docs");
+    }
+
     private void assertMetadata(final Metadata metadata) {
         assertNotNull(metadata);
         assertNotNull(metadata.getTimestamp());
diff --git a/src/test/java/org/cyclonedx/parsers/XmlParserTest.java b/src/test/java/org/cyclonedx/parsers/XmlParserTest.java
index 5713c1a12..6c531d0d8 100644
--- a/src/test/java/org/cyclonedx/parsers/XmlParserTest.java
+++ b/src/test/java/org/cyclonedx/parsers/XmlParserTest.java
@@ -20,6 +20,7 @@ package org.cyclonedx.parsers;
 
 import org.apache.commons.io.IOUtils;
 import org.cyclonedx.CycloneDxSchema;
+import org.cyclonedx.CycloneDxSchema.Version;
 import org.cyclonedx.model.Bom;
 import org.cyclonedx.model.Component;
 import org.cyclonedx.model.Dependency;
@@ -458,9 +459,9 @@ public class XmlParserTest {
         assertEquals(1, bom.getVersion());
 
         assertMetadata(bom.getMetadata());
-        assertComponent(bom);
+        assertComponent(bom, Version.VERSION_14);
         assertServices(bom);
-        assertVulnerabilities(bom);
+        assertVulnerabilities(bom, Version.VERSION_14);
 
         // Dependencies
         assertEquals(1, bom.getDependencies().size());
@@ -479,15 +480,22 @@ public class XmlParserTest {
         assertEquals(1, bom.getVersion());
 
         assertMetadata(bom.getMetadata());
-        assertComponent(bom);
+        assertComponent(bom, Version.VERSION_15);
         assertServices(bom);
-        assertVulnerabilities(bom);
+        assertVulnerabilities(bom, Version.VERSION_15);
 
         // Dependencies
         assertEquals(1, bom.getDependencies().size());
         Dependency d1 = bom.getDependencies().get(0);
         assertNotNull(d1);
         assertEquals("pkg:maven/com.acme/jackson-databind@2.9.4", d1.getRef());
+
+        //Assert Licensing
+        //Assert Vulnerability Rejected
+        //Assert Annotations
+        //Assert Bom Properties
+        //Assert License Properties
+        //Assert Vulnerabilities Timestamps
     }
 
     @Test
@@ -501,7 +509,7 @@ public class XmlParserTest {
         assertNull(bom.getVulnerabilities());
     }
 
-    private void assertVulnerabilities(final Bom bom) {
+    private void assertVulnerabilities(final Bom bom, final Version version) {
         final List<Vulnerability> vulnerabilities = bom.getVulnerabilities();
         assertEquals(1, vulnerabilities.size());
         Vulnerability vuln = vulnerabilities.get(0);
@@ -570,6 +578,15 @@ public class XmlParserTest {
             vuln.getAnalysis().getDetail());
         assertEquals("update", vuln.getAnalysis().getResponses().get(0).getResponseName());
 
+        //Vulnerability Analysis Timestamp 1.5
+        if (version != Version.VERSION_14) {
+            assertNotNull(vuln.getAnalysis().getFirstIssued());
+            assertNotNull(vuln.getAnalysis().getLastUpdated());
+        } else {
+            assertNull(vuln.getAnalysis().getFirstIssued());
+            assertNull(vuln.getAnalysis().getLastUpdated());
+        }
+
         //Affects
         assertEquals(1, vuln.getAffects().size());
         assertEquals("pkg:maven/com.acme/jackson-databind@2.9.9", vuln.getAffects().get(0).getRef());
@@ -631,7 +648,7 @@ public class XmlParserTest {
         assertEquals("http://api.partner.org/swagger", s.getExternalReferences().get(1).getUrl());
     }
 
-    private void assertComponent(final Bom bom) {
+    private void assertComponent(final Bom bom, final Version version) {
         final List<Component> components = bom.getComponents();
         assertEquals(1, components.size());
         Component component = components.get(0);
@@ -646,7 +663,15 @@ public class XmlParserTest {
         assertEquals("Acme Application", component.getSwid().getName());
         assertEquals("9.1.1", component.getSwid().getVersion());
         assertEquals("swidgen-242eb18a-503e-ca37-393b-cf156ef09691_9.1.1", component.getSwid().getTagId());
-        assertEquals(1, component.getExternalReferences().size());
+
+        if (version == Version.VERSION_14) {
+            assertEquals(1, component.getExternalReferences().size());
+        }
+        else {
+            assertEquals(2, component.getExternalReferences().size());
+            //Security Contact
+            assertSecurityContact(component.getExternalReferences().get(1));
+        }
 
         //Evidence
         assertNotNull(component.getEvidence());
@@ -657,6 +682,12 @@ public class XmlParserTest {
             component.getEvidence().getLicenseChoice().getLicenses().get(0).getUrl());
     }
 
+    private void assertSecurityContact(ExternalReference externalReference){
+        assertEquals(externalReference.getType(), ExternalReference.Type.SECURITY_CONTACT);
+        assertEquals(externalReference.getComment(), "test");
+        assertEquals(externalReference.getUrl(), "http://example.org/docs");
+    }
+
     private void assertMetadata(final Metadata metadata) {
         assertNotNull(metadata);
         assertNotNull(metadata.getTimestamp());
diff --git a/src/test/resources/bom-1.5.json b/src/test/resources/bom-1.5.json
index d92a9f96a..1f2f1a60b 100644
--- a/src/test/resources/bom-1.5.json
+++ b/src/test/resources/bom-1.5.json
@@ -181,6 +181,11 @@
           "type": "documentation",
           "url": "http://example.org/docs",
           "comment": "All component versions are documented here"
+        },
+        {
+          "type": "security-contact",
+          "url": "http://example.org/docs",
+          "comment": "test"
         }
       ],
       "evidence": {
@@ -376,7 +381,9 @@
         "response": [
           "update"
         ],
-        "detail": "An optional explanation of why the application is not affected by the vulnerable component."
+        "detail": "An optional explanation of why the application is not affected by the vulnerable component.",
+        "firstIssued": "2022-01-01T00:00:00.000Z",
+        "lastUpdated": "2022-02-01T00:00:00.000Z"
       },
       "affects": [
          {
diff --git a/src/test/resources/bom-1.5.xml b/src/test/resources/bom-1.5.xml
index f58b3e5c6..a4a2567d5 100644
--- a/src/test/resources/bom-1.5.xml
+++ b/src/test/resources/bom-1.5.xml
@@ -110,6 +110,10 @@
                     <url>http://example.org/docs</url>
                     <comment>All component versions are documented here</comment>
                 </reference>
+                <reference type="security-contact">
+                    <url>http://example.org/docs</url>
+                    <comment>test</comment>
+                </reference>
             </externalReferences>
             <evidence>
                 <licenses>
@@ -261,6 +265,8 @@
                     <response>update</response>
                 </responses>
                 <detail>An optional explanation of why the application is not affected by the vulnerable component.</detail>
+                <firstIssued>2020-04-07T07:01:00Z</firstIssued>
+                <lastUpdated>2020-04-07T07:01:00Z</lastUpdated>
             </analysis>
             <affects>
                 <target>
diff --git a/src/test/resources/bom-1.5_ejemplo.xml b/src/test/resources/bom-1.5_ejemplo.xml
new file mode 100644
index 000000000..913285eac
--- /dev/null
+++ b/src/test/resources/bom-1.5_ejemplo.xml
@@ -0,0 +1,181 @@
+<?xml version="1.0"?>
+<bom serialNumber="urn:uuid:3e671687-395b-41f5-a30f-a58921a69b79" version="1" xmlns="http://cyclonedx.org/schema/bom/1.5">
+    <metadata>
+        <timestamp>2020-04-07T07:01:00Z</timestamp>
+        <tools>
+            <tool>
+                <vendor>Awesome Vendor</vendor>
+                <name>Awesome Tool</name>
+                <version>9.1.2</version>
+                <hashes>
+                    <hash alg="SHA-1">25ed8e31b995bb927966616df2a42b979a2717f0</hash>
+                    <hash alg="SHA-256">a74f733635a19aefb1f73e5947cef59cd7440c6952ef0f03d09d974274cbd6df</hash>
+                </hashes>
+            </tool>
+        </tools>
+        <authors>
+            <author>
+                <name>Samantha Wright</name>
+                <email>samantha.wright@example.com</email>
+                <phone>800-555-1212</phone>
+            </author>
+        </authors>
+        <component type="application">
+            <author>Acme Super Heros</author>
+            <name>Acme Application</name>
+            <version>9.1.1</version>
+            <swid tagId="swidgen-242eb18a-503e-ca37-393b-cf156ef09691_9.1.1" name="Acme Application" version="9.1.1">
+                <text content-type="text/xml" encoding="base64">PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiID8+CjxTb2Z0d2FyZUlkZW50aXR5IHhtbDpsYW5nPSJFTiIgbmFtZT0iQWNtZSBBcHBsaWNhdGlvbiIgdmVyc2lvbj0iOS4xLjEiIAogdmVyc2lvblNjaGVtZT0ibXVsdGlwYXJ0bnVtZXJpYyIgCiB0YWdJZD0ic3dpZGdlbi1iNTk1MWFjOS00MmMwLWYzODItM2YxZS1iYzdhMmE0NDk3Y2JfOS4xLjEiIAogeG1sbnM9Imh0dHA6Ly9zdGFuZGFyZHMuaXNvLm9yZy9pc28vMTk3NzAvLTIvMjAxNS9zY2hlbWEueHNkIj4gCiB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWluc3RhbmNlIiAKIHhzaTpzY2hlbWFMb2NhdGlvbj0iaHR0cDovL3N0YW5kYXJkcy5pc28ub3JnL2lzby8xOTc3MC8tMi8yMDE1LWN1cnJlbnQvc2NoZW1hLnhzZCBzY2hlbWEueHNkIiA+CiAgPE1ldGEgZ2VuZXJhdG9yPSJTV0lEIFRhZyBPbmxpbmUgR2VuZXJhdG9yIHYwLjEiIC8+IAogIDxFbnRpdHkgbmFtZT0iQWNtZSwgSW5jLiIgcmVnaWQ9ImV4YW1wbGUuY29tIiByb2xlPSJ0YWdDcmVhdG9yIiAvPiAKPC9Tb2Z0d2FyZUlkZW50aXR5Pg==</text>
+            </swid>
+        </component>
+        <manufacture>
+            <name>Acme, Inc.</name>
+            <url>https://example.com</url>
+            <contact>
+                <name>Acme Professional Services</name>
+                <email>professional.services@example.com</email>
+            </contact>
+        </manufacture>
+        <supplier>
+            <name>Acme, Inc.</name>
+            <url>https://example.com</url>
+            <contact>
+                <name>Acme Distribution</name>
+                <email>distribution@example.com</email>
+            </contact>
+        </supplier>
+    </metadata>
+    <components>
+        <component type="application">
+            <author>Acme Super Heros</author>
+            <publisher>Acme Inc</publisher>
+            <group>com.acme</group>
+            <name>tomcat-catalina</name>
+            <version>9.0.14</version>
+            <description>Modified version of Apache Catalina</description>
+            <scope>required</scope>
+            <hashes>
+                <hash alg="MD5">3942447fac867ae5cdb3229b658f4d48</hash>
+                <hash alg="SHA-1">e6b1000b94e835ffd37f4c6dcbdad43f4b48a02a</hash>
+                <hash alg="SHA-256">f498a8ff2dd007e29c2074f5e4b01a9a01775c3ff3aeaf6906ea503bc5791b7b</hash>
+                <hash alg="SHA-512">e8f33e424f3f4ed6db76a482fde1a5298970e442c531729119e37991884bdffab4f9426b7ee11fccd074eeda0634d71697d6f88a460dce0ac8d627a29f7d1282</hash>
+            </hashes>
+            <licenses>
+                <license>
+                    <id>Apache-2.0</id>
+                    <text content-type="text/plain" encoding="base64">CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFwYWNoZSBMaWNlbnNlCiAgICAgICAgICAgICAgICAgICAgICAgICAgIFZlcnNpb24gMi4wLCBKYW51YXJ5IDIwMDQKICAgICAgICAgICAgICAgICAgICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzLwoKICAgVEVSTVMgQU5EIENPTkRJVElPTlMgRk9SIFVTRSwgUkVQUk9EVUNUSU9OLCBBTkQgRElTVFJJQlVUSU9OCgogICAxLiBEZWZpbml0aW9ucy4KCiAgICAgICJMaWNlbnNlIiBzaGFsbCBtZWFuIHRoZSB0ZXJtcyBhbmQgY29uZGl0aW9ucyBmb3IgdXNlLCByZXByb2R1Y3Rpb24sCiAgICAgIGFuZCBkaXN0cmlidXRpb24gYXMgZGVmaW5lZCBieSBTZWN0aW9ucyAxIHRocm91Z2ggOSBvZiB0aGlzIGRvY3VtZW50LgoKICAgICAgIkxpY2Vuc29yIiBzaGFsbCBtZWFuIHRoZSBjb3B5cmlnaHQgb3duZXIgb3IgZW50aXR5IGF1dGhvcml6ZWQgYnkKICAgICAgdGhlIGNvcHlyaWdodCBvd25lciB0aGF0IGlzIGdyYW50aW5nIHRoZSBMaWNlbnNlLgoKICAgICAgIkxlZ2FsIEVudGl0eSIgc2hhbGwgbWVhbiB0aGUgdW5pb24gb2YgdGhlIGFjdGluZyBlbnRpdHkgYW5kIGFsbAogICAgICBvdGhlciBlbnRpdGllcyB0aGF0IGNvbnRyb2wsIGFyZSBjb250cm9sbGVkIGJ5LCBvciBhcmUgdW5kZXIgY29tbW9uCiAgICAgIGNvbnRyb2wgd2l0aCB0aGF0IGVudGl0eS4gRm9yIHRoZSBwdXJwb3NlcyBvZiB0aGlzIGRlZmluaXRpb24sCiAgICAgICJjb250cm9sIiBtZWFucyAoaSkgdGhlIHBvd2VyLCBkaXJlY3Qgb3IgaW5kaXJlY3QsIHRvIGNhdXNlIHRoZQogICAgICBkaXJlY3Rpb24gb3IgbWFuYWdlbWVudCBvZiBzdWNoIGVudGl0eSwgd2hldGhlciBieSBjb250cmFjdCBvcgogICAgICBvdGhlcndpc2UsIG9yIChpaSkgb3duZXJzaGlwIG9mIGZpZnR5IHBlcmNlbnQgKDUwJSkgb3IgbW9yZSBvZiB0aGUKICAgICAgb3V0c3RhbmRpbmcgc2hhcmVzLCBvciAoaWlpKSBiZW5lZmljaWFsIG93bmVyc2hpcCBvZiBzdWNoIGVudGl0eS4KCiAgICAgICJZb3UiIChvciAiWW91ciIpIHNoYWxsIG1lYW4gYW4gaW5kaXZpZHVhbCBvciBMZWdhbCBFbnRpdHkKICAgICAgZXhlcmNpc2luZyBwZXJtaXNzaW9ucyBncmFudGVkIGJ5IHRoaXMgTGljZW5zZS4KCiAgICAgICJTb3VyY2UiIGZvcm0gc2hhbGwgbWVhbiB0aGUgcHJlZmVycmVkIGZvcm0gZm9yIG1ha2luZyBtb2RpZmljYXRpb25zLAogICAgICBpbmNsdWRpbmcgYnV0IG5vdCBsaW1pdGVkIHRvIHNvZnR3YXJlIHNvdXJjZSBjb2RlLCBkb2N1bWVudGF0aW9uCiAgICAgIHNvdXJjZSwgYW5kIGNvbmZpZ3VyYXRpb24gZmlsZXMuCgogICAgICAiT2JqZWN0IiBmb3JtIHNoYWxsIG1lYW4gYW55IGZvcm0gcmVzdWx0aW5nIGZyb20gbWVjaGFuaWNhbAogICAgICB0cmFuc2Zvcm1hdGlvbiBvciB0cmFuc2xhdGlvbiBvZiBhIFNvdXJjZSBmb3JtLCBpbmNsdWRpbmcgYnV0CiAgICAgIG5vdCBsaW1pdGVkIHRvIGNvbXBpbGVkIG9iamVjdCBjb2RlLCBnZW5lcmF0ZWQgZG9jdW1lbnRhdGlvbiwKICAgICAgYW5kIGNvbnZlcnNpb25zIHRvIG90aGVyIG1lZGlhIHR5cGVzLgoKICAgICAgIldvcmsiIHNoYWxsIG1lYW4gdGhlIHdvcmsgb2YgYXV0aG9yc2hpcCwgd2hldGhlciBpbiBTb3VyY2Ugb3IKICAgICAgT2JqZWN0IGZvcm0sIG1hZGUgYXZhaWxhYmxlIHVuZGVyIHRoZSBMaWNlbnNlLCBhcyBpbmRpY2F0ZWQgYnkgYQogICAgICBjb3B5cmlnaHQgbm90aWNlIHRoYXQgaXMgaW5jbHVkZWQgaW4gb3IgYXR0YWNoZWQgdG8gdGhlIHdvcmsKICAgICAgKGFuIGV4YW1wbGUgaXMgcHJvdmlkZWQgaW4gdGhlIEFwcGVuZGl4IGJlbG93KS4KCiAgICAgICJEZXJpdmF0aXZlIFdvcmtzIiBzaGFsbCBtZWFuIGFueSB3b3JrLCB3aGV0aGVyIGluIFNvdXJjZSBvciBPYmplY3QKICAgICAgZm9ybSwgdGhhdCBpcyBiYXNlZCBvbiAob3IgZGVyaXZlZCBmcm9tKSB0aGUgV29yayBhbmQgZm9yIHdoaWNoIHRoZQogICAgICBlZGl0b3JpYWwgcmV2aXNpb25zLCBhbm5vdGF0aW9ucywgZWxhYm9yYXRpb25zLCBvciBvdGhlciBtb2RpZmljYXRpb25zCiAgICAgIHJlcHJlc2VudCwgYXMgYSB3aG9sZSwgYW4gb3JpZ2luYWwgd29yayBvZiBhdXRob3JzaGlwLiBGb3IgdGhlIHB1cnBvc2VzCiAgICAgIG9mIHRoaXMgTGljZW5zZSwgRGVyaXZhdGl2ZSBXb3JrcyBzaGFsbCBub3QgaW5jbHVkZSB3b3JrcyB0aGF0IHJlbWFpbgogICAgICBzZXBhcmFibGUgZnJvbSwgb3IgbWVyZWx5IGxpbmsgKG9yIGJpbmQgYnkgbmFtZSkgdG8gdGhlIGludGVyZmFjZXMgb2YsCiAgICAgIHRoZSBXb3JrIGFuZCBEZXJpdmF0aXZlIFdvcmtzIHRoZXJlb2YuCgogICAgICAiQ29udHJpYnV0aW9uIiBzaGFsbCBtZWFuIGFueSB3b3JrIG9mIGF1dGhvcnNoaXAsIGluY2x1ZGluZwogICAgICB0aGUgb3JpZ2luYWwgdmVyc2lvbiBvZiB0aGUgV29yayBhbmQgYW55IG1vZGlmaWNhdGlvbnMgb3IgYWRkaXRpb25zCiAgICAgIHRvIHRoYXQgV29yayBvciBEZXJpdmF0aXZlIFdvcmtzIHRoZXJlb2YsIHRoYXQgaXMgaW50ZW50aW9uYWxseQogICAgICBzdWJtaXR0ZWQgdG8gTGljZW5zb3IgZm9yIGluY2x1c2lvbiBpbiB0aGUgV29yayBieSB0aGUgY29weXJpZ2h0IG93bmVyCiAgICAgIG9yIGJ5IGFuIGluZGl2aWR1YWwgb3IgTGVnYWwgRW50aXR5IGF1dGhvcml6ZWQgdG8gc3VibWl0IG9uIGJlaGFsZiBvZgogICAgICB0aGUgY29weXJpZ2h0IG93bmVyLiBGb3IgdGhlIHB1cnBvc2VzIG9mIHRoaXMgZGVmaW5pdGlvbiwgInN1Ym1pdHRlZCIKICAgICAgbWVhbnMgYW55IGZvcm0gb2YgZWxlY3Ryb25pYywgdmVyYmFsLCBvciB3cml0dGVuIGNvbW11bmljYXRpb24gc2VudAogICAgICB0byB0aGUgTGljZW5zb3Igb3IgaXRzIHJlcHJlc2VudGF0aXZlcywgaW5jbHVkaW5nIGJ1dCBub3QgbGltaXRlZCB0bwogICAgICBjb21tdW5pY2F0aW9uIG9uIGVsZWN0cm9uaWMgbWFpbGluZyBsaXN0cywgc291cmNlIGNvZGUgY29udHJvbCBzeXN0ZW1zLAogICAgICBhbmQgaXNzdWUgdHJhY2tpbmcgc3lzdGVtcyB0aGF0IGFyZSBtYW5hZ2VkIGJ5LCBvciBvbiBiZWhhbGYgb2YsIHRoZQogICAgICBMaWNlbnNvciBmb3IgdGhlIHB1cnBvc2Ugb2YgZGlzY3Vzc2luZyBhbmQgaW1wcm92aW5nIHRoZSBXb3JrLCBidXQKICAgICAgZXhjbHVkaW5nIGNvbW11bmljYXRpb24gdGhhdCBpcyBjb25zcGljdW91c2x5IG1hcmtlZCBvciBvdGhlcndpc2UKICAgICAgZGVzaWduYXRlZCBpbiB3cml0aW5nIGJ5IHRoZSBjb3B5cmlnaHQgb3duZXIgYXMgIk5vdCBhIENvbnRyaWJ1dGlvbi4iCgogICAgICAiQ29udHJpYnV0b3IiIHNoYWxsIG1lYW4gTGljZW5zb3IgYW5kIGFueSBpbmRpdmlkdWFsIG9yIExlZ2FsIEVudGl0eQogICAgICBvbiBiZWhhbGYgb2Ygd2hvbSBhIENvbnRyaWJ1dGlvbiBoYXMgYmVlbiByZWNlaXZlZCBieSBMaWNlbnNvciBhbmQKICAgICAgc3Vic2VxdWVudGx5IGluY29ycG9yYXRlZCB3aXRoaW4gdGhlIFdvcmsuCgogICAyLiBHcmFudCBvZiBDb3B5cmlnaHQgTGljZW5zZS4gU3ViamVjdCB0byB0aGUgdGVybXMgYW5kIGNvbmRpdGlvbnMgb2YKICAgICAgdGhpcyBMaWNlbnNlLCBlYWNoIENvbnRyaWJ1dG9yIGhlcmVieSBncmFudHMgdG8gWW91IGEgcGVycGV0dWFsLAogICAgICB3b3JsZHdpZGUsIG5vbi1leGNsdXNpdmUsIG5vLWNoYXJnZSwgcm95YWx0eS1mcmVlLCBpcnJldm9jYWJsZQogICAgICBjb3B5cmlnaHQgbGljZW5zZSB0byByZXByb2R1Y2UsIHByZXBhcmUgRGVyaXZhdGl2ZSBXb3JrcyBvZiwKICAgICAgcHVibGljbHkgZGlzcGxheSwgcHVibGljbHkgcGVyZm9ybSwgc3VibGljZW5zZSwgYW5kIGRpc3RyaWJ1dGUgdGhlCiAgICAgIFdvcmsgYW5kIHN1Y2ggRGVyaXZhdGl2ZSBXb3JrcyBpbiBTb3VyY2Ugb3IgT2JqZWN0IGZvcm0uCgogICAzLiBHcmFudCBvZiBQYXRlbnQgTGljZW5zZS4gU3ViamVjdCB0byB0aGUgdGVybXMgYW5kIGNvbmRpdGlvbnMgb2YKICAgICAgdGhpcyBMaWNlbnNlLCBlYWNoIENvbnRyaWJ1dG9yIGhlcmVieSBncmFudHMgdG8gWW91IGEgcGVycGV0dWFsLAogICAgICB3b3JsZHdpZGUsIG5vbi1leGNsdXNpdmUsIG5vLWNoYXJnZSwgcm95YWx0eS1mcmVlLCBpcnJldm9jYWJsZQogICAgICAoZXhjZXB0IGFzIHN0YXRlZCBpbiB0aGlzIHNlY3Rpb24pIHBhdGVudCBsaWNlbnNlIHRvIG1ha2UsIGhhdmUgbWFkZSwKICAgICAgdXNlLCBvZmZlciB0byBzZWxsLCBzZWxsLCBpbXBvcnQsIGFuZCBvdGhlcndpc2UgdHJhbnNmZXIgdGhlIFdvcmssCiAgICAgIHdoZXJlIHN1Y2ggbGljZW5zZSBhcHBsaWVzIG9ubHkgdG8gdGhvc2UgcGF0ZW50IGNsYWltcyBsaWNlbnNhYmxlCiAgICAgIGJ5IHN1Y2ggQ29udHJpYnV0b3IgdGhhdCBhcmUgbmVjZXNzYXJpbHkgaW5mcmluZ2VkIGJ5IHRoZWlyCiAgICAgIENvbnRyaWJ1dGlvbihzKSBhbG9uZSBvciBieSBjb21iaW5hdGlvbiBvZiB0aGVpciBDb250cmlidXRpb24ocykKICAgICAgd2l0aCB0aGUgV29yayB0byB3aGljaCBzdWNoIENvbnRyaWJ1dGlvbihzKSB3YXMgc3VibWl0dGVkLiBJZiBZb3UKICAgICAgaW5zdGl0dXRlIHBhdGVudCBsaXRpZ2F0aW9uIGFnYWluc3QgYW55IGVudGl0eSAoaW5jbHVkaW5nIGEKICAgICAgY3Jvc3MtY2xhaW0gb3IgY291bnRlcmNsYWltIGluIGEgbGF3c3VpdCkgYWxsZWdpbmcgdGhhdCB0aGUgV29yawogICAgICBvciBhIENvbnRyaWJ1dGlvbiBpbmNvcnBvcmF0ZWQgd2l0aGluIHRoZSBXb3JrIGNvbnN0aXR1dGVzIGRpcmVjdAogICAgICBvciBjb250cmlidXRvcnkgcGF0ZW50IGluZnJpbmdlbWVudCwgdGhlbiBhbnkgcGF0ZW50IGxpY2Vuc2VzCiAgICAgIGdyYW50ZWQgdG8gWW91IHVuZGVyIHRoaXMgTGljZW5zZSBmb3IgdGhhdCBXb3JrIHNoYWxsIHRlcm1pbmF0ZQogICAgICBhcyBvZiB0aGUgZGF0ZSBzdWNoIGxpdGlnYXRpb24gaXMgZmlsZWQuCgogICA0LiBSZWRpc3RyaWJ1dGlvbi4gWW91IG1heSByZXByb2R1Y2UgYW5kIGRpc3RyaWJ1dGUgY29waWVzIG9mIHRoZQogICAgICBXb3JrIG9yIERlcml2YXRpdmUgV29ya3MgdGhlcmVvZiBpbiBhbnkgbWVkaXVtLCB3aXRoIG9yIHdpdGhvdXQKICAgICAgbW9kaWZpY2F0aW9ucywgYW5kIGluIFNvdXJjZSBvciBPYmplY3QgZm9ybSwgcHJvdmlkZWQgdGhhdCBZb3UKICAgICAgbWVldCB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6CgogICAgICAoYSkgWW91IG11c3QgZ2l2ZSBhbnkgb3RoZXIgcmVjaXBpZW50cyBvZiB0aGUgV29yayBvcgogICAgICAgICAgRGVyaXZhdGl2ZSBXb3JrcyBhIGNvcHkgb2YgdGhpcyBMaWNlbnNlOyBhbmQKCiAgICAgIChiKSBZb3UgbXVzdCBjYXVzZSBhbnkgbW9kaWZpZWQgZmlsZXMgdG8gY2FycnkgcHJvbWluZW50IG5vdGljZXMKICAgICAgICAgIHN0YXRpbmcgdGhhdCBZb3UgY2hhbmdlZCB0aGUgZmlsZXM7IGFuZAoKICAgICAgKGMpIFlvdSBtdXN0IHJldGFpbiwgaW4gdGhlIFNvdXJjZSBmb3JtIG9mIGFueSBEZXJpdmF0aXZlIFdvcmtzCiAgICAgICAgICB0aGF0IFlvdSBkaXN0cmlidXRlLCBhbGwgY29weXJpZ2h0LCBwYXRlbnQsIHRyYWRlbWFyaywgYW5kCiAgICAgICAgICBhdHRyaWJ1dGlvbiBub3RpY2VzIGZyb20gdGhlIFNvdXJjZSBmb3JtIG9mIHRoZSBXb3JrLAogICAgICAgICAgZXhjbHVkaW5nIHRob3NlIG5vdGljZXMgdGhhdCBkbyBub3QgcGVydGFpbiB0byBhbnkgcGFydCBvZgogICAgICAgICAgdGhlIERlcml2YXRpdmUgV29ya3M7IGFuZAoKICAgICAgKGQpIElmIHRoZSBXb3JrIGluY2x1ZGVzIGEgIk5PVElDRSIgdGV4dCBmaWxlIGFzIHBhcnQgb2YgaXRzCiAgICAgICAgICBkaXN0cmlidXRpb24sIHRoZW4gYW55IERlcml2YXRpdmUgV29ya3MgdGhhdCBZb3UgZGlzdHJpYnV0ZSBtdXN0CiAgICAgICAgICBpbmNsdWRlIGEgcmVhZGFibGUgY29weSBvZiB0aGUgYXR0cmlidXRpb24gbm90aWNlcyBjb250YWluZWQKICAgICAgICAgIHdpdGhpbiBzdWNoIE5PVElDRSBmaWxlLCBleGNsdWRpbmcgdGhvc2Ugbm90aWNlcyB0aGF0IGRvIG5vdAogICAgICAgICAgcGVydGFpbiB0byBhbnkgcGFydCBvZiB0aGUgRGVyaXZhdGl2ZSBXb3JrcywgaW4gYXQgbGVhc3Qgb25lCiAgICAgICAgICBvZiB0aGUgZm9sbG93aW5nIHBsYWNlczogd2l0aGluIGEgTk9USUNFIHRleHQgZmlsZSBkaXN0cmlidXRlZAogICAgICAgICAgYXMgcGFydCBvZiB0aGUgRGVyaXZhdGl2ZSBXb3Jrczsgd2l0aGluIHRoZSBTb3VyY2UgZm9ybSBvcgogICAgICAgICAgZG9jdW1lbnRhdGlvbiwgaWYgcHJvdmlkZWQgYWxvbmcgd2l0aCB0aGUgRGVyaXZhdGl2ZSBXb3Jrczsgb3IsCiAgICAgICAgICB3aXRoaW4gYSBkaXNwbGF5IGdlbmVyYXRlZCBieSB0aGUgRGVyaXZhdGl2ZSBXb3JrcywgaWYgYW5kCiAgICAgICAgICB3aGVyZXZlciBzdWNoIHRoaXJkLXBhcnR5IG5vdGljZXMgbm9ybWFsbHkgYXBwZWFyLiBUaGUgY29udGVudHMKICAgICAgICAgIG9mIHRoZSBOT1RJQ0UgZmlsZSBhcmUgZm9yIGluZm9ybWF0aW9uYWwgcHVycG9zZXMgb25seSBhbmQKICAgICAgICAgIGRvIG5vdCBtb2RpZnkgdGhlIExpY2Vuc2UuIFlvdSBtYXkgYWRkIFlvdXIgb3duIGF0dHJpYnV0aW9uCiAgICAgICAgICBub3RpY2VzIHdpdGhpbiBEZXJpdmF0aXZlIFdvcmtzIHRoYXQgWW91IGRpc3RyaWJ1dGUsIGFsb25nc2lkZQogICAgICAgICAgb3IgYXMgYW4gYWRkZW5kdW0gdG8gdGhlIE5PVElDRSB0ZXh0IGZyb20gdGhlIFdvcmssIHByb3ZpZGVkCiAgICAgICAgICB0aGF0IHN1Y2ggYWRkaXRpb25hbCBhdHRyaWJ1dGlvbiBub3RpY2VzIGNhbm5vdCBiZSBjb25zdHJ1ZWQKICAgICAgICAgIGFzIG1vZGlmeWluZyB0aGUgTGljZW5zZS4KCiAgICAgIFlvdSBtYXkgYWRkIFlvdXIgb3duIGNvcHlyaWdodCBzdGF0ZW1lbnQgdG8gWW91ciBtb2RpZmljYXRpb25zIGFuZAogICAgICBtYXkgcHJvdmlkZSBhZGRpdGlvbmFsIG9yIGRpZmZlcmVudCBsaWNlbnNlIHRlcm1zIGFuZCBjb25kaXRpb25zCiAgICAgIGZvciB1c2UsIHJlcHJvZHVjdGlvbiwgb3IgZGlzdHJpYnV0aW9uIG9mIFlvdXIgbW9kaWZpY2F0aW9ucywgb3IKICAgICAgZm9yIGFueSBzdWNoIERlcml2YXRpdmUgV29ya3MgYXMgYSB3aG9sZSwgcHJvdmlkZWQgWW91ciB1c2UsCiAgICAgIHJlcHJvZHVjdGlvbiwgYW5kIGRpc3RyaWJ1dGlvbiBvZiB0aGUgV29yayBvdGhlcndpc2UgY29tcGxpZXMgd2l0aAogICAgICB0aGUgY29uZGl0aW9ucyBzdGF0ZWQgaW4gdGhpcyBMaWNlbnNlLgoKICAgNS4gU3VibWlzc2lvbiBvZiBDb250cmlidXRpb25zLiBVbmxlc3MgWW91IGV4cGxpY2l0bHkgc3RhdGUgb3RoZXJ3aXNlLAogICAgICBhbnkgQ29udHJpYnV0aW9uIGludGVudGlvbmFsbHkgc3VibWl0dGVkIGZvciBpbmNsdXNpb24gaW4gdGhlIFdvcmsKICAgICAgYnkgWW91IHRvIHRoZSBMaWNlbnNvciBzaGFsbCBiZSB1bmRlciB0aGUgdGVybXMgYW5kIGNvbmRpdGlvbnMgb2YKICAgICAgdGhpcyBMaWNlbnNlLCB3aXRob3V0IGFueSBhZGRpdGlvbmFsIHRlcm1zIG9yIGNvbmRpdGlvbnMuCiAgICAgIE5vdHdpdGhzdGFuZGluZyB0aGUgYWJvdmUsIG5vdGhpbmcgaGVyZWluIHNoYWxsIHN1cGVyc2VkZSBvciBtb2RpZnkKICAgICAgdGhlIHRlcm1zIG9mIGFueSBzZXBhcmF0ZSBsaWNlbnNlIGFncmVlbWVudCB5b3UgbWF5IGhhdmUgZXhlY3V0ZWQKICAgICAgd2l0aCBMaWNlbnNvciByZWdhcmRpbmcgc3VjaCBDb250cmlidXRpb25zLgoKICAgNi4gVHJhZGVtYXJrcy4gVGhpcyBMaWNlbnNlIGRvZXMgbm90IGdyYW50IHBlcm1pc3Npb24gdG8gdXNlIHRoZSB0cmFkZQogICAgICBuYW1lcywgdHJhZGVtYXJrcywgc2VydmljZSBtYXJrcywgb3IgcHJvZHVjdCBuYW1lcyBvZiB0aGUgTGljZW5zb3IsCiAgICAgIGV4Y2VwdCBhcyByZXF1aXJlZCBmb3IgcmVhc29uYWJsZSBhbmQgY3VzdG9tYXJ5IHVzZSBpbiBkZXNjcmliaW5nIHRoZQogICAgICBvcmlnaW4gb2YgdGhlIFdvcmsgYW5kIHJlcHJvZHVjaW5nIHRoZSBjb250ZW50IG9mIHRoZSBOT1RJQ0UgZmlsZS4KCiAgIDcuIERpc2NsYWltZXIgb2YgV2FycmFudHkuIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvcgogICAgICBhZ3JlZWQgdG8gaW4gd3JpdGluZywgTGljZW5zb3IgcHJvdmlkZXMgdGhlIFdvcmsgKGFuZCBlYWNoCiAgICAgIENvbnRyaWJ1dG9yIHByb3ZpZGVzIGl0cyBDb250cmlidXRpb25zKSBvbiBhbiAiQVMgSVMiIEJBU0lTLAogICAgICBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IKICAgICAgaW1wbGllZCwgaW5jbHVkaW5nLCB3aXRob3V0IGxpbWl0YXRpb24sIGFueSB3YXJyYW50aWVzIG9yIGNvbmRpdGlvbnMKICAgICAgb2YgVElUTEUsIE5PTi1JTkZSSU5HRU1FTlQsIE1FUkNIQU5UQUJJTElUWSwgb3IgRklUTkVTUyBGT1IgQQogICAgICBQQVJUSUNVTEFSIFBVUlBPU0UuIFlvdSBhcmUgc29sZWx5IHJlc3BvbnNpYmxlIGZvciBkZXRlcm1pbmluZyB0aGUKICAgICAgYXBwcm9wcmlhdGVuZXNzIG9mIHVzaW5nIG9yIHJlZGlzdHJpYnV0aW5nIHRoZSBXb3JrIGFuZCBhc3N1bWUgYW55CiAgICAgIHJpc2tzIGFzc29jaWF0ZWQgd2l0aCBZb3VyIGV4ZXJjaXNlIG9mIHBlcm1pc3Npb25zIHVuZGVyIHRoaXMgTGljZW5zZS4KCiAgIDguIExpbWl0YXRpb24gb2YgTGlhYmlsaXR5LiBJbiBubyBldmVudCBhbmQgdW5kZXIgbm8gbGVnYWwgdGhlb3J5LAogICAgICB3aGV0aGVyIGluIHRvcnQgKGluY2x1ZGluZyBuZWdsaWdlbmNlKSwgY29udHJhY3QsIG9yIG90aGVyd2lzZSwKICAgICAgdW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IChzdWNoIGFzIGRlbGliZXJhdGUgYW5kIGdyb3NzbHkKICAgICAgbmVnbGlnZW50IGFjdHMpIG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzaGFsbCBhbnkgQ29udHJpYnV0b3IgYmUKICAgICAgbGlhYmxlIHRvIFlvdSBmb3IgZGFtYWdlcywgaW5jbHVkaW5nIGFueSBkaXJlY3QsIGluZGlyZWN0LCBzcGVjaWFsLAogICAgICBpbmNpZGVudGFsLCBvciBjb25zZXF1ZW50aWFsIGRhbWFnZXMgb2YgYW55IGNoYXJhY3RlciBhcmlzaW5nIGFzIGEKICAgICAgcmVzdWx0IG9mIHRoaXMgTGljZW5zZSBvciBvdXQgb2YgdGhlIHVzZSBvciBpbmFiaWxpdHkgdG8gdXNlIHRoZQogICAgICBXb3JrIChpbmNsdWRpbmcgYnV0IG5vdCBsaW1pdGVkIHRvIGRhbWFnZXMgZm9yIGxvc3Mgb2YgZ29vZHdpbGwsCiAgICAgIHdvcmsgc3RvcHBhZ2UsIGNvbXB1dGVyIGZhaWx1cmUgb3IgbWFsZnVuY3Rpb24sIG9yIGFueSBhbmQgYWxsCiAgICAgIG90aGVyIGNvbW1lcmNpYWwgZGFtYWdlcyBvciBsb3NzZXMpLCBldmVuIGlmIHN1Y2ggQ29udHJpYnV0b3IKICAgICAgaGFzIGJlZW4gYWR2aXNlZCBvZiB0aGUgcG9zc2liaWxpdHkgb2Ygc3VjaCBkYW1hZ2VzLgoKICAgOS4gQWNjZXB0aW5nIFdhcnJhbnR5IG9yIEFkZGl0aW9uYWwgTGlhYmlsaXR5LiBXaGlsZSByZWRpc3RyaWJ1dGluZwogICAgICB0aGUgV29yayBvciBEZXJpdmF0aXZlIFdvcmtzIHRoZXJlb2YsIFlvdSBtYXkgY2hvb3NlIHRvIG9mZmVyLAogICAgICBhbmQgY2hhcmdlIGEgZmVlIGZvciwgYWNjZXB0YW5jZSBvZiBzdXBwb3J0LCB3YXJyYW50eSwgaW5kZW1uaXR5LAogICAgICBvciBvdGhlciBsaWFiaWxpdHkgb2JsaWdhdGlvbnMgYW5kL29yIHJpZ2h0cyBjb25zaXN0ZW50IHdpdGggdGhpcwogICAgICBMaWNlbnNlLiBIb3dldmVyLCBpbiBhY2NlcHRpbmcgc3VjaCBvYmxpZ2F0aW9ucywgWW91IG1heSBhY3Qgb25seQogICAgICBvbiBZb3VyIG93biBiZWhhbGYgYW5kIG9uIFlvdXIgc29sZSByZXNwb25zaWJpbGl0eSwgbm90IG9uIGJlaGFsZgogICAgICBvZiBhbnkgb3RoZXIgQ29udHJpYnV0b3IsIGFuZCBvbmx5IGlmIFlvdSBhZ3JlZSB0byBpbmRlbW5pZnksCiAgICAgIGRlZmVuZCwgYW5kIGhvbGQgZWFjaCBDb250cmlidXRvciBoYXJtbGVzcyBmb3IgYW55IGxpYWJpbGl0eQogICAgICBpbmN1cnJlZCBieSwgb3IgY2xhaW1zIGFzc2VydGVkIGFnYWluc3QsIHN1Y2ggQ29udHJpYnV0b3IgYnkgcmVhc29uCiAgICAgIG9mIHlvdXIgYWNjZXB0aW5nIGFueSBzdWNoIHdhcnJhbnR5IG9yIGFkZGl0aW9uYWwgbGlhYmlsaXR5LgoKICAgRU5EIE9GIFRFUk1TIEFORCBDT05ESVRJT05TCgogICBBUFBFTkRJWDogSG93IHRvIGFwcGx5IHRoZSBBcGFjaGUgTGljZW5zZSB0byB5b3VyIHdvcmsuCgogICAgICBUbyBhcHBseSB0aGUgQXBhY2hlIExpY2Vuc2UgdG8geW91ciB3b3JrLCBhdHRhY2ggdGhlIGZvbGxvd2luZwogICAgICBib2lsZXJwbGF0ZSBub3RpY2UsIHdpdGggdGhlIGZpZWxkcyBlbmNsb3NlZCBieSBicmFja2V0cyAiW10iCiAgICAgIHJlcGxhY2VkIHdpdGggeW91ciBvd24gaWRlbnRpZnlpbmcgaW5mb3JtYXRpb24uIChEb24ndCBpbmNsdWRlCiAgICAgIHRoZSBicmFja2V0cyEpICBUaGUgdGV4dCBzaG91bGQgYmUgZW5jbG9zZWQgaW4gdGhlIGFwcHJvcHJpYXRlCiAgICAgIGNvbW1lbnQgc3ludGF4IGZvciB0aGUgZmlsZSBmb3JtYXQuIFdlIGFsc28gcmVjb21tZW5kIHRoYXQgYQogICAgICBmaWxlIG9yIGNsYXNzIG5hbWUgYW5kIGRlc2NyaXB0aW9uIG9mIHB1cnBvc2UgYmUgaW5jbHVkZWQgb24gdGhlCiAgICAgIHNhbWUgInByaW50ZWQgcGFnZSIgYXMgdGhlIGNvcHlyaWdodCBub3RpY2UgZm9yIGVhc2llcgogICAgICBpZGVudGlmaWNhdGlvbiB3aXRoaW4gdGhpcmQtcGFydHkgYXJjaGl2ZXMuCgogICBDb3B5cmlnaHQgW3l5eXldIFtuYW1lIG9mIGNvcHlyaWdodCBvd25lcl0KCiAgIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSAiTGljZW5zZSIpOwogICB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuCiAgIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdAoKICAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMAoKICAgVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZQogICBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiAiQVMgSVMiIEJBU0lTLAogICBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC4KICAgU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZAogICBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS4=</text>
+                    <url>https://www.apache.org/licenses/LICENSE-2.0.txt</url>
+                </license>
+            </licenses>
+            <purl>pkg:maven/com.acme/tomcat-catalina@9.0.14?packaging=jar</purl>
+            <pedigree>
+                <ancestors>
+                    <component type="application">
+                        <author>Apache Super Heros</author>
+                        <publisher>Apache</publisher>
+                        <group>org.apache.tomcat</group>
+                        <name>tomcat-catalina</name>
+                        <version>9.0.14</version>
+                        <description>Apache Catalina</description>
+                        <licenses>
+                            <license>
+                                <id>Apache-2.0</id>
+                            </license>
+                        </licenses>
+                        <purl>pkg:maven/org.apache.tomcat/tomcat-catalina@9.0.14?packaging=jar</purl>
+                    </component>
+                </ancestors>
+                <commits>
+                    <commit>
+                        <uid>7638417db6d59f3c431d3e1f261cc637155684cd</uid>
+                        <url>https://location/to/7638417db6d59f3c431d3e1f261cc637155684cd</url>
+                        <author>
+                            <timestamp>2018-11-07T22:01:45Z</timestamp>
+                            <name>John Doe</name>
+                            <email>john.doe@example.com</email>
+                        </author>
+                        <committer>
+                            <timestamp>2018-11-07T22:01:45Z</timestamp>
+                            <name>Jane Doe</name>
+                            <email>jane.doe@example.com</email>
+                        </committer>
+                        <message>Initial commit</message>
+                    </commit>
+                </commits>
+                <notes>Commentary here</notes>
+            </pedigree>
+        </component>
+        <component type="library">
+            <supplier>
+                <name>Example Inc.</name>
+                <url>https://example.com</url>
+                <url>https://example.net</url>
+                <contact>
+                    <name>Example Support AMER</name>
+                    <email>support@example.com</email>
+                    <phone>800-555-1212</phone>
+                </contact>
+                <contact>
+                    <name>Example Support APAC</name>
+                    <email>support@apac.example.com</email>
+                </contact>
+            </supplier>
+            <author>Example Super Heros</author>
+            <group>org.example</group>
+            <name>mylibrary</name>
+            <version>1.0.0</version>
+            <scope>required</scope>
+            <hashes>
+                <hash alg="MD5">2342c2eaf1feb9a80195dbaddf2ebaa3</hash>
+                <hash alg="SHA-1">68b78babe00a053f9e35ec6a2d9080f5b90122b0</hash>
+                <hash alg="SHA-256">708f1f53b41f11f02d12a11b1a38d2905d47b099afc71a0f1124ef8582ec7313</hash>
+                <hash alg="SHA-512">387b7ae16b9cae45f830671541539bf544202faae5aac544a93b7b0a04f5f846fa2f4e81ef3f1677e13aed7496408a441f5657ab6d54423e56bf6f38da124aef</hash>
+            </hashes>
+            <licenses>
+                <expression>EPL-2.0 OR GPL-2.0-with-classpath-exception</expression>
+            </licenses>
+            <copyright>Copyright Example Inc. All rights reserved.</copyright>
+            <cpe>cpe:/a:example:myapplication:1.0.0</cpe>
+            <purl>pkg:maven/com.example/myapplication@1.0.0?packaging=war</purl>
+            <modified>false</modified>
+            <externalReferences>
+                <reference type="documentation">
+                    <url>http://example.org/docs</url>
+                    <comment>All component versions are documented here</comment>
+                </reference>
+                <reference type="advisories">
+                    <url>http://example.org/security</url>
+                </reference>
+            </externalReferences>
+        </component>
+        <component type="framework">
+            <author>Example Super Heros</author>
+            <group>com.example</group>
+            <name>myframework</name>
+            <version>1.0.0</version>
+            <description>Example Inc, enterprise framework</description>
+            <scope>required</scope>
+            <hashes>
+                <hash alg="MD5">cfcb0b64aacd2f81c1cd546543de965a</hash>
+                <hash alg="SHA-1">7fbeef2346c45d565c3341f037bce4e088af8a52</hash>
+                <hash alg="SHA-256">0384db3cec55d86a6898c489fdb75a8e75fe66b26639634983d2f3c3558493d1</hash>
+                <hash alg="SHA-512">854909cdb9e3ca183056837144aab6d8069b377bd66445087cc7157bf0c3f620418705dd0b83bdc2f73a508c2bdb316ca1809d75ee6972d02023a3e7dd655c79</hash>
+            </hashes>
+            <licenses>
+                <license>
+                    <name>Some random license</name>
+                </license>
+            </licenses>
+            <purl>pkg:maven/com.example/myframework@1.0.0?packaging=war</purl>
+            <modified>false</modified>
+            <externalReferences>
+                <reference type="website">
+                    <url>http://example.com/myframework</url>
+                </reference>
+                <reference type="advisories">
+                    <url>http://example.com/security</url>
+                </reference>
+            </externalReferences>
+        </component>
+    </components>
+</bom>