Add a new Java configuration option to recursively search parent poms… (#2274)

- Add a new Java configuration option to recursively search parent poms for licenses
---------
Signed-off-by: Colm O hEigeartaigh <coheigea@apache.org>
Signed-off-by: Christopher Phillips <christopher.phillips@anchore.com>
Co-authored-by: Christopher Phillips <christopher.phillips@anchore.com>
This commit is contained in:
Colm O hEigeartaigh 2023-11-03 14:33:02 +00:00 committed by GitHub
parent 793cef5086
commit 2d582f78a1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 612 additions and 30 deletions

View File

@ -603,13 +603,15 @@ golang:
no-proxy: ""
java:
# when running across pom.xml files that could have more information, syft will
# explicitly search maven for license information by querying the online pom when this is true eg:
# https://repo1.maven.org/maven2/org/springframework/boot/spring-boot-starter-test/3.1.5/spring-boot-starter-test-3.1.5.pom
# this option is helpful for when the parent pom has this information,
# but it is not accessible from within the final built artifact
search-maven-for-licenses: false
maven-url: "https://repo1.maven.org/maven2"
max-parent-recursive-depth: 5
# enables Syft to use the network to fill in more detailed information about artifacts
# currently this enables searching maven-url for license data
# when running across pom.xml files that could have more information, syft will
# explicitly search maven for license information by querying the online pom when this is true
# this option is helpful for when the parent pom has more data,
# that is not accessible from within the final built artifact
use-network: false
linux-kernel:
# whether to catalog linux kernel modules found within lib/modules/** directories

View File

@ -140,8 +140,9 @@ func (cfg Catalog) ToCatalogerConfig() cataloger.Config {
CatalogModules: cfg.LinuxKernel.CatalogModules,
},
Java: javaCataloger.DefaultCatalogerOpts().
WithSearchMavenForLicenses(cfg.Java.SearchMavenForLicenses).
WithMavenCentralURL(cfg.Java.MavenURL),
WithUseNetwork(cfg.Java.UseNetwork).
WithMavenCentralURL(cfg.Java.MavenURL).
WithMaxParentRecursiveDepth(cfg.Java.MaxParentRecursiveDepth),
Python: pythonCataloger.CatalogerConfig{
GuessUnpinnedRequirements: cfg.Python.GuessUnpinnedRequirements,
},

View File

@ -1,6 +1,7 @@
package options
type java struct {
SearchMavenForLicenses bool `yaml:"search-maven-for-licenses" json:"search-maven-for-licenses" mapstructure:"search-maven-for-licenses"`
MavenURL string `yaml:"maven-url" json:"maven-url" mapstructure:"maven-url"`
UseNetwork bool `yaml:"use-network" json:"use-network" mapstructure:"use-network"`
MavenURL string `yaml:"maven-url" json:"maven-url" mapstructure:"maven-url"`
MaxParentRecursiveDepth int `yaml:"max-parent-recursive-depth" json:"max-parent-recursive-depth" mapstructure:"max-parent-recursive-depth"`
}

View File

@ -37,6 +37,7 @@ func (c Config) JavaConfig() java.Config {
return java.Config{
SearchUnindexedArchives: c.Search.IncludeUnindexedArchives,
SearchIndexedArchives: c.Search.IncludeIndexedArchives,
SearchMavenForLicenses: c.Java.SearchMavenForLicenses,
UseNetwork: c.Java.UseNetwork,
MaxParentRecursiveDepth: c.Java.MaxParentRecursiveDepth,
}
}

View File

@ -286,8 +286,8 @@ func (j *archiveParser) guessMainPackageNameAndVersionFromPomInfo() (name, versi
if version == "" && pomProjectObject != nil {
version = pomProjectObject.Version
}
if pomProjectObject != nil && j.cfg.SearchMavenForLicenses {
findPomLicenses(pomProjectObject)
if pomProjectObject != nil && j.cfg.UseNetwork {
findPomLicenses(pomProjectObject, j.cfg)
}
if pomProjectObject != nil {
@ -304,17 +304,20 @@ func artifactIDMatchesFilename(artifactID, fileName string) bool {
return strings.HasPrefix(artifactID, fileName) || strings.HasSuffix(fileName, artifactID)
}
func findPomLicenses(pomProjectObject *parsedPomProject) {
func findPomLicenses(pomProjectObject *parsedPomProject, cfg Config) {
// If we don't have any licenses until now, and if we have a parent Pom, then we'll check the parent pom in maven central for licenses.
if pomProjectObject != nil && pomProjectObject.Parent != nil && len(pomProjectObject.Licenses) == 0 {
parentPom, err := getPomFromMavenCentral(pomProjectObject.Parent.GroupID, pomProjectObject.Parent.ArtifactID, pomProjectObject.Parent.Version)
parentLicenses, err := recursivelyFindLicensesFromParentPom(
pomProjectObject.Parent.GroupID,
pomProjectObject.Parent.ArtifactID,
pomProjectObject.Parent.Version,
cfg)
if err != nil {
// We don't want to abort here as the parent pom might not exist in Maven Central, we'll just log the error
log.Tracef("unable to get parent pom from Maven central: %v", err)
return
}
parentLicenses := parseLicensesFromPom(parentPom)
if len(parentLicenses) > 0 || parentPom == nil || parentPom.Parent == nil {
if len(parentLicenses) > 0 {
for _, licenseName := range parentLicenses {
pomProjectObject.Licenses = append(pomProjectObject.Licenses, pkg.NewLicenseFromFields(licenseName, "", nil))
}
@ -322,22 +325,44 @@ func findPomLicenses(pomProjectObject *parsedPomProject) {
}
}
func formatMavenPomURL(groupID, artifactID, version string) (requestURL string, err error) {
func formatMavenPomURL(groupID, artifactID, version, mavenBaseURL string) (requestURL string, err error) {
// groupID needs to go from maven.org -> maven/org
urlPath := strings.Split(groupID, ".")
artifactPom := fmt.Sprintf("%s-%s.pom", artifactID, version)
urlPath = append(urlPath, artifactID, version, artifactPom)
// ex:"https://repo1.maven.org/maven2/groupID/artifactID/artifactPom
requestURL, err = url.JoinPath(MavenBaseURL, urlPath...)
requestURL, err = url.JoinPath(mavenBaseURL, urlPath...)
if err != nil {
return requestURL, fmt.Errorf("could not construct maven url: %w", err)
}
return requestURL, err
}
func getPomFromMavenCentral(groupID, artifactID, version string) (*gopom.Project, error) {
requestURL, err := formatMavenPomURL(groupID, artifactID, version)
func recursivelyFindLicensesFromParentPom(groupID, artifactID, version string, cfg Config) ([]string, error) {
var licenses []string
// As there can be nested parent poms, we'll recursively check for licenses until we reach the max depth
for i := 0; i < cfg.MaxParentRecursiveDepth; i++ {
parentPom, err := getPomFromMavenCentral(groupID, artifactID, version, cfg.MavenBaseURL)
if err != nil {
return nil, err
}
parentLicenses := parseLicensesFromPom(parentPom)
if len(parentLicenses) > 0 || parentPom == nil || parentPom.Parent == nil {
licenses = parentLicenses
break
}
groupID = *parentPom.Parent.GroupID
artifactID = *parentPom.Parent.ArtifactID
version = *parentPom.Parent.Version
}
return licenses, nil
}
func getPomFromMavenCentral(groupID, artifactID, version, mavenBaseURL string) (*gopom.Project, error) {
requestURL, err := formatMavenPomURL(groupID, artifactID, version, mavenBaseURL)
if err != nil {
return nil, err
}

View File

@ -4,6 +4,8 @@ import (
"bufio"
"fmt"
"io"
"net/http"
"net/http/httptest"
"os"
"os/exec"
"path/filepath"
@ -44,6 +46,102 @@ func generateJavaBuildFixture(t *testing.T, fixturePath string) {
run(t, cmd)
}
func generateMockMavenHandler(responseFixture string) func(w http.ResponseWriter, r *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
// Set the Content-Type header to indicate that the response is XML
w.Header().Set("Content-Type", "application/xml")
// Copy the file's content to the response writer
file, err := os.Open(responseFixture)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
defer file.Close()
_, err = io.Copy(w, file)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}
}
type handlerPath struct {
path string
handler func(w http.ResponseWriter, r *http.Request)
}
func TestSearchMavenForLicenses(t *testing.T) {
mux, url, teardown := setup()
defer teardown()
tests := []struct {
name string
fixture string
detectNested bool
config Config
requestPath string
requestHandlers []handlerPath
expectedLicenses []pkg.License
}{
{
name: "searchMavenForLicenses returns the expected licenses when search is set to true",
fixture: "opensaml-core-3.4.6",
detectNested: false,
config: Config{
UseNetwork: true,
MavenBaseURL: url,
MaxParentRecursiveDepth: 2,
},
requestHandlers: []handlerPath{
{
path: "/org/opensaml/opensaml-parent/3.4.6/opensaml-parent-3.4.6.pom",
handler: generateMockMavenHandler("test-fixtures/maven-xml-responses/opensaml-parent-3.4.6.pom"),
},
{
path: "/net/shibboleth/parent/7.11.2/parent-7.11.2.pom",
handler: generateMockMavenHandler("test-fixtures/maven-xml-responses/parent-7.11.2.pom"),
},
},
expectedLicenses: []pkg.License{
{
Type: license.Declared,
Value: `The Apache Software License, Version 2.0`,
SPDXExpression: ``,
},
},
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
// configure maven central requests
for _, hdlr := range tc.requestHandlers {
mux.HandleFunc(hdlr.path, hdlr.handler)
}
// setup metadata fixture; note:
// this fixture has a pomProjectObject and has a parent object
// it has no licenses on either which is the condition for testing
// the searchMavenForLicenses functionality
jarName := generateJavaMetadataJarFixture(t, tc.fixture)
fixture, err := os.Open(jarName)
require.NoError(t, err)
// setup parser
ap, cleanupFn, err := newJavaArchiveParser(
file.LocationReadCloser{
Location: file.NewLocation(fixture.Name()),
ReadCloser: fixture,
}, tc.detectNested, tc.config)
defer cleanupFn()
// assert licenses are discovered from upstream
_, _, licenses := ap.guessMainPackageNameAndVersionFromPomInfo()
assert.Equal(t, tc.expectedLicenses, licenses)
})
}
}
func TestFormatMavenURL(t *testing.T) {
tests := []struct {
name string
@ -63,7 +161,7 @@ func TestFormatMavenURL(t *testing.T) {
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
requestURL, err := formatMavenPomURL(tc.groupID, tc.artifactID, tc.version)
requestURL, err := formatMavenPomURL(tc.groupID, tc.artifactID, tc.version, MavenBaseURL)
assert.NoError(t, err, "expected no err; got %w", err)
assert.Equal(t, tc.expected, requestURL)
})
@ -303,7 +401,7 @@ func TestParseJar(t *testing.T) {
parser, cleanupFn, err := newJavaArchiveParser(file.LocationReadCloser{
Location: file.NewLocation(fixture.Name()),
ReadCloser: fixture,
}, false, Config{SearchMavenForLicenses: false})
}, false, Config{UseNetwork: false})
defer cleanupFn()
require.NoError(t, err)
@ -1303,3 +1401,21 @@ func run(t testing.TB, cmd *exec.Cmd) {
}
}
}
// setup sets up a test HTTP server for mocking requests to maven central.
// The returned url is injected into the Config so the client uses the test server.
// Tests should register handlers on mux to simulate the expected request/response structure
func setup() (mux *http.ServeMux, serverURL string, teardown func()) {
// mux is the HTTP request multiplexer used with the test server.
mux = http.NewServeMux()
// We want to ensure that tests catch mistakes where the endpoint URL is
// specified as absolute rather than relative. It only makes a difference
// when there's a non-empty base URL path. So, use that. See issue #752.
apiHandler := http.NewServeMux()
apiHandler.Handle("/", mux)
// server is a test HTTP server used to provide mock API responses.
server := httptest.NewServer(apiHandler)
return mux, server.URL, server.Close
}

View File

@ -3,6 +3,7 @@ package java
type Config struct {
SearchUnindexedArchives bool
SearchIndexedArchives bool
SearchMavenForLicenses bool
UseNetwork bool
MavenBaseURL string
MaxParentRecursiveDepth int
}

View File

@ -3,12 +3,13 @@ package java
const MavenBaseURL = "https://repo1.maven.org/maven2"
type CatalogerOpts struct {
SearchMavenForLicenses bool
MavenURL string
UseNetwork bool
MavenURL string
MaxParentRecursiveDepth int
}
func (j CatalogerOpts) WithSearchMavenForLicenses(input bool) CatalogerOpts {
j.SearchMavenForLicenses = input
func (j CatalogerOpts) WithUseNetwork(input bool) CatalogerOpts {
j.UseNetwork = input
return j
}
@ -19,9 +20,17 @@ func (j CatalogerOpts) WithMavenCentralURL(input string) CatalogerOpts {
return j
}
func (j CatalogerOpts) WithMaxParentRecursiveDepth(input int) CatalogerOpts {
if input > 0 {
j.MaxParentRecursiveDepth = input
}
return j
}
func DefaultCatalogerOpts() CatalogerOpts {
return CatalogerOpts{
SearchMavenForLicenses: false,
MavenURL: MavenBaseURL,
UseNetwork: false,
MavenURL: MavenBaseURL,
MaxParentRecursiveDepth: 5,
}
}

View File

@ -3,6 +3,7 @@ CACHE_PATH = $(shell pwd)/cache
JACKSON_CORE = jackson-core-2.15.2
SBT_JACKSON_CORE = com.fasterxml.jackson.core.jackson-core-2.15.2
OPENSAML_CORE = opensaml-core-3.4.6
API_ALL_SOURCES = api-all-2.0.0-sources
$(CACHE_DIR):
@ -14,5 +15,8 @@ $(CACHE_DIR)/$(JACKSON_CORE).jar: $(CACHE_DIR)
$(CACHE_DIR)/$(SBT_JACKSON_CORE).jar: $(CACHE_DIR)
cd $(SBT_JACKSON_CORE) && zip -r $(CACHE_PATH)/$(SBT_JACKSON_CORE).jar .
$(CACHE_DIR)/$(OPENSAML_CORE).jar: $(CACHE_DIR)
cd $(OPENSAML_CORE) && zip -r $(CACHE_PATH)/$(OPENSAML_CORE).jar .
$(CACHE_DIR)/$(API_ALL_SOURCES).jar: $(CACHE_DIR)
cd $(API_ALL_SOURCES) && zip -r $(CACHE_PATH)/$(API_ALL_SOURCES).jar .

View File

@ -0,0 +1,27 @@
JarIndex-Version: 1.0
opensaml-core-3.4.6.jar
META-INF
META-INF/maven
META-INF/maven/org.opensaml
META-INF/maven/org.opensaml/opensaml-core
META-INF/services
org
org/opensaml
org/opensaml/core
org/opensaml/core/config
org/opensaml/core/config/provider
org/opensaml/core/criterion
org/opensaml/core/metrics
org/opensaml/core/metrics/impl
org/opensaml/core/xml
org/opensaml/core/xml/config
org/opensaml/core/xml/io
org/opensaml/core/xml/persist
org/opensaml/core/xml/schema
org/opensaml/core/xml/schema/impl
org/opensaml/core/xml/util
schema
default-config.xml
schema-config.xml

View File

@ -0,0 +1,12 @@
Manifest-Version: 1.0
Automatic-Module-Name: org.opensaml.core
Built-By: putmanb
Build-Jdk: 1.7.0_80
Created-By: Apache Maven 3.6.3
Main-Class: org.opensaml.core.Version
Name: org/opensaml/core/
Implementation-Vendor: opensaml.org
Implementation-Title: opensaml-core
Implementation-Version: 3.4.6

View File

@ -0,0 +1,4 @@
#Created by Apache Maven 3.6.3
version=3.4.6
groupId=org.opensaml
artifactId=opensaml-core

View File

@ -0,0 +1,75 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.opensaml</groupId>
<artifactId>opensaml-parent</artifactId>
<version>3.4.6</version>
<relativePath>../opensaml-parent</relativePath>
</parent>
<name>OpenSAML :: Core</name>
<description>Core</description>
<artifactId>opensaml-core</artifactId>
<packaging>jar</packaging>
<properties>
<automatic.module.name>org.opensaml.core</automatic.module.name>
</properties>
<dependencies>
<!-- Compile Dependencies -->
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
</dependency>
<dependency>
<groupId>io.dropwizard.metrics</groupId>
<artifactId>metrics-core</artifactId>
</dependency>
<!-- Provided Dependencies -->
<!-- Runtime Dependencies -->
<!-- Test Dependencies -->
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<index>true</index>
<manifestEntries>
<Main-Class>org.opensaml.core.Version</Main-Class>
</manifestEntries>
<manifestSections>
<manifestSection>
<name>org/opensaml/core/</name>
<manifestEntries>
<Implementation-Title>${project.artifactId}</Implementation-Title>
<Implementation-Version>${project.version}</Implementation-Version>
<Implementation-Vendor>opensaml.org</Implementation-Vendor>
</manifestEntries>
</manifestSection>
</manifestSections>
</archive>
</configuration>
</plugin>
</plugins>
</build>
<distributionManagement>
<site>
<id>site</id>
<url>dav:${opensaml-module.site.url}</url>
</site>
</distributionManagement>
</project>

View File

@ -0,0 +1,186 @@
<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>net.shibboleth</groupId>
<artifactId>parent</artifactId>
<version>7.11.2</version>
</parent>
<name>OpenSAML</name>
<description>
A library for creating, reading, writing and performing some processing of SAML messages.
For further information see https://wiki.shibboleth.net/confluence/display/OS30/Home
</description>
<groupId>org.opensaml</groupId>
<artifactId>opensaml-parent</artifactId>
<version>3.4.6</version>
<packaging>pom</packaging>
<modules>
<module>../opensaml-core</module>
<module>../opensaml-storage-api</module>
<module>../opensaml-security-api</module>
<module>../opensaml-xmlsec-api</module>
<module>../opensaml-messaging-api</module>
<module>../opensaml-soap-api</module>
<module>../opensaml-saml-api</module>
<module>../opensaml-xacml-api</module>
<module>../opensaml-xacml-saml-api</module>
<module>../opensaml-storage-impl</module>
<module>../opensaml-security-impl</module>
<module>../opensaml-xmlsec-impl</module>
<module>../opensaml-messaging-impl</module>
<module>../opensaml-soap-impl</module>
<module>../opensaml-saml-impl</module>
<module>../opensaml-xacml-impl</module>
<module>../opensaml-xacml-saml-impl</module>
<module>../opensaml-profile-api</module>
<module>../opensaml-profile-impl</module>
<module>../opensaml-bom</module>
<module>../opensaml-tests-bom</module>
</modules>
<properties>
<java-support.version>7.5.2</java-support.version>
<spring-extensions.version>5.4.2</spring-extensions.version>
<checkstyle.configLocation>${project.basedir}/../opensaml-parent/resources/checkstyle/checkstyle.xml</checkstyle.configLocation>
<opensaml-parent.site.url>${shibboleth.site.url}java-opensaml/${project.version}/</opensaml-parent.site.url>
<opensaml-module.site.url>${opensaml-parent.site.url}${project.artifactId}</opensaml-module.site.url>
</properties>
<!-- Dependencies which are required by every single project module should go here and will be inherited by all modules. -->
<dependencies>
<!-- Compile Dependencies -->
<dependency>
<groupId>net.shibboleth.utilities</groupId>
<artifactId>java-support</artifactId>
<version>${java-support.version}</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</dependency>
<!-- Provided Dependencies -->
<!-- Runtime Dependencies -->
<!-- Test Dependencies -->
<dependency>
<groupId>net.shibboleth.utilities</groupId>
<artifactId>java-support</artifactId>
<version>${java-support.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.xmlunit</groupId>
<artifactId>xmlunit-legacy</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<!-- Dependencies which are not required by every project module but for which every module should use the same version
of the dependency should go here. That is to say, placing a dependency here allows one to "peg" the version of the artifact
used by all project modules. -->
<dependencyManagement>
<dependencies>
<!-- Compile Dependencies -->
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>4.3.5.Final</version>
<exclusions>
<exclusion>
<groupId>xml-apis</groupId>
<artifactId>xml-apis</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.1-api</artifactId>
<version>1.0.0.Final</version>
</dependency>
<dependency>
<groupId>net.spy</groupId>
<artifactId>spymemcached</artifactId>
<version>2.12.3</version>
</dependency>
<!-- Provided Dependencies -->
<!-- Runtime Dependencies -->
<!-- Test Dependencies -->
<dependency>
<groupId>net.shibboleth.ext</groupId>
<artifactId>spring-extensions</artifactId>
<version>${spring-extensions.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</dependencyManagement>
<scm>
<connection>${shibboleth.scm.connection}java-opensaml</connection>
<developerConnection>${shibboleth.scm.developerConnection}java-opensaml</developerConnection>
<url>${shibboleth.scm.url}java-opensaml.git</url>
</scm>
<distributionManagement>
<site>
<id>site</id>
<url>dav:${opensaml-parent.site.url}</url>
</site>
</distributionManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-site-plugin</artifactId>
<executions>
<execution>
<id>attach-descriptor</id>
<goals>
<goal>attach-descriptor</goal>
</goals>
</execution>
</executions>
<configuration>
<siteDirectory>../opensaml-parent/src/site</siteDirectory>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifestEntries>
<Automatic-Module-Name>${automatic.module.name}</Automatic-Module-Name>
</manifestEntries>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,118 @@
<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>net.shibboleth</groupId>
<artifactId>parent</artifactId>
<version>7.11.2</version>
<packaging>pom</packaging>
<name>Shibboleth Project V3 Super POM</name>
<description>
A POM containing properties, profiles, plugin configurations, etc. that are common across all Shibboleth V3 projects.
</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
<bouncycastle.version>1.59</bouncycastle.version>
<cryptacular.version>1.1.4</cryptacular.version>
<!-- IMPORTANT: httpclient and httpcore versions need to be updated together. -->
<httpclient.groupId>org.apache.httpcomponents</httpclient.groupId>
<httpclient.version>4.5.13</httpclient.version>
<httpclient.httpcore.version>4.4.14</httpclient.httpcore.version>
<guava.version>20.0</guava.version>
<jetty.groupId>org.eclipse.jetty</jetty.groupId>
<jetty.version>9.2.14.v20151106</jetty.version>
<ldaptive.version>1.0.13</ldaptive.version>
<logback.version>1.2.3</logback.version>
<metrics.version>3.1.5</metrics.version>
<jackson.version>2.10.4</jackson.version>
<slf4j.groupId>org.slf4j</slf4j.groupId>
<slf4j.version>1.7.30</slf4j.version>
<spring.groupId>org.springframework</spring.groupId>
<spring.version>4.3.30.RELEASE</spring.version>
<spring-webflow.groupId>org.springframework.webflow</spring-webflow.groupId>
<spring-webflow.version>2.4.8.RELEASE</spring-webflow.version>
<xmlsec.version>2.0.10</xmlsec.version>
<xmlunit.version>2.5.1</xmlunit.version>
<checkstyle.version>8.26</checkstyle.version>
<checkstyle-plugin.version>3.1.0</checkstyle-plugin.version>
<checkstyle.configLocation>checkstyle.xml</checkstyle.configLocation>
<maven-javadoc-plugin.version>3.0.0</maven-javadoc-plugin.version>
<maven.central.url>https://repo1.maven.org/maven2</maven.central.url>
<shibboleth.site.url>https://build.shibboleth.net/nexus/content/sites/site/</shibboleth.site.url>
<shibboleth.scm.connection>scm:git:https://git.shibboleth.net/git/</shibboleth.scm.connection>
<shibboleth.scm.developerConnection>scm:git:git@git.shibboleth.net:</shibboleth.scm.developerConnection>
<shibboleth.scm.url>https://git.shibboleth.net/view/?p=</shibboleth.scm.url>
</properties>
<!-- The Maven version prerequisite applies to the maven-versions-plugin:display-plugin-updates goal only. -->
<prerequisites>
<maven>3.3.1</maven>
</prerequisites>
<!-- Dependencies set for all projects. Be certain anything added here really should apply to every single project. -->
<dependencies>
</dependencies>
<!-- Dependencies with fixed versions and excludes that may be used by projects. -->
<dependencyManagement>
</dependencyManagement>
<distributionManagement>
</distributionManagement>
<build>
</build>
<reporting>
</reporting>
<profiles>
</profiles>
<!-- Project Metadata -->
<url>http://shibboleth.net/</url>
<inceptionYear>1999</inceptionYear>
<licenses>
<license>
<name>The Apache Software License, Version 2.0</name>
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
<distribution>repo</distribution>
</license>
</licenses>
<mailingLists>
</mailingLists>
<issueManagement>
</issueManagement>
<scm>
<connection>${shibboleth.scm.connection}java-parent-project-v3</connection>
<developerConnection>${shibboleth.scm.developerConnection}java-parent-project-v3</developerConnection>
<url>${shibboleth.scm.url}java-parent-project-v3.git</url>
</scm>
<developers>
</developers>
<contributors>
</contributors>
<organization>
</organization>
</project>