Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Add suggestions by Christian

...

The aim of the Project Dependency Trees model is to resolve these issues.

Project Dependency Trees documents are intended to be machine generated based on build time information. Build tools not able to generate these documents solely from build information are considered in need for corresponding enhancements.

Model evolution

One of the top level elements of the Maven POM is the modelVersion element that specifies the model version for the POM. To date there have been two model versions 3.0.0 and 4.0.0. In both cases, a critical issue for changing the model version is that older clients cannot parse the newer model. This required the forking of Central (which is why central is repo.maven.org/maven2 because 4.0.0 was introduced with Maven 2 and Maven 1 clients could not parse the new model version)

...

<project modelVersion="..." groupId="..." artifactId="..." [platformId="..."] version="...">
<generator .../>
  <information .../>
  <license .../>
  <artifacts .../>
</project>

...

  • modelVersion attribute - containing the model version of the project dependency trees, which can be used by consumers to select an XSLT tranformation to apply against the model if they need to translate a newer modelVersion to one that the consumer can parse.
  • groupId attribute - containing the groupId of the project
  • artifactId attribute - containing the artifactId of the project
  • version attribute - containing the version of the project
  • artifacts element - at least one element must be present, there are uniqueness constraints on this element relating to platformId attributes
  • generator element - there must be exactly one generator element present. This element identifies the build tool that generated the Project Dependency Trees document.

The following are optional elements:

  • platformId attribute - this is only present for additional atomic deployments of platform specific artifacts taking place after the initial deployment. When present there must be exactly one artifacts element and it must have the matching platformId as specified on the project element.
  • information element - there can be at most one of these, it contains additional information about the project and its artifacts
  • license elements - there can be any number of these, each element represents a set of licensing terms under which the project's artifacts are made available.

    In the vast majority of cases, projects are covered by a single set of license terms. Those cases will have a single <license> element that provides the SPDX expression for the license terms, e.g. <license spdx="(LGPL-2.0 AND GPL-2.0)"> which would indicate that portions of the code are LGPL and other portions are GPL.

    In other cases, projects are dual or multi-licensed. Those cases will have multiple <license> elements where the consumer is free to select any one of those expressions as the license terms that they will be complying with, thus <license spdx="GPL-2.0"/><license spdx="(BSD-2-Clause AND Apache-2.0)"/> would indicate that the consumer either has to comply with the terms of the GPL or both BSD and Apache licenses. While SPDX syntax would allow for <license spdx="(GPL-2.0 OR BSD-2-Clause AND Apache-2.0)"/> as an equivalent expression, dual licensing seems important enough that it should be separated out explicitly in separate elements as the priority rules of SPDX expression syntax - while clear and unambiguous - can be confusing to the uninitiated with regard to OR being lower priority than AND

...

<generator> element

The information element consists of optional information about the project and its artifacts.

TODO: decide what, if any, additional content can go in here, SCM, Issue trackers, URLs, Mailing Lists, etc.

<information>
 <name .../>
 <description .../>
</information>

There are no mandatory elements

The following are optional elements:

  • name element - containing the name of the project (or when the <information> tag is scoped to a specific <artifact> overriding the project name for that specific artifact)
  • description element - containing the description of the project (or when the <information> tag is scoped to a specific <artifact> the description of that specific artifact)

<license> element

The license element consists of information about one set of licensing terms that the project and its artifacts is made available under.

<license spdx="..."/>

There is one mandatory element

generator element identifies the build tool that created the document.

<generator name="..." version="..." url="..."/>

The following are mandatory elements

  • name the human readable name of the build tool, e.g. Apache MavenApache BuildrRakeGradle, etc.
  • version the version of the build tool
  • url the url of the home page of build tool, e.g. http://maven.apache.orghttp://buildr.apache.orghttp://rake.rubyforge.orghttp://gradle.org, etc. This is not the download URL for the build tool

There are no optional elements

<information> element

The information element consists of optional information about the project and its artifacts.

TODO: decide what, if any, additional content can go in here, SCM, Issue trackers, URLs, Mailing Lists, etc.

<information>
 <name .../>
 <description .../>
</information>

There are no mandatory elements

The following are optional elements:

  • name element - containing the name of the project (or when the <information> spdx attribute - containing a SPDX expression for a single set of terms that the project and its artifacts (or when the <license> tag is scoped to a specific <artifact> overriding the project licenses name for that specific artifact) are made available under. The SPDX expression may not contain OR operators. Instead the SPDX expression must be normalized to remove OR operators and instead present each disjoint set of licenses as a separate <license> tag.
  • description element - containing the description of the project (or when the <information> tag is scoped to a specific <artifact> the description of that specific artifact)

<license> element

The license element consists of information about one set of licensing terms that the project and its artifacts is made available under.

<license spdx="..."/>

There is one mandatory element

  • spdx attribute - containing a SPDX expression for a single set of terms that the project and its artifacts (or when the <license> tag is scoped to a specific <artifact> overriding the project licenses for that specific artifact) are made available under. The SPDX expression may not contain OR operators. Instead the SPDX expression must be normalized to remove OR operators and instead present each disjoint set of licenses as a separate <license> tag.

There are There are no optional elements

<artifacts> element

...

<project modelVersion="..." groupId="..." artifactId="..." [platformId="..."] version="...">
     <information>  <generator name="Apache Maven" version="5.0.0" url="http://maven.apache.org"/>
    <information>
        <!-- container for descriptive information -->
        [<name>...</name>]
        [<description>...</description>]
        ...
    </information>
<license spdx="..."/>
<license spdx="..."/>
...
<license spdx="..."/>
    <artifacts [platformId="..."]>
        <artifact type="..." [classifier="..."]>
            <information>
                <!-- optional element if need to override root level information for specific artifacts -->
            </information>
            <!-- 
              components are internal packaging constructs used by the packaging type but requiring more general validation
              e.g. for Java 9+ the ids could be the module ids if we wanted to validate that the module ids were unique in the
              effective tree.
            -->
            <component id="..."/>
            <component id="..."/>
            ...
            <component id="..."/>
            <!--
If the artifact has a different set of licenses from those defined at the project level, we define the licenses
of this artifact here. Otherwise we defer to the licenses defined at the top level of the project.
              licensing is a top level concern, and legitimately can vary per artifact. Let's not solve license compatibility, 
              rather leverage https://spdx.org/
            -->
            <license spdx="..."/>
            <license spdx="..."/>
            ...
            <license spdx="..."/>
            <!--
              provides is a marker that we have duplication of content. This could be because we are much like the many servlet-api jar
              files where there are many GAV's of the same javax.servlet:servlet-api:3.0 thus we could have the case where
 
              org.jboss.spec.javax.servlet:jboss-servlet-api_3.0_spec:jar:1.0.2.Final PROVIDES javax.servlet:servlet-api:3.0
              org.jboss.spec.javax.servlet:jboss-servlet-api_3.0_spec:jar:1.0.1.Final PROVIDES javax.servlet:servlet-api:3.0
              org.jboss.spec.javax.servlet:jboss-servlet-api_3.0_spec:jar:1.0.0.Final PROVIDES javax.servlet:servlet-api:3.0
              org.mortbay.jetty:servlet-api-3.0:jar:7.0.0pre2 PROVIDES javax.servlet:servlet-api:3.0
 
              similarly
 
              org.slf4j:log4j-over-slf4j:jar:1.7.21 PROVIDES log4j:log4j:[1.0,2)
 
              The consumer of the tree can then decide if/when/how to collapse redundant nodes as they see fit.
 
              TODO: decide optionality of version and range attributes
            -->
            <provides groupId="..." artifactId="..." [platformId="..."] version="..." [range="..."] type="..." [classifier="..."]>
                <!-- no elements here as we have "rebundled" hence implicitly promoted up one level-->
            </provides>
            <provides groupId="..." artifactId="..." [platformId="..."] version="..." [range="..."] type="..." [classifier="..."]/>
            ...
            <provides groupId="..." artifactId="..." [platformId="..."] version="..." [range="..."] type="..." [classifier="..."]/>
            <!--
              requires are the mandatory dependencies. This is effectively a recursive artifact where the GAV is not inherited and
              where we have discarded the information section. If you want those details, fetch that project's dependencies trees.
            -->
            <requires groupId="..." artifactId="..." [platformId="..."] version="..." range="..." type="..." [classifier="..."]>
                <component id="..."/>
                <license spdx:id="..."/>
                <provides groupId="..." artifactId="..." [platformId="..."] version="..." [range="..."] type="..." [classifier="..."]/>
                <requires groupId="..." artifactId="..." [platformId="..."] version="..." range="..." type="..." [classifier="..."]>
                    ...
                </requires>
                <supports groupId="..." artifactId="..." [platformId="..."] version="..." [range="..."] type="..." [classifier="..."]/>
            </requires>
            <requires groupId="..." artifactId="..." [platformId="..."] version="..." range="..." type="..." [classifier="..."]>
                ...
            </requires>
            ...
            <requires groupId="..." artifactId="..." [platformId="..."] version="..." range="..." type="..." [classifier="..."]>
                ...
            </requires>
            <!--
              supports are the optional dependencies. We list them here to aid in conflict resolution. We do not include a nested tree
              as a consumer would only pull them in if the consumer already has its own a requires for them, so we really only
              need to validate the range. 
 
              TODO: decide optionality of range attribute
              TODO: decide if we want a version attribute 
            -->
            <supports groupId="..." artifactId="..." [platformId="..."] version="..." [range="..."] type="..." [classifier="..."]/>
            <supports groupId="..." artifactId="..." [platformId="..."] version="..." [range="..."] type="..." [classifier="..."]/>
            <supports groupId="..." artifactId="..." [platformId="..."] version="..." [range="..."] type="..." [classifier="..."]/>
        </artifact>
        <artifact ...>
            ...
        </artifact>
        ...
        <artifact ...>
            ...
        </artifact>
    </artifacts>
<!-- if the project does not specify a platformId then we can include additional platform details that were part of the atomic deployment -->
<artifacts platformId="...">
...
</artifacts>
...
<artifacts platformId="...">
...
</artifacts>
</project>

...

TODO: We need a cohort of sample transformations of trees to ensure that implementations can correctly aggregate Project Dependency Trees when building new projects that depend on other projects.

Schema

Here is a draft XML schema:

<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema" >

when building new projects that depend on other projects.

Schema

Here is a draft XML schema:

<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema" >
<xsd:simpleType name=”coordinate”>
<xsd:restriction base=”xsd:string”>
<!-- TODO add pattern for groupId/artifactId/platformId/version/type/classifier valid values -->
</xsd:restriction>
</xsd:simpleType>
<xs:element name="project">
<xs:annotation>
<xs:documentation source="version">5.0.0+</xs:documentation>
<xs:documentation source="description">
The <code>&lt;project&gt;</code> element is the root of the project
dependency trees.
</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:attribute name="modelVersion" type="xs:string"/>
<xs:attribute name="groupId" type="coordinate"/>
<xs:attribute name="artifactId" type="coordinate"/>
<xs:attribute name="version" type="coordinate"/>
<xs:attribute name="platformId" type="coordinate" use="optional"/>
<xs:all>
<xs:element ref="generator" minOccurs="1" maxOccurs="1"/>
<xs:element ref="information" minOccurs="0" maxOccurs="1"/>
<xs:element ref="license" minOccurs="0" maxOccurs="unbounded"/>
<xs:element ref="artifacts" minOccurs="1" maxOccurs="unbounded"/>
</xs:all>
</xs:complexType>
</xs:element><xsd:simpleType name=”coordinate”>
<xsd:restriction base=”xsd:string”>
<!-- TODO add pattern for groupId/artifactId/platformId/version/type/classifier valid values -->
</xsd:restriction>
</xsd:simpleType>
<xs:element name="projectgenerator">
<xs:annotation>
<xs:documentation source="version">5.0.0+</xs:documentation>
<xs:documentation source="description">
The <code>&lt;projectgenerator&gt;</code> element isidentifies the rootbuild oftool
theresponsible project
for dependencycreating trees.
this <document</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:attribute name="modelVersion" type="xs:string"/>
<xs:attribute name="groupId" type="coordinate"/>
<xs:attribute name="artifactId" type="coordinate"/> </xs:annotation>
<xs:complexType>
<xs:attribute name="versionname" type="coordinatexs:string"/>
<xs:attribute name="platformIdversion" type="coordinate" use="optional"/>
<xs:all>
<xs:element ref="information" minOccurs="0" maxOccurs="1xs:string"/>
<xs:elementattribute refname="licenseurl" minOccurstype="0" maxOccurs="unbounded"/>
<xs:element ref="artifacts" minOccurs="1" maxOccurs="unboundedxs:string"/>
</xs:all>
</xs:complexType>
</xs:element>
<xs:element name="information">
<xs:annotation>
<xs:documentation source="version">5.0.0+</xs:documentation>
<xs:documentation source="description">
The <code>&lt;information&gt;</code> element is a container for
descriptive information about either all the artifacts in a project or
a specific artifact.</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:all>
<xs:element name="name" type="xs:string" maxOccurs="1"/>
<xs:element name="description" type="xs:string" maxOccurs="1"/>
<!-- TODO add additional elements -->
</xs:all>
</xs:complexType>
</xs:element>

 

<xs:element name="license" xmlns:spdx="http://spdx.org/rdf/terms#">
<xs:annotation>
<xs:documentation source="version">5.0.0+</xs:documentation>
<xs:documentation source="description">
The <code>&lt;license&gt;</code> element defines one of the licenses
under which the artifacts are made available. Where a license is
attached to the <code>&lt;project&gt;</code> element this defines the
default licenses for all artifacts in the project. Where a license is
attached to an <code>&lt;artifact&gt;</code> element this signifies
that the specific artifact is covered by the
<code>&lt;license&gt;</code> elements defined within that
<code>&lt;artifact&gt;</code> element. Licenses are identified using
the <a href="http://spdx.org">SPDX</a> identifiers</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:attribute name="spdx" type="xs:string"/>
</xs:complexType>
</xs:element>

...