From 64295fc97e8dccc5b3b2e739bef518edd17976cb Mon Sep 17 00:00:00 2001 From: Alexey Loubyansky Date: Thu, 22 Feb 2024 13:56:54 +0100 Subject: [PATCH] Integrate the licenses-generator as a module of Bacon --- .../pnc/bacon/common/ObjectHelperTest.java | 6 +- licenses-generator/README.md | 39 +++ licenses-generator/pom.xml | 239 +++++++++++++ .../jboss/pnc/bacon/licenses/GavFinder.java | 33 ++ .../bacon/licenses/LicenseSummaryFactory.java | 60 ++++ .../bacon/licenses/LicensesFileManager.java | 211 ++++++++++++ .../pnc/bacon/licenses/LicensesGenerator.java | 143 ++++++++ .../LicensesGeneratorApplication.java | 78 +++++ .../licenses/LicensesGeneratorException.java | 27 ++ .../licenses/maven/MavenEmbedderFactory.java | 45 +++ .../licenses/maven/MavenProjectFactory.java | 103 ++++++ .../maven/MavenProjectFactoryException.java | 27 ++ .../maven/ProjectBuildingRequestFactory.java | 70 ++++ .../licenses/maven/SnowdropMavenEmbedder.java | 40 +++ .../properties/GeneratorProperties.java | 94 +++++ .../GeneratorPropertiesException.java | 31 ++ .../licenses/properties/PropertyKeys.java | 34 ++ .../sanitiser/AliasLicenseSanitiser.java | 68 ++++ .../sanitiser/ExceptionLicenseSanitiser.java | 49 +++ .../licenses/sanitiser/LicenseSanitiser.java | 28 ++ .../sanitiser/LicenseServiceSanitiser.java | 47 +++ .../licenses/sanitiser/MavenSanitiser.java | 71 ++++ .../sanitiser/NoopLicenseSanitiser.java | 31 ++ .../licenses/sanitiser/RedHatLicense.java | 148 ++++++++ .../exceptions/ExactVersionMatcher.java | 32 ++ .../exceptions/LicenseException.java | 68 ++++ .../exceptions/RangeVersionMatcher.java | 48 +++ .../exceptions/RegexpVersionMatcher.java | 36 ++ .../sanitiser/exceptions/VersionMatcher.java | 21 ++ .../provider/ExternalLicenseDto.java | 60 ++++ .../provider/ExternalLicenseProvider.java | 94 +++++ .../provider/ExternalLicensesDto.java | 36 ++ .../jboss/pnc/bacon/licenses/utils/Gav.java | 77 +++++ .../pnc/bacon/licenses/utils/JsonUtils.java | 59 ++++ .../bacon/licenses/xml/DependencyElement.java | 186 ++++++++++ .../bacon/licenses/xml/LicenseElement.java | 131 +++++++ .../bacon/licenses/xml/LicenseSummary.java | 71 ++++ .../src/main/resources/generator.properties | 0 .../src/main/resources/licenses.qute | 57 ++++ .../main/resources/rh-license-exceptions.json | 106 ++++++ .../src/main/resources/rh-license-names.json | 323 ++++++++++++++++++ .../main/resources/simplelogger.properties | 2 + .../bacon/licenses/ExternalLicensesTest.java | 125 +++++++ .../bacon/licenses/LicenseServiceMock.java | 86 +++++ .../licenses/LicenseSummaryFactoryTest.java | 94 +++++ .../maven/MavenProjectFactoryTest.java | 159 +++++++++ .../properties/GeneratorPropertiesTest.java | 71 ++++ .../sanitiser/AliasLicenseSanitiserTest.java | 188 ++++++++++ .../ExceptionLicenseSanitiserTest.java | 127 +++++++ .../sanitiser/NoopLicenseSanitiserTest.java | 30 ++ .../licenses/sanitiser/RedHatLicenseTest.java | 85 +++++ .../exceptions/ExactVersionMatcherTest.java | 29 ++ .../exceptions/RangeVersionMatcherTest.java | 63 ++++ .../exceptions/RegexpVersionMatcherTest.java | 31 ++ .../licenses/xml/LicenseSummaryTest.java | 59 ++++ .../test/resources/rh-license-exceptions.json | 72 ++++ .../src/test/resources/rh-license-names.json | 33 ++ .../resources/test-pom-with-exceptions.xml | 23 ++ .../src/test/resources/test-pom.xml | 17 + .../test_properties/empty.properties | 0 .../test_properties/modified.properties | 3 + .../wrong-repositories.properties | 1 + pig/pom.xml | 2 +- .../pig/impl/license/LicenseGenerator.java | 8 +- pom.xml | 135 +++++++- 65 files changed, 4555 insertions(+), 15 deletions(-) create mode 100644 licenses-generator/README.md create mode 100644 licenses-generator/pom.xml create mode 100644 licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/GavFinder.java create mode 100644 licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/LicenseSummaryFactory.java create mode 100644 licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/LicensesFileManager.java create mode 100644 licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/LicensesGenerator.java create mode 100644 licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/LicensesGeneratorApplication.java create mode 100644 licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/LicensesGeneratorException.java create mode 100644 licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/maven/MavenEmbedderFactory.java create mode 100644 licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/maven/MavenProjectFactory.java create mode 100644 licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/maven/MavenProjectFactoryException.java create mode 100644 licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/maven/ProjectBuildingRequestFactory.java create mode 100644 licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/maven/SnowdropMavenEmbedder.java create mode 100644 licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/properties/GeneratorProperties.java create mode 100644 licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/properties/GeneratorPropertiesException.java create mode 100644 licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/properties/PropertyKeys.java create mode 100644 licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/sanitiser/AliasLicenseSanitiser.java create mode 100644 licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/sanitiser/ExceptionLicenseSanitiser.java create mode 100644 licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/sanitiser/LicenseSanitiser.java create mode 100644 licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/sanitiser/LicenseServiceSanitiser.java create mode 100644 licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/sanitiser/MavenSanitiser.java create mode 100644 licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/sanitiser/NoopLicenseSanitiser.java create mode 100644 licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/sanitiser/RedHatLicense.java create mode 100644 licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/sanitiser/exceptions/ExactVersionMatcher.java create mode 100644 licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/sanitiser/exceptions/LicenseException.java create mode 100644 licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/sanitiser/exceptions/RangeVersionMatcher.java create mode 100644 licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/sanitiser/exceptions/RegexpVersionMatcher.java create mode 100644 licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/sanitiser/exceptions/VersionMatcher.java create mode 100644 licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/sanitiser/provider/ExternalLicenseDto.java create mode 100644 licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/sanitiser/provider/ExternalLicenseProvider.java create mode 100644 licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/sanitiser/provider/ExternalLicensesDto.java create mode 100644 licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/utils/Gav.java create mode 100644 licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/utils/JsonUtils.java create mode 100644 licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/xml/DependencyElement.java create mode 100644 licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/xml/LicenseElement.java create mode 100644 licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/xml/LicenseSummary.java create mode 100644 licenses-generator/src/main/resources/generator.properties create mode 100644 licenses-generator/src/main/resources/licenses.qute create mode 100644 licenses-generator/src/main/resources/rh-license-exceptions.json create mode 100644 licenses-generator/src/main/resources/rh-license-names.json create mode 100644 licenses-generator/src/main/resources/simplelogger.properties create mode 100644 licenses-generator/src/test/java/org/jboss/pnc/bacon/licenses/ExternalLicensesTest.java create mode 100644 licenses-generator/src/test/java/org/jboss/pnc/bacon/licenses/LicenseServiceMock.java create mode 100644 licenses-generator/src/test/java/org/jboss/pnc/bacon/licenses/LicenseSummaryFactoryTest.java create mode 100644 licenses-generator/src/test/java/org/jboss/pnc/bacon/licenses/maven/MavenProjectFactoryTest.java create mode 100644 licenses-generator/src/test/java/org/jboss/pnc/bacon/licenses/properties/GeneratorPropertiesTest.java create mode 100644 licenses-generator/src/test/java/org/jboss/pnc/bacon/licenses/sanitiser/AliasLicenseSanitiserTest.java create mode 100644 licenses-generator/src/test/java/org/jboss/pnc/bacon/licenses/sanitiser/ExceptionLicenseSanitiserTest.java create mode 100644 licenses-generator/src/test/java/org/jboss/pnc/bacon/licenses/sanitiser/NoopLicenseSanitiserTest.java create mode 100644 licenses-generator/src/test/java/org/jboss/pnc/bacon/licenses/sanitiser/RedHatLicenseTest.java create mode 100644 licenses-generator/src/test/java/org/jboss/pnc/bacon/licenses/sanitiser/exceptions/ExactVersionMatcherTest.java create mode 100644 licenses-generator/src/test/java/org/jboss/pnc/bacon/licenses/sanitiser/exceptions/RangeVersionMatcherTest.java create mode 100644 licenses-generator/src/test/java/org/jboss/pnc/bacon/licenses/sanitiser/exceptions/RegexpVersionMatcherTest.java create mode 100644 licenses-generator/src/test/java/org/jboss/pnc/bacon/licenses/xml/LicenseSummaryTest.java create mode 100644 licenses-generator/src/test/resources/rh-license-exceptions.json create mode 100644 licenses-generator/src/test/resources/rh-license-names.json create mode 100644 licenses-generator/src/test/resources/test-pom-with-exceptions.xml create mode 100644 licenses-generator/src/test/resources/test-pom.xml create mode 100644 licenses-generator/src/test/resources/test_properties/empty.properties create mode 100644 licenses-generator/src/test/resources/test_properties/modified.properties create mode 100644 licenses-generator/src/test/resources/test_properties/wrong-repositories.properties diff --git a/common/src/test/java/org/jboss/pnc/bacon/common/ObjectHelperTest.java b/common/src/test/java/org/jboss/pnc/bacon/common/ObjectHelperTest.java index 84fcaadd0..73a0f3711 100644 --- a/common/src/test/java/org/jboss/pnc/bacon/common/ObjectHelperTest.java +++ b/common/src/test/java/org/jboss/pnc/bacon/common/ObjectHelperTest.java @@ -1,9 +1,9 @@ package org.jboss.pnc.bacon.common; import ch.qos.logback.classic.Level; -import com.google.common.collect.Maps; import org.junit.jupiter.api.Test; +import java.util.HashMap; import java.util.Map; import static com.github.stefanbirkner.systemlambda.SystemLambda.tapSystemOut; @@ -14,7 +14,7 @@ class ObjectHelperTest { @Test void printJson() throws Exception { String actual = tapSystemOut(() -> { - Map testSubject = Maps.newHashMap(); + Map testSubject = new HashMap<>(); testSubject.put("test", "subject"); @@ -29,7 +29,7 @@ void printJson() throws Exception { @Test void printYaml() throws Exception { String actual = tapSystemOut(() -> { - Map testSubject = Maps.newHashMap(); + Map testSubject = new HashMap<>(); testSubject.put("test", "subject"); diff --git a/licenses-generator/README.md b/licenses-generator/README.md new file mode 100644 index 000000000..7a4153681 --- /dev/null +++ b/licenses-generator/README.md @@ -0,0 +1,39 @@ +# Overview + +This project generates `licenses.xml` and `licenses.html` files based on a `pom.xml`. It loads all transitive dependnencies from `dependencies` section of the project's `pom.xml` and collects all their licenses. Then it aligns the license names and URLs to comply with the approved Red Hat license names and URLs. Finally, when generating `licenses.html`, it also downloads license contents for offline use. + +# Standalone usage +This project can be pakaged as an uber-jar and used standalone. To create an uber-jar run the following command: +``` +mvn clean package +``` + +Then generate `licenses.(xml|html)`: +``` +java -jar target/licenses-generator-shaded.jar -Dpom={path to pom.xml} -Ddestination={destination directory} [-DgeneratorProperties={path to a properties file}] [-DaliasesFile={path to aliases file}] [-DexceptionsFile={path to exceptions file}] +``` + +# Usage in an application +You can add this project as a dependency and generate license files by using its API directly. Add the following dependency to your project's `pom.xml`: +``` + + me.snowdrop + licenses-generator + ${project.version} + +``` + +Create an instance of `LicensesGenerator` and use `generateLicensesForPom` or `generateLicensesForGavs`. The latter method is only exposed to use directly and will not resolve transitive dependencies. + +# Configuration +Project can be configured with a `src/main/resources/generator.properties` file. However, it can be oveerriden when running in standalone mode by providing `-DgeneratorProperties={path to a properties file}` as an application argument. When using generator via API, you can provide `GeneratorProperties` when creating an instance of `LicensesGenerator`. + +These are the available properties (you can also see them in `PropertyKeys`): + +Name|Description|Default value +---|---|--- +repository.names | Comma separated list of repository names. Must be the same length as repository.urls | Maven Central +repository.urls | Comma separated list of repository URLs. Must be the same length as repository.names | http://repo1.maven.org/maven2 +licenseServiceUrl | An optional URL of a license service.
If not provided, the license data will be collected from the the rh-license-exceptions.json file or artifacts' pom.xml | *null* +aliasesFile | An absolute path to the license aliases file (can be overwritten by -DaliasesFile) | rh-license-names.json from this project +exceptionsFile | An absolute path to the license exceptions file (can be overwritten by -DexceptionsFile) | rh-license-exceptions.json from this project diff --git a/licenses-generator/pom.xml b/licenses-generator/pom.xml new file mode 100644 index 000000000..70e742483 --- /dev/null +++ b/licenses-generator/pom.xml @@ -0,0 +1,239 @@ + + + + 4.0.0 + + + org.jboss.pnc.bacon + parent + 2.5.6-SNAPSHOT + + licenses-generator + + Licenses Generator to gather dependency licenses and generate licenses.xml|html files + + + + + io.quarkus.qute + qute-core + + + + + org.glassfish + javax.json + + + + + org.jenkins-ci.lib + lib-jenkins-maven-embedder + + + org.apache.maven + maven-artifact + + + org.apache.maven + maven-compat + + + org.apache.maven + maven-core + + + org.checkerframework + checker-qual + + + org.slf4j + slf4j-api + + + + + org.apache.maven + maven-embedder + + + org.slf4j + slf4j-api + + + + org.codehaus.plexus + plexus-utils + + + org.checkerframework + checker-qual + + + + + org.apache.maven.resolver + maven-resolver-connector-basic + + + org.slf4j + slf4j-api + + + + + org.apache.maven.resolver + maven-resolver-transport-wagon + + + org.slf4j + slf4j-api + + + + + org.apache.maven.resolver + maven-resolver-api + + + org.apache.maven.resolver + maven-resolver-spi + + + org.apache.maven.resolver + maven-resolver-impl + + + org.apache.maven.resolver + maven-resolver-util + + + org.apache.maven.wagon + wagon-file + + + org.apache.maven.wagon + wagon-http + + + + + org.glassfish.jaxb + jaxb-runtime + + + + + org.jboss.resteasy + resteasy-client + + + org.jboss.resteasy + resteasy-jackson2-provider + + + + + org.apache.commons + commons-configuration2 + + + commons-beanutils + commons-beanutils + + + + + commons-io + commons-io + + + + + org.slf4j + slf4j-api + + + + + org.junit.jupiter + junit-jupiter-api + test + + + org.junit.jupiter + junit-jupiter-engine + test + + + org.assertj + assertj-core + test + + + org.mockito + mockito-inline + test + + + io.undertow + undertow-servlet + test + + + + + + jenkins-ci-releases + https://repo.jenkins-ci.org/releases/ + + + + + + + org.apache.maven.plugins + maven-shade-plugin + 3.0.0 + + + licenses-generator + + shade + + package + + licenses-generator-shaded + + + org.jboss.pnc.bacon.licenses.LicensesGeneratorApplication + + + + + META-INF/sisu/javax.inject.Named + + + false + + + + + + + + diff --git a/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/GavFinder.java b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/GavFinder.java new file mode 100644 index 000000000..800a8f51f --- /dev/null +++ b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/GavFinder.java @@ -0,0 +1,33 @@ +package org.jboss.pnc.bacon.licenses; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.project.MavenProject; +import org.jboss.pnc.bacon.licenses.maven.MavenProjectFactory; +import org.jboss.pnc.bacon.licenses.utils.Gav; + +import java.nio.file.Path; +import java.util.Collection; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class GavFinder { + private final MavenProjectFactory mavenProjectFactory; + + GavFinder(MavenProjectFactory mavenProjectFactory) { + this.mavenProjectFactory = mavenProjectFactory; + } + + public Collection inMavenProject(Path pomPath) { + return getArtifactsForMavenProject(pomPath) + .map(a -> new Gav(a.getGroupId(), a.getArtifactId(), a.getVersion(), a.getType())) + .collect(Collectors.toSet()); + } + + Stream getArtifactsForMavenProject(Path pomPath) { + return mavenProjectFactory.getMavenProjects(pomPath.toFile(), true) + .stream() + .map(MavenProject::getArtifacts) + .flatMap(Set::stream); + } +} diff --git a/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/LicenseSummaryFactory.java b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/LicenseSummaryFactory.java new file mode 100644 index 000000000..a1211419e --- /dev/null +++ b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/LicenseSummaryFactory.java @@ -0,0 +1,60 @@ +/* + * Copyright 2016-2017 Red Hat, Inc, and individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jboss.pnc.bacon.licenses; + +import org.apache.maven.artifact.Artifact; +import org.jboss.pnc.bacon.licenses.sanitiser.LicenseSanitiser; +import org.jboss.pnc.bacon.licenses.xml.DependencyElement; +import org.jboss.pnc.bacon.licenses.xml.LicenseSummary; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Collection; +import java.util.Comparator; +import java.util.List; +import java.util.stream.Collectors; + +/** + * Class responsible for retrieving licenses information based on a provided GAV. + * + * @author Gytis Trikleris + */ +public class LicenseSummaryFactory { + + private final Logger logger = LoggerFactory.getLogger(LicenseSummaryFactory.class); + + private final LicenseSanitiser licenseSanitiser; + + public LicenseSummaryFactory(LicenseSanitiser licenseSanitiser) { + this.licenseSanitiser = licenseSanitiser; + } + + public LicenseSummary getLicenseSummary(Collection artifacts) { + logger.debug("Getting license summary for a collection of " + artifacts.size() + " artifacts"); + List dependencyElements = artifacts.parallelStream() + .map(DependencyElement::new) + .map(licenseSanitiser::fix) + .sorted( + Comparator.comparing(DependencyElement::getGroupId) + .thenComparing(DependencyElement::getArtifactId) + .thenComparing(DependencyElement::getVersion)) + .collect(Collectors.toList()); + + return new LicenseSummary(dependencyElements); + } + +} diff --git a/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/LicensesFileManager.java b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/LicensesFileManager.java new file mode 100644 index 000000000..e1eb3154f --- /dev/null +++ b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/LicensesFileManager.java @@ -0,0 +1,211 @@ +/* + * Copyright 2016-2017 Red Hat, Inc, and individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jboss.pnc.bacon.licenses; + +import io.quarkus.qute.Qute; +import org.apache.commons.io.FileUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; +import org.jboss.pnc.bacon.licenses.xml.DependencyElement; +import org.jboss.pnc.bacon.licenses.xml.LicenseElement; +import org.jboss.pnc.bacon.licenses.xml.LicenseSummary; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.xml.bind.JAXBException; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileOutputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.UncheckedIOException; +import java.nio.charset.StandardCharsets; +import java.util.AbstractMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; + +/** + * Class responsible for persisting licenses information to XML and HTML files. + * + * @author Gytis Trikleris + */ +public class LicensesFileManager { + + private static final int DOWNLOAD_TIMEOUT = 60_000; + + private static final String CONTENTS_DIR = "contents"; + private static final String LICENSES_QUTE = "licenses.qute"; + + private final Logger logger = LoggerFactory.getLogger(LicensesFileManager.class); + + private final CloseableHttpClient httpClient = HttpClientBuilder.create() + .setDefaultRequestConfig( + RequestConfig.custom() + .setConnectTimeout(DOWNLOAD_TIMEOUT) + .setSocketTimeout(DOWNLOAD_TIMEOUT) + .build()) + .build(); + + /** + * Create a licenses.xml file. + * + * @param licenseSummary license summary XML element, which should be written to a licenses.xml file. + * @param directoryPath directory where new file should be stored. + * @throws LicensesGeneratorException on generation failure + */ + public void createLicensesXml(LicenseSummary licenseSummary, String directoryPath) + throws LicensesGeneratorException { + logger.debug("Generating licenses.xml at {}", directoryPath); + File file = new File(directoryPath, "licenses.xml"); + try { + FileUtils.writeStringToFile(file, licenseSummary.toXmlString(), StandardCharsets.UTF_8); + } catch (JAXBException | IOException e) { + throw new LicensesGeneratorException("Failed to create licenses.xml", e); + } + } + + /** + * Create a licenses.html file and download copy of each license for offline use. + * + * @param licenseSummary license summary XML element, which should be written to a licenses.xml file. + * @param directoryPath directory where new file should be stored. + * @throws LicensesGeneratorException on generation failure + */ + public void createLicensesHtml(LicenseSummary licenseSummary, String directoryPath) + throws LicensesGeneratorException { + logger.debug("Generating licenses.html at {}", directoryPath); + Map licenseFiles = downloadLicenseFiles(licenseSummary.getDependencies(), directoryPath); + + File file = new File(directoryPath, "licenses.html"); + + try (FileWriter fileOutputStream = new FileWriter(file)) { + fileOutputStream.write( + Qute.fmt(loadTemplate()) + .data("dependencies", licenseSummary.getDependencies()) + .data("licenseFiles", licenseFiles) + .render()); + } catch (IOException e) { + throw new LicensesGeneratorException("Failed to create licenses.html", e); + } + } + + private static String loadTemplate() { + final InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(LICENSES_QUTE); + if (is == null) { + throw new IllegalStateException("Failed to locate " + LICENSES_QUTE + " on the classpath"); + } + try (BufferedReader reader = new BufferedReader(new InputStreamReader(is))) { + StringBuilder sb = new StringBuilder(); + String line = reader.readLine(); + while (line != null) { + sb.append(line).append(System.lineSeparator()); + line = reader.readLine(); + } + return sb.toString(); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + private Map downloadLicenseFiles(List dependencies, String directoryPath) { + final File licenseContentsDirectory = new File(directoryPath, CONTENTS_DIR); + licenseContentsDirectory.mkdirs(); + return dependencies.stream() + .flatMap( + dependency -> dependency.getLicenses() + .stream() + .map(license -> downloadLicenseFile(dependency, license, licenseContentsDirectory))) + .filter(Optional::isPresent) + .map(Optional::get) + .distinct() + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + } + + private Optional> downloadLicenseFile( + DependencyElement dependency, + LicenseElement license, + File licenseContentsDirectory) { + String textUrl = license.getTextUrl(); + if (StringUtils.isBlank(textUrl)) { + return Optional.empty(); + } + logger.debug("Downloading license file for {} from {}", dependency.toGavString(), textUrl); + try { + String fileName = getLocalLicenseFileName(license); + File file = new File(licenseContentsDirectory, fileName); + boolean download = false; + if (!file.exists()) { + synchronized (this) { + if (!file.exists()) { + file.createNewFile(); + download = true; + } + } + } + if (download) { + try { + downloadTo(textUrl, file); + } catch (IOException e) { + if (!textUrl.startsWith("https")) { + downloadTo(textUrl.replace("http", "https"), file); + } else { + throw e; + } + } + } + return Optional.of( + new AbstractMap.SimpleEntry<>(license.getName(), String.format("%s/%s", CONTENTS_DIR, fileName))); + } catch (Exception e) { + logger.warn( + "Failed to download license '{}' for '{}' from '{}'", + license.getName(), + dependency.toGavString(), + textUrl, + e); + return Optional.empty(); + } + } + + // TODO: optimize! + private void downloadTo(String url, File file) throws IOException { + HttpGet request = new HttpGet(url); + HttpResponse response = httpClient.execute(request); + HttpEntity entity = response.getEntity(); + if (entity != null) { + try (OutputStream stream = new FileOutputStream(file)) { + entity.writeTo(stream); + } + } + } + + private String getLocalLicenseFileName(LicenseElement licenseElement) { + String fileName = licenseElement.getName().replaceAll("[^A-Za-z0-9 ]", ""); + return fileName.replace(" ", "+"); + } + +} diff --git a/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/LicensesGenerator.java b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/LicensesGenerator.java new file mode 100644 index 000000000..71dff7351 --- /dev/null +++ b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/LicensesGenerator.java @@ -0,0 +1,143 @@ +/* + * Copyright 2016-2017 Red Hat, Inc, and individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jboss.pnc.bacon.licenses; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.artifact.factory.ArtifactFactory; +import org.apache.maven.project.ProjectBuilder; +import org.codehaus.plexus.PlexusContainer; +import org.codehaus.plexus.component.repository.exception.ComponentLookupException; +import org.jboss.pnc.bacon.licenses.maven.MavenEmbedderFactory; +import org.jboss.pnc.bacon.licenses.maven.MavenProjectFactory; +import org.jboss.pnc.bacon.licenses.maven.ProjectBuildingRequestFactory; +import org.jboss.pnc.bacon.licenses.maven.SnowdropMavenEmbedder; +import org.jboss.pnc.bacon.licenses.properties.GeneratorProperties; +import org.jboss.pnc.bacon.licenses.sanitiser.AliasLicenseSanitiser; +import org.jboss.pnc.bacon.licenses.sanitiser.ExceptionLicenseSanitiser; +import org.jboss.pnc.bacon.licenses.sanitiser.LicenseSanitiser; +import org.jboss.pnc.bacon.licenses.sanitiser.LicenseServiceSanitiser; +import org.jboss.pnc.bacon.licenses.sanitiser.MavenSanitiser; +import org.jboss.pnc.bacon.licenses.sanitiser.NoopLicenseSanitiser; +import org.jboss.pnc.bacon.licenses.utils.Gav; +import org.jboss.pnc.bacon.licenses.xml.LicenseSummary; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.nio.file.Paths; +import java.util.Collection; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * @author Gytis Trikleris + */ +public class LicensesGenerator { + + private final Logger logger = LoggerFactory.getLogger(LicensesGenerator.class); + + private final ArtifactFactory artifactFactory; + + private final MavenProjectFactory mavenProjectFactory; + + private final LicenseSummaryFactory licenseSummaryFactory; + + private final LicensesFileManager licensesFileManager; + + private final String aliasesFilePath; + + private final String exceptionsFilePath; + + private final Optional licenseServiceUrl; + + private final GavFinder gavFinder; + + public LicensesGenerator() throws LicensesGeneratorException { + this(new GeneratorProperties()); + } + + public LicensesGenerator(GeneratorProperties generatorProperties) throws LicensesGeneratorException { + MavenEmbedderFactory mavenEmbedderFactory = new MavenEmbedderFactory(); + SnowdropMavenEmbedder mavenEmbedder = mavenEmbedderFactory.getSnowdropMavenEmbedder(); + ProjectBuildingRequestFactory projectBuildingRequestFactory = new ProjectBuildingRequestFactory( + generatorProperties, + mavenEmbedder); + PlexusContainer container = mavenEmbedder.getPlexusContainer(); + try { + ProjectBuilder projectBuilder = container.lookup(ProjectBuilder.class); + this.mavenProjectFactory = new MavenProjectFactory(projectBuilder, projectBuildingRequestFactory); + this.artifactFactory = container.lookup(ArtifactFactory.class); + } catch (ComponentLookupException e) { + throw new LicensesGeneratorException(e.getMessage(), e); + } + + this.licenseServiceUrl = generatorProperties.getLicenseServiceUrl(); + this.aliasesFilePath = generatorProperties.getAliasesFilePath(); + this.exceptionsFilePath = generatorProperties.getExceptionsFilePath(); + this.licenseSummaryFactory = createLicenseSummaryFactory(); + this.licensesFileManager = new LicensesFileManager(); + this.gavFinder = new GavFinder(mavenProjectFactory); + } + + public GavFinder findGavs() { + return gavFinder; + } + + public void generateLicensesForPom(String pomPath, String resultPath) throws LicensesGeneratorException { + logger.debug("Generating licenses for {}", pomPath); + Collection artifacts = gavFinder.getArtifactsForMavenProject(Paths.get(pomPath)) + .collect(Collectors.toSet()); + generateLicensesForArtifacts(artifacts, resultPath); + } + + public void generateLicensesForGavs(Collection gavs, String resultPath) throws LicensesGeneratorException { + logger.debug("Generating licenses for a collection of {} gavs", gavs.size()); + Set artifacts = gavs.parallelStream().map(this::gavToArtifact).collect(Collectors.toSet()); + generateLicensesForArtifacts(artifacts, resultPath); + } + + private void generateLicensesForArtifacts(Collection artifacts, String resultPath) + throws LicensesGeneratorException { + logger.debug("Generating licenses for artifacts"); + LicenseSummary licenseSummary = licenseSummaryFactory.getLicenseSummary(artifacts); + licensesFileManager.createLicensesXml(licenseSummary, resultPath); + licensesFileManager.createLicensesHtml(licenseSummary, resultPath); + } + + protected Artifact gavToArtifact(Gav gav) { + logger.debug("Getting artifact for " + gav); + return artifactFactory + .createArtifact(gav.getGroupId(), gav.getArtifactId(), gav.getVersion(), null, gav.getType()); + } + + protected LicenseSummaryFactory createLicenseSummaryFactory() { + logger.debug("Initialising license sanitisers"); + LicenseSanitiser noopLicenseSanitiser = new NoopLicenseSanitiser(); + LicenseSanitiser aliasLicenseSanitiser = new AliasLicenseSanitiser(aliasesFilePath, noopLicenseSanitiser); + LicenseSanitiser mavenSanitiser = new MavenSanitiser(mavenProjectFactory, aliasLicenseSanitiser); + + Optional maybeExternalLicenseSanitiser = licenseServiceUrl + .map(url -> new LicenseServiceSanitiser(url, mavenSanitiser)); + + LicenseSanitiser secondSanitiser = maybeExternalLicenseSanitiser.orElse(mavenSanitiser); + + LicenseSanitiser exceptionLicenseSanitiser = new ExceptionLicenseSanitiser(exceptionsFilePath, secondSanitiser); + + logger.debug("Initialising license summary factory"); + return new LicenseSummaryFactory(exceptionLicenseSanitiser); + } +} diff --git a/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/LicensesGeneratorApplication.java b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/LicensesGeneratorApplication.java new file mode 100644 index 000000000..1d93f20ce --- /dev/null +++ b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/LicensesGeneratorApplication.java @@ -0,0 +1,78 @@ +/* + * Copyright 2016-2017 Red Hat, Inc, and individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jboss.pnc.bacon.licenses; + +import org.jboss.pnc.bacon.licenses.properties.GeneratorProperties; +import org.jboss.pnc.bacon.licenses.properties.PropertyKeys; + +import java.util.Arrays; +import java.util.Objects; +import java.util.Properties; + +/** + * @author Gytis Trikleris + */ +public class LicensesGeneratorApplication { + + public static void main(String... args) throws Exception { + Properties properties = argsToProperties(args); + GeneratorProperties generatorProperties = getGeneratorProperties(properties); + LicensesGenerator licensesGenerator = new LicensesGenerator(generatorProperties); + + String pomPath = properties.getProperty("pom"); + String resultPath = properties.getProperty("destination"); + + licensesGenerator.generateLicensesForPom(pomPath, resultPath); + } + + private static GeneratorProperties getGeneratorProperties(Properties properties) { + GeneratorProperties generatorProperties; + + if (properties.containsKey("generatorProperties")) { + generatorProperties = new GeneratorProperties(properties.getProperty("generatorProperties")); + } else { + generatorProperties = new GeneratorProperties(); + } + + // Override properties if explicitly provided + if (properties.containsKey(PropertyKeys.ALIASES_FILE)) { + generatorProperties.setAliasesFilePath(properties.getProperty(PropertyKeys.ALIASES_FILE)); + } + + if (properties.containsKey(PropertyKeys.EXCEPTIONS_FILE)) { + generatorProperties.setExceptionsFilePath(properties.getProperty(PropertyKeys.EXCEPTIONS_FILE)); + } + + return generatorProperties; + } + + private static Properties argsToProperties(String... args) { + Properties properties = new Properties(); + Arrays.stream(args) + .map(s -> s.replace("-D", "")) + .filter(s -> s.contains("=")) + .map(s -> s.split("=")) + .filter(a -> a.length == 2) + .forEach(a -> properties.put(a[0], a[1])); + + Objects.requireNonNull(properties.getProperty("pom"), "'pom' is required"); + Objects.requireNonNull(properties.getProperty("destination"), "'destination' is required"); + + return properties; + } + +} diff --git a/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/LicensesGeneratorException.java b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/LicensesGeneratorException.java new file mode 100644 index 000000000..87b70c7f1 --- /dev/null +++ b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/LicensesGeneratorException.java @@ -0,0 +1,27 @@ +/* + * Copyright 2016-2017 Red Hat, Inc, and individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jboss.pnc.bacon.licenses; + +/** + * @author Gytis Trikleris + */ +public class LicensesGeneratorException extends Exception { + + public LicensesGeneratorException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/maven/MavenEmbedderFactory.java b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/maven/MavenEmbedderFactory.java new file mode 100644 index 000000000..3975557b4 --- /dev/null +++ b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/maven/MavenEmbedderFactory.java @@ -0,0 +1,45 @@ +/* + * Copyright 2016-2017 Red Hat, Inc, and individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jboss.pnc.bacon.licenses.maven; + +import hudson.maven.MavenEmbedderException; +import hudson.maven.MavenRequest; +import org.apache.maven.model.building.ModelBuildingRequest; + +/** + * @author Gytis Trikleris + */ +public class MavenEmbedderFactory { + + public SnowdropMavenEmbedder getSnowdropMavenEmbedder() { + try { + return new SnowdropMavenEmbedder(getMavenRequest()); + } catch (MavenEmbedderException e) { + throw new RuntimeException("Failed to create Maven embedder", e); + } + } + + private MavenRequest getMavenRequest() { + MavenRequest mavenRequest = new MavenRequest(); + mavenRequest.setSystemProperties(System.getProperties()); + mavenRequest.setProcessPlugins(false); + mavenRequest.setValidationLevel(ModelBuildingRequest.VALIDATION_LEVEL_MINIMAL); + + return mavenRequest; + } + +} diff --git a/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/maven/MavenProjectFactory.java b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/maven/MavenProjectFactory.java new file mode 100644 index 000000000..89b233362 --- /dev/null +++ b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/maven/MavenProjectFactory.java @@ -0,0 +1,103 @@ +/* + * Copyright 2016-2017 Red Hat, Inc, and individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jboss.pnc.bacon.licenses.maven; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.project.MavenProject; +import org.apache.maven.project.ProjectBuilder; +import org.apache.maven.project.ProjectBuildingException; +import org.apache.maven.project.ProjectBuildingRequest; +import org.apache.maven.project.ProjectBuildingResult; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +/** + * @author Gytis Trikleris + */ +public class MavenProjectFactory { + + private final Logger logger = LoggerFactory.getLogger(MavenProjectFactory.class); + + private final ProjectBuilder projectBuilder; + + private final ProjectBuildingRequestFactory projectBuildingRequestFactory; + + public MavenProjectFactory( + ProjectBuilder projectBuilder, + ProjectBuildingRequestFactory projectBuildingRequestFactory) { + this.projectBuilder = projectBuilder; + this.projectBuildingRequestFactory = projectBuildingRequestFactory; + } + + public Optional getMavenProject(Artifact artifact, boolean resolveDependencies) { + ProjectBuildingRequest request = projectBuildingRequestFactory.getProjectBuildingRequest(); + request.setResolveDependencies(resolveDependencies); + + try { + ProjectBuildingResult result = projectBuilder.build(artifact, request); + return Optional.ofNullable(result.getProject()); + } catch (ProjectBuildingException e) { + logger.warn("Failed to get maven project for " + artifact, e); + return Optional.empty(); + } + } + + public List getMavenProjects(File pom, boolean resolveDependencies) { + ProjectBuildingRequest request = projectBuildingRequestFactory.getProjectBuildingRequest(); + request.setResolveDependencies(resolveDependencies); + + List interimMavenProjects; + + try { + interimMavenProjects = projectBuilder.build(Collections.singletonList(pom), true, request) + .parallelStream() + .map(ProjectBuildingResult::getProject) + .collect(Collectors.toList()); + } catch (ProjectBuildingException e) { + logger.warn("Failed to get maven project for " + pom.getName(), e); + return Collections.emptyList(); + } + + if (resolveDependencies) { + // This is needed as the build above doesn't resolve dependencies + return interimMavenProjects.parallelStream() + .map(p -> resolveMavenProject(p, request)) + .filter(Optional::isPresent) + .map(Optional::get) + .collect(Collectors.toList()); + } + + return interimMavenProjects; + } + + private Optional resolveMavenProject(MavenProject mavenProject, ProjectBuildingRequest request) { + try { + ProjectBuildingResult result = projectBuilder.build(mavenProject.getFile(), request); + return Optional.ofNullable(result.getProject()); + } catch (ProjectBuildingException e) { + logger.warn("Failed to resolve maven project", e); + return Optional.empty(); + } + } + +} diff --git a/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/maven/MavenProjectFactoryException.java b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/maven/MavenProjectFactoryException.java new file mode 100644 index 000000000..e0409f2a3 --- /dev/null +++ b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/maven/MavenProjectFactoryException.java @@ -0,0 +1,27 @@ +/* + * Copyright 2016-2017 Red Hat, Inc, and individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jboss.pnc.bacon.licenses.maven; + +/** + * @author Gytis Trikleris + */ +public class MavenProjectFactoryException extends Exception { + + public MavenProjectFactoryException(Throwable cause) { + super(cause); + } +} diff --git a/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/maven/ProjectBuildingRequestFactory.java b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/maven/ProjectBuildingRequestFactory.java new file mode 100644 index 000000000..012adc0b6 --- /dev/null +++ b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/maven/ProjectBuildingRequestFactory.java @@ -0,0 +1,70 @@ +/* + * Copyright 2016-2017 Red Hat, Inc, and individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jboss.pnc.bacon.licenses.maven; + +import org.apache.maven.artifact.repository.ArtifactRepository; +import org.apache.maven.model.building.ModelBuildingRequest; +import org.apache.maven.project.DefaultProjectBuildingRequest; +import org.apache.maven.project.ProjectBuildingRequest; +import org.codehaus.plexus.component.repository.exception.ComponentLookupException; +import org.jboss.pnc.bacon.licenses.properties.GeneratorProperties; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author Gytis Trikleris + */ +public class ProjectBuildingRequestFactory { + + private final GeneratorProperties properties; + + private final SnowdropMavenEmbedder maven; + + public ProjectBuildingRequestFactory(GeneratorProperties properties, SnowdropMavenEmbedder maven) { + this.properties = properties; + this.maven = maven; + } + + public ProjectBuildingRequest getProjectBuildingRequest() { + try { + DefaultProjectBuildingRequest request = new DefaultProjectBuildingRequest(); + request.setLocalRepository(maven.getLocalRepository()); + request.setRemoteRepositories(getRepositories()); + request.setResolveDependencies(true); + request.setRepositorySession(maven.buildRepositorySystemSession()); + request.setSystemProperties(System.getProperties()); + request.setProcessPlugins(false); + request.setValidationLevel(ModelBuildingRequest.VALIDATION_LEVEL_MINIMAL); + + return request; + } catch (Exception e) { + throw new RuntimeException("Failed to create project building request", e); + } + } + + private List getRepositories() { + return properties.getRepositories().entrySet().stream().map(entry -> { + try { + return maven.createRepository(entry.getValue(), entry.getKey()); + } catch (ComponentLookupException e) { + throw new RuntimeException("Failed to initialise repository", e); + } + }).collect(Collectors.toList()); + } + +} diff --git a/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/maven/SnowdropMavenEmbedder.java b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/maven/SnowdropMavenEmbedder.java new file mode 100644 index 000000000..765752f19 --- /dev/null +++ b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/maven/SnowdropMavenEmbedder.java @@ -0,0 +1,40 @@ +/* + * Copyright 2016-2017 Red Hat, Inc, and individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jboss.pnc.bacon.licenses.maven; + +import hudson.maven.MavenEmbedder; +import hudson.maven.MavenEmbedderException; +import hudson.maven.MavenRequest; +import org.apache.maven.DefaultMaven; +import org.apache.maven.Maven; +import org.eclipse.aether.RepositorySystemSession; + +/** + * @author Gytis Trikleris + */ +public class SnowdropMavenEmbedder extends MavenEmbedder { + + public SnowdropMavenEmbedder(MavenRequest mavenRequest) throws MavenEmbedderException { + super(Thread.currentThread().getContextClassLoader(), mavenRequest); + } + + public RepositorySystemSession buildRepositorySystemSession() throws Exception { + DefaultMaven defaultMaven = (DefaultMaven) super.getPlexusContainer().lookup(Maven.class); + return defaultMaven.newRepositorySession(super.buildMavenExecutionRequest(super.getMavenRequest())); + } + +} diff --git a/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/properties/GeneratorProperties.java b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/properties/GeneratorProperties.java new file mode 100644 index 000000000..6fb2214a5 --- /dev/null +++ b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/properties/GeneratorProperties.java @@ -0,0 +1,94 @@ +/* + * Copyright 2016-2017 Red Hat, Inc, and individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jboss.pnc.bacon.licenses.properties; + +import org.apache.commons.configuration2.Configuration; +import org.apache.commons.configuration2.builder.fluent.Configurations; +import org.apache.commons.configuration2.ex.ConfigurationException; + +import java.util.AbstractMap; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +/** + * @author Gytis Trikleris + */ +public class GeneratorProperties { + + private static final String DEFAULT_FILE_PATH = "generator.properties"; + + private static final String DEFAULT_REPOSITORY_NAME = "Maven Central"; + + private static final String DEFAULT_REPOSITORY_URL = "https://repo1.maven.org/maven2"; + + private static final String DEFAULT_ALIASES_FILE_PATH = "rh-license-names.json"; + + private static final String DEFAULT_EXCEPTIONS_FILE_PATH = "rh-license-exceptions.json"; + + private final Configuration configuration; + + public GeneratorProperties() { + this(DEFAULT_FILE_PATH); + } + + public GeneratorProperties(String filePath) { + try { + configuration = new Configurations().properties(filePath); + } catch (ConfigurationException e) { + throw new GeneratorPropertiesException("Couldn't load application properties", e); + } + } + + public Map getRepositories() { + String joinedNames = configuration.getString(PropertyKeys.REPOSITORY_NAMES, DEFAULT_REPOSITORY_NAME); + String joinedUrls = configuration.getString(PropertyKeys.REPOSITORY_URLS, DEFAULT_REPOSITORY_URL); + String[] names = joinedNames.split(","); + String[] urls = joinedUrls.split(","); + + if (names.length != urls.length) { + throw new GeneratorPropertiesException("Same number of repository names and urls is expected"); + } + + return IntStream.range(0, names.length) + .mapToObj(i -> new AbstractMap.SimpleEntry<>(names[i], urls[i])) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + } + + public Optional getLicenseServiceUrl() { + String url = configuration.getString(PropertyKeys.LICENSE_SERVICE_URL, null); + return Optional.ofNullable(url); + } + + public String getAliasesFilePath() { + return configuration.getString(PropertyKeys.ALIASES_FILE, DEFAULT_ALIASES_FILE_PATH); + } + + public void setAliasesFilePath(String aliasesFilePath) { + configuration.setProperty(PropertyKeys.ALIASES_FILE, aliasesFilePath); + } + + public String getExceptionsFilePath() { + return configuration.getString(PropertyKeys.EXCEPTIONS_FILE, DEFAULT_EXCEPTIONS_FILE_PATH); + } + + public void setExceptionsFilePath(String exceptionsFilePath) { + configuration.setProperty(PropertyKeys.EXCEPTIONS_FILE, exceptionsFilePath); + } + +} diff --git a/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/properties/GeneratorPropertiesException.java b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/properties/GeneratorPropertiesException.java new file mode 100644 index 000000000..332f30175 --- /dev/null +++ b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/properties/GeneratorPropertiesException.java @@ -0,0 +1,31 @@ +/* + * Copyright 2016-2017 Red Hat, Inc, and individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jboss.pnc.bacon.licenses.properties; + +/** + * @author Gytis Trikleris + */ +public class GeneratorPropertiesException extends RuntimeException { + + public GeneratorPropertiesException(String message) { + super(message); + } + + public GeneratorPropertiesException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/properties/PropertyKeys.java b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/properties/PropertyKeys.java new file mode 100644 index 000000000..8dcd71a4c --- /dev/null +++ b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/properties/PropertyKeys.java @@ -0,0 +1,34 @@ +/* + * Copyright 2016-2017 Red Hat, Inc, and individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jboss.pnc.bacon.licenses.properties; + +/** + * @author Gytis Trikleris + */ +public interface PropertyKeys { + + String REPOSITORY_NAMES = "repository.names"; + + String REPOSITORY_URLS = "repository.urls"; + + String LICENSE_SERVICE_URL = "licenseServiceUrl"; + + String ALIASES_FILE = "aliasesFile"; + + String EXCEPTIONS_FILE = "exceptionsFile"; + +} diff --git a/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/sanitiser/AliasLicenseSanitiser.java b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/sanitiser/AliasLicenseSanitiser.java new file mode 100644 index 000000000..6ab93e4ef --- /dev/null +++ b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/sanitiser/AliasLicenseSanitiser.java @@ -0,0 +1,68 @@ +/* + * Copyright 2016-2017 Red Hat, Inc, and individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jboss.pnc.bacon.licenses.sanitiser; + +import org.jboss.pnc.bacon.licenses.xml.DependencyElement; +import org.jboss.pnc.bacon.licenses.xml.LicenseElement; + +import java.util.Optional; +import java.util.Set; + +import static org.jboss.pnc.bacon.licenses.utils.JsonUtils.loadJsonToSet; + +/** + * @author Gytis Trikleris + */ +public class AliasLicenseSanitiser implements LicenseSanitiser { + + private final Set redHatLicenses; + + private final LicenseSanitiser next; + + public AliasLicenseSanitiser(String namesFilePath, LicenseSanitiser next) { + this.redHatLicenses = loadJsonToSet(namesFilePath, RedHatLicense::new); + this.next = next; + } + + @Override + public DependencyElement fix(DependencyElement originalDependencyElement) { + boolean shouldCallNext = false; + DependencyElement dependencyElement = new DependencyElement(originalDependencyElement); + + for (LicenseElement licenseElement : dependencyElement.getLicenses()) { + Optional redHatLicenseOptional = redHatLicenses.stream() + .filter(redHatLicense -> redHatLicense.isAliasTo(licenseElement)) + .findFirst(); + + if (redHatLicenseOptional.isPresent()) { + RedHatLicense redHatLicense = redHatLicenseOptional.get(); + licenseElement.setName(redHatLicense.getName()); + licenseElement.setUrl(redHatLicense.getUrl()); + licenseElement.setTextUrl(redHatLicense.getTextUrl()); + } else { + shouldCallNext = true; + } + } + + if (shouldCallNext) { + return next.fix(dependencyElement); + } + + return dependencyElement; + } + +} diff --git a/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/sanitiser/ExceptionLicenseSanitiser.java b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/sanitiser/ExceptionLicenseSanitiser.java new file mode 100644 index 000000000..cc9cbd440 --- /dev/null +++ b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/sanitiser/ExceptionLicenseSanitiser.java @@ -0,0 +1,49 @@ +/* + * Copyright 2016-2017 Red Hat, Inc, and individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jboss.pnc.bacon.licenses.sanitiser; + +import org.jboss.pnc.bacon.licenses.sanitiser.exceptions.LicenseException; +import org.jboss.pnc.bacon.licenses.utils.JsonUtils; +import org.jboss.pnc.bacon.licenses.xml.DependencyElement; + +import java.util.Set; + +/** + * @author Gytis Trikleris + */ +public class ExceptionLicenseSanitiser implements LicenseSanitiser { + + private final Set exceptions; + + private final LicenseSanitiser next; + + public ExceptionLicenseSanitiser(String exceptionsFilePath, LicenseSanitiser next) { + this.exceptions = JsonUtils.loadJsonToSet(exceptionsFilePath, LicenseException::new); + this.next = next; + } + + @Override + public DependencyElement fix(DependencyElement dependencyElement) { + return exceptions.stream() + .filter(exception -> exception.matches(dependencyElement)) + .findFirst() + .map(exception -> new DependencyElement(dependencyElement, exception.getLicenses())) + .orElseGet(() -> next.fix(dependencyElement)); + + } + +} diff --git a/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/sanitiser/LicenseSanitiser.java b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/sanitiser/LicenseSanitiser.java new file mode 100644 index 000000000..9dad2440b --- /dev/null +++ b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/sanitiser/LicenseSanitiser.java @@ -0,0 +1,28 @@ +/* + * Copyright 2016-2017 Red Hat, Inc, and individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jboss.pnc.bacon.licenses.sanitiser; + +import org.jboss.pnc.bacon.licenses.xml.DependencyElement; + +/** + * @author Gytis Trikleris + */ +public interface LicenseSanitiser { + + DependencyElement fix(DependencyElement dependencyElement); + +} diff --git a/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/sanitiser/LicenseServiceSanitiser.java b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/sanitiser/LicenseServiceSanitiser.java new file mode 100644 index 000000000..70cf41765 --- /dev/null +++ b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/sanitiser/LicenseServiceSanitiser.java @@ -0,0 +1,47 @@ +/* + * Copyright 2016-2017 Red Hat, Inc, and individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jboss.pnc.bacon.licenses.sanitiser; + +import org.jboss.pnc.bacon.licenses.sanitiser.provider.ExternalLicenseProvider; +import org.jboss.pnc.bacon.licenses.xml.DependencyElement; +import org.jboss.pnc.bacon.licenses.xml.LicenseElement; + +import java.util.Set; + +/** + * @author Michal Szynkiewicz, michal.l.szynkiewicz@gmail.com
+ * Date: 11/15/17 + */ +public class LicenseServiceSanitiser implements LicenseSanitiser { + + private final LicenseSanitiser next; + private final ExternalLicenseProvider provider; + + public LicenseServiceSanitiser(String licenseServiceUrl, LicenseSanitiser next) { + this.next = next; + this.provider = new ExternalLicenseProvider(licenseServiceUrl); + } + + @Override + public DependencyElement fix(DependencyElement dependencyElement) { + Set licenses = provider.getLicenses(dependencyElement.toGavString()); + if (!licenses.isEmpty()) { + return new DependencyElement(dependencyElement, licenses); + } else { + return next.fix(dependencyElement); + } + } +} diff --git a/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/sanitiser/MavenSanitiser.java b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/sanitiser/MavenSanitiser.java new file mode 100644 index 000000000..ca3aee3d2 --- /dev/null +++ b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/sanitiser/MavenSanitiser.java @@ -0,0 +1,71 @@ +/* + * Copyright 2016-2017 Red Hat, Inc, and individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jboss.pnc.bacon.licenses.sanitiser; + +import org.apache.maven.model.License; +import org.apache.maven.project.MavenProject; +import org.jboss.pnc.bacon.licenses.maven.MavenProjectFactory; +import org.jboss.pnc.bacon.licenses.xml.DependencyElement; +import org.jboss.pnc.bacon.licenses.xml.LicenseElement; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashSet; +import java.util.Optional; +import java.util.Set; + +/** + * A pass-through sanitiser. If the dependency element does not have a license, the sanitiser will try to get it from a + * maven project. Then, the dependency element will be given to the next sanitiser. + * + * @author Michal Szynkiewicz + * @author Gytis Trikleris + */ +public class MavenSanitiser implements LicenseSanitiser { + + private final Logger logger = LoggerFactory.getLogger(MavenSanitiser.class); + + private final MavenProjectFactory mavenProjectFactory; + + private final LicenseSanitiser next; + + public MavenSanitiser(MavenProjectFactory mavenProjectFactory, LicenseSanitiser next) { + this.mavenProjectFactory = mavenProjectFactory; + this.next = next; + } + + @Override + public DependencyElement fix(DependencyElement dependencyElement) { + if (dependencyElement.getLicenses().size() > 0) { + return next.fix(dependencyElement); + } + return next.fix(new DependencyElement(dependencyElement, getMavenProjectLicenses(dependencyElement))); + } + + private Set getMavenProjectLicenses(DependencyElement dependencyElement) { + Set licenses = new HashSet<>(); + Optional mavenProject = mavenProjectFactory + .getMavenProject(dependencyElement.getArtifact(), false); + if (mavenProject.isPresent()) { + for (License license : mavenProject.get().getLicenses()) { + licenses.add(new LicenseElement(license)); + } + } else { + logger.warn("Could not get maven project for {}", dependencyElement); + } + return licenses; + } +} diff --git a/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/sanitiser/NoopLicenseSanitiser.java b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/sanitiser/NoopLicenseSanitiser.java new file mode 100644 index 000000000..31ec24665 --- /dev/null +++ b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/sanitiser/NoopLicenseSanitiser.java @@ -0,0 +1,31 @@ +/* + * Copyright 2016-2017 Red Hat, Inc, and individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jboss.pnc.bacon.licenses.sanitiser; + +import org.jboss.pnc.bacon.licenses.xml.DependencyElement; + +/** + * @author Gytis Trikleris + */ +public class NoopLicenseSanitiser implements LicenseSanitiser { + + @Override + public DependencyElement fix(DependencyElement dependencyElement) { + return dependencyElement; + } + +} diff --git a/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/sanitiser/RedHatLicense.java b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/sanitiser/RedHatLicense.java new file mode 100644 index 000000000..a75392166 --- /dev/null +++ b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/sanitiser/RedHatLicense.java @@ -0,0 +1,148 @@ +/* + * Copyright 2016-2017 Red Hat, Inc, and individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jboss.pnc.bacon.licenses.sanitiser; + +import org.jboss.pnc.bacon.licenses.xml.LicenseElement; + +import javax.json.JsonObject; +import javax.json.JsonString; + +import java.util.HashSet; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * @author Gytis Trikleris + */ +public class RedHatLicense { + + private String name; + + private String url; + + private String textUrl; + + private Set aliases; + + private Set urlAliases; + + public RedHatLicense(JsonObject jsonObject) { + this.name = jsonObject.getString("name"); + this.url = jsonObject.getString("url"); + this.textUrl = jsonObject.getString("textUrl", this.url); + this.aliases = initAliases(jsonObject); + this.urlAliases = initUrlAliases(jsonObject); + } + + public String getName() { + return name; + } + + public String getUrl() { + return url; + } + + public Set getAliases() { + return aliases; + } + + public Set getUrlAliases() { + return urlAliases; + } + + public LicenseElement toLicenseElement() { + return new LicenseElement(name, url, textUrl); + } + + public String getTextUrl() { + return textUrl; + } + + public boolean isAliasTo(LicenseElement licenseElement) { + return isNameAlias(licenseElement) || isUrlAlias(licenseElement); + } + + private boolean isNameAlias(LicenseElement licenseElement) { + String name = sanitiseName(licenseElement.getName()); + + return name != null && aliases.contains(name); + } + + private boolean isUrlAlias(LicenseElement licenseElement) { + String url = sanitiseUrl(licenseElement.getUrl()); + + return url != null && urlAliases.contains(url); + } + + private String sanitiseName(String name) { + if (name == null) { + return null; + } + + return name.trim().toLowerCase(); + } + + private String sanitiseUrl(String url) { + if (url == null) { + return null; + } + + String resultUrl = url.trim().toLowerCase(); + + if (resultUrl.startsWith("http://")) { + resultUrl = resultUrl.substring(7); + } else if (resultUrl.startsWith("https://")) { + resultUrl = resultUrl.substring(8); + } + + if (resultUrl.startsWith("www.")) { + resultUrl = resultUrl.substring(4); + } + + if (resultUrl.endsWith("/")) { + resultUrl = resultUrl.substring(0, resultUrl.length() - 1); + } + + return resultUrl; + } + + private Set initAliases(JsonObject jsonObject) { + if (!jsonObject.containsKey("aliases")) { + return new HashSet<>(); + } + + return jsonObject.getJsonArray("aliases") + .getValuesAs(JsonString.class) + .stream() + .map(JsonString::getString) + .map(this::sanitiseName) + .collect(Collectors.toSet()); + } + + private Set initUrlAliases(JsonObject jsonObject) { + if (!jsonObject.containsKey("urlAliases")) { + return new HashSet<>(); + } + + return jsonObject.getJsonArray("urlAliases") + .getValuesAs(JsonString.class) + .stream() + .map(JsonString::getString) + .map(this::sanitiseUrl) + .collect(Collectors.toSet()); + } +} diff --git a/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/sanitiser/exceptions/ExactVersionMatcher.java b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/sanitiser/exceptions/ExactVersionMatcher.java new file mode 100644 index 000000000..1fb0c4af7 --- /dev/null +++ b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/sanitiser/exceptions/ExactVersionMatcher.java @@ -0,0 +1,32 @@ +/* + * Copyright 2016-2017 Red Hat, Inc, and individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jboss.pnc.bacon.licenses.sanitiser.exceptions; + +import java.util.Objects; + +class ExactVersionMatcher implements VersionMatcher { + private final String version; + + ExactVersionMatcher(String version) { + this.version = Objects.requireNonNull(version, "version must be set"); + } + + @Override + public boolean matches(String version) { + return this.version.equals(version); + } +} diff --git a/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/sanitiser/exceptions/LicenseException.java b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/sanitiser/exceptions/LicenseException.java new file mode 100644 index 000000000..fd78476db --- /dev/null +++ b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/sanitiser/exceptions/LicenseException.java @@ -0,0 +1,68 @@ +/* + * Copyright 2016-2017 Red Hat, Inc, and individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jboss.pnc.bacon.licenses.sanitiser.exceptions; + +import org.jboss.pnc.bacon.licenses.xml.DependencyElement; +import org.jboss.pnc.bacon.licenses.xml.LicenseElement; + +import javax.json.JsonObject; + +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; + +public class LicenseException { + private String groupId; + private String artifactId; + private VersionMatcher versionMatcher; + private Set licenses; + + public LicenseException(JsonObject jsonObject) { + this.groupId = jsonObject.getString("groupId"); + Objects.requireNonNull(this.groupId, "groupId cannot be null"); + + this.artifactId = jsonObject.getString("artifactId"); + Objects.requireNonNull(this.artifactId, "artifactId cannot be null"); + + if (jsonObject.containsKey("version")) { + this.versionMatcher = new ExactVersionMatcher(jsonObject.getString("version")); + } else if (jsonObject.containsKey("version-range")) { + this.versionMatcher = new RangeVersionMatcher(jsonObject.getString("version-range")); + } else if (jsonObject.containsKey("version-regexp")) { + this.versionMatcher = new RegexpVersionMatcher(jsonObject.getString("version-regexp")); + } else { + throw new IllegalArgumentException( + "License exception for " + groupId + ":" + artifactId + + " must contain 'version' or 'version-range' or 'version-regexp'"); + } + + this.licenses = jsonObject.getJsonArray("licenses") + .getValuesAs(JsonObject.class) + .stream() + .map(LicenseElement::new) + .collect(Collectors.toSet()); + } + + public boolean matches(DependencyElement dependency) { + return groupId.equals(dependency.getGroupId()) && artifactId.equals(dependency.getArtifactId()) + && versionMatcher.matches(dependency.getVersion()); + } + + public Set getLicenses() { + return licenses; + } +} diff --git a/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/sanitiser/exceptions/RangeVersionMatcher.java b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/sanitiser/exceptions/RangeVersionMatcher.java new file mode 100644 index 000000000..3d631b353 --- /dev/null +++ b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/sanitiser/exceptions/RangeVersionMatcher.java @@ -0,0 +1,48 @@ +/* + * Copyright 2016-2017 Red Hat, Inc, and individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jboss.pnc.bacon.licenses.sanitiser.exceptions; + +import org.eclipse.aether.util.version.GenericVersionScheme; +import org.eclipse.aether.version.InvalidVersionSpecificationException; +import org.eclipse.aether.version.VersionConstraint; +import org.eclipse.aether.version.VersionScheme; + +import java.util.Objects; + +class RangeVersionMatcher implements VersionMatcher { + private final VersionScheme scheme; + private final VersionConstraint constraint; + + RangeVersionMatcher(String spec) { + Objects.requireNonNull(spec, "version range spec must be set"); + scheme = new GenericVersionScheme(); + try { + constraint = scheme.parseVersionConstraint(spec); + } catch (InvalidVersionSpecificationException e) { + throw new IllegalArgumentException(e); + } + } + + @Override + public boolean matches(String version) { + try { + return constraint.containsVersion(scheme.parseVersion(version)); + } catch (InvalidVersionSpecificationException e) { + return false; + } + } +} diff --git a/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/sanitiser/exceptions/RegexpVersionMatcher.java b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/sanitiser/exceptions/RegexpVersionMatcher.java new file mode 100644 index 000000000..666c69bca --- /dev/null +++ b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/sanitiser/exceptions/RegexpVersionMatcher.java @@ -0,0 +1,36 @@ +/* + * Copyright 2016-2017 Red Hat, Inc, and individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jboss.pnc.bacon.licenses.sanitiser.exceptions; + +import java.util.Objects; +import java.util.regex.Pattern; + +class RegexpVersionMatcher implements VersionMatcher { + private final Pattern regexp; + + RegexpVersionMatcher(String regexp) { + this.regexp = Pattern.compile(Objects.requireNonNull(regexp, "version regexp must be set")); + } + + @Override + public boolean matches(String version) { + if (version == null) { + return false; + } + return this.regexp.matcher(version).matches(); + } +} diff --git a/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/sanitiser/exceptions/VersionMatcher.java b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/sanitiser/exceptions/VersionMatcher.java new file mode 100644 index 000000000..758c478ab --- /dev/null +++ b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/sanitiser/exceptions/VersionMatcher.java @@ -0,0 +1,21 @@ +/* + * Copyright 2016-2017 Red Hat, Inc, and individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jboss.pnc.bacon.licenses.sanitiser.exceptions; + +public interface VersionMatcher { + boolean matches(String version); +} diff --git a/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/sanitiser/provider/ExternalLicenseDto.java b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/sanitiser/provider/ExternalLicenseDto.java new file mode 100644 index 000000000..462fb1f2a --- /dev/null +++ b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/sanitiser/provider/ExternalLicenseDto.java @@ -0,0 +1,60 @@ +/* + * Copyright 2016-2017 Red Hat, Inc, and individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jboss.pnc.bacon.licenses.sanitiser.provider; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import org.codehaus.plexus.util.StringUtils; +import org.jboss.pnc.bacon.licenses.xml.LicenseElement; + +/** + * @author Michal Szynkiewicz, michal.l.szynkiewicz@gmail.com + */ +@JsonIgnoreProperties(ignoreUnknown = true) +public class ExternalLicenseDto { + private String name; + private String url; + private String textUrl; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getTextUrl() { + return textUrl; + } + + @JsonProperty("license_text_url") + public void setTextUrl(String textUrl) { + this.textUrl = textUrl; + } + + public LicenseElement toLicenseElement() { + return new LicenseElement(name, url, StringUtils.isBlank(textUrl) ? url : textUrl); + } +} diff --git a/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/sanitiser/provider/ExternalLicenseProvider.java b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/sanitiser/provider/ExternalLicenseProvider.java new file mode 100644 index 000000000..6999e4a67 --- /dev/null +++ b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/sanitiser/provider/ExternalLicenseProvider.java @@ -0,0 +1,94 @@ +/* + * Copyright 2016-2017 Red Hat, Inc, and individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jboss.pnc.bacon.licenses.sanitiser.provider; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.type.CollectionType; +import com.fasterxml.jackson.databind.type.TypeFactory; +import org.jboss.pnc.bacon.licenses.LicensesGeneratorException; +import org.jboss.pnc.bacon.licenses.xml.LicenseElement; +import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder; + +import javax.ws.rs.client.Client; +import javax.ws.rs.client.ClientBuilder; +import javax.ws.rs.core.Response; + +import java.io.IOException; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.logging.Logger; +import java.util.stream.Collectors; + +/** + * @author Michal Szynkiewicz, michal.l.szynkiewicz@gmail.com
+ * Date: 10/20/17 + */ +public class ExternalLicenseProvider { + + private static final Logger logger = Logger.getLogger(ExternalLicenseProvider.class.getSimpleName()); + private final Client client; + private final String licenseServiceUrl; + + public ExternalLicenseProvider(String licenseServiceUrl) { + this.licenseServiceUrl = licenseServiceUrl; + logger.info("Using license service " + licenseServiceUrl); + + ClientBuilder clientBuilder = ResteasyClientBuilder.newBuilder(); + client = clientBuilder.build(); + } + + public Set getLicenses(String gav) { + try (Response response = client.target(licenseServiceUrl).queryParam("gav", gav).request().get()) { + if (response.getStatus() != 200) { + logger.info( + "Unable to get license information for " + gav + " from license service: error " + + response.getStatus()); + } else { + logger.info("Got license information for " + gav + " from license service"); + String content = response.readEntity(String.class); + + Set licenses = parseLicenses(content).stream() + .flatMap(dto -> dto.getLicenses().stream()) + .map(ExternalLicenseDto::toLicenseElement) + .collect(Collectors.toSet()); + + if (areValid(licenses)) { + return licenses; + } + } + } catch (LicensesGeneratorException e) { + throw new RuntimeException("Error getting license for gav: " + gav, e); + } + return Collections.emptySet(); + } + + private boolean areValid(Collection licenses) { + return licenses.stream().allMatch(LicenseElement::isValid); + } + + private List parseLicenses(String content) throws LicensesGeneratorException { + ObjectMapper mapper = new ObjectMapper(); + TypeFactory typeFactory = mapper.getTypeFactory(); + CollectionType licenseList = typeFactory.constructCollectionType(List.class, ExternalLicensesDto.class); + try { + return mapper.readValue(content, licenseList); + } catch (IOException e) { + throw new LicensesGeneratorException("Unable to parse EAP licenses: " + content, e); + } + } +} diff --git a/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/sanitiser/provider/ExternalLicensesDto.java b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/sanitiser/provider/ExternalLicensesDto.java new file mode 100644 index 000000000..a9d508714 --- /dev/null +++ b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/sanitiser/provider/ExternalLicensesDto.java @@ -0,0 +1,36 @@ +/* + * Copyright 2016-2017 Red Hat, Inc, and individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jboss.pnc.bacon.licenses.sanitiser.provider; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import java.util.Set; + +/** + * @author Michal Szynkiewicz, michal.l.szynkiewicz@gmail.com + */ +@JsonIgnoreProperties(ignoreUnknown = true) +public class ExternalLicensesDto { + private Set licenses; + + public Set getLicenses() { + return licenses; + } + + public void setLicenses(Set licenses) { + this.licenses = licenses; + } +} diff --git a/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/utils/Gav.java b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/utils/Gav.java new file mode 100644 index 000000000..27e5fe540 --- /dev/null +++ b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/utils/Gav.java @@ -0,0 +1,77 @@ +/* + * Copyright 2016-2017 Red Hat, Inc, and individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jboss.pnc.bacon.licenses.utils; + +import java.util.Objects; + +/** + * @author Gytis Trikleris + */ +public class Gav { + + private final String groupId; + + private final String artifactId; + + private final String version; + + private final String type; + + public Gav(String groupId, String artifactId, String version, String type) { + this.groupId = groupId; + this.artifactId = artifactId; + this.version = version; + this.type = type; + } + + public String getGroupId() { + return groupId; + } + + public String getArtifactId() { + return artifactId; + } + + public String getVersion() { + return version; + } + + public String getType() { + return type; + } + + @Override + public String toString() { + return groupId + ":" + artifactId + ":" + version + ":" + type; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (!(o instanceof Gav)) + return false; + Gav gav = (Gav) o; + return Objects.equals(groupId, gav.groupId) && Objects.equals(artifactId, gav.artifactId) + && Objects.equals(version, gav.version) && Objects.equals(type, gav.type); + } + + @Override + public int hashCode() { + return Objects.hash(groupId, artifactId, version, type); + } +} diff --git a/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/utils/JsonUtils.java b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/utils/JsonUtils.java new file mode 100644 index 000000000..4b2af1065 --- /dev/null +++ b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/utils/JsonUtils.java @@ -0,0 +1,59 @@ +/* + * Copyright 2016-2017 Red Hat, Inc, and individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jboss.pnc.bacon.licenses.utils; + +import javax.json.Json; +import javax.json.JsonObject; +import javax.json.JsonValue; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * @author Michal Szynkiewicz, michal.l.szynkiewicz@gmail.com
+ * Date: 9/14/17 + */ +public interface JsonUtils { + + static Set loadJsonToSet(String resourceLocation, Function mapper) { + try (InputStream fileInputStream = getInputStream(resourceLocation)) { + return Json.createReader(fileInputStream) + .readArray() + .stream() + .map(JsonValue::asJsonObject) + .map(mapper) + .collect(Collectors.toSet()); + } catch (IOException e) { + throw new RuntimeException("Failed to read the resource: " + resourceLocation, e); + } + } + + static InputStream getInputStream(String resourceLocation) throws IOException { + Path path = Paths.get(resourceLocation); + + if (Files.exists(path)) { + return Files.newInputStream(path); + } + + return JsonUtils.class.getClassLoader().getResourceAsStream(resourceLocation); + } +} diff --git a/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/xml/DependencyElement.java b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/xml/DependencyElement.java new file mode 100644 index 000000000..9cee1c233 --- /dev/null +++ b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/xml/DependencyElement.java @@ -0,0 +1,186 @@ +/* + * Copyright 2016-2017 Red Hat, Inc, and individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jboss.pnc.bacon.licenses.xml; + +import org.apache.maven.artifact.Artifact; + +import javax.json.JsonObject; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElementWrapper; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; +import javax.xml.bind.annotation.XmlType; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * @author Gytis Trikleris + */ +@XmlRootElement(name = "dependency") +@XmlType(propOrder = { "groupId", "artifactId", "version", "licenses" }) +public class DependencyElement { + + private String groupId; + + private String artifactId; + + private String version; + + private Set licenses = new HashSet<>(); + + private Artifact artifact; + + public DependencyElement() { + } + + public DependencyElement(Artifact artifact) { + this.groupId = artifact.getGroupId(); + this.artifactId = artifact.getArtifactId(); + this.version = artifact.getVersion(); + this.artifact = artifact; + } + + public DependencyElement(DependencyElement dependencyElement) { + this( + dependencyElement.getGroupId(), + dependencyElement.getArtifactId(), + dependencyElement.getVersion(), + dependencyElement.getLicenses()); + } + + public DependencyElement(JsonObject dependencyElementJson) { + this.groupId = dependencyElementJson.getString("groupId"); + Objects.requireNonNull(this.groupId, "groupId cannot be null"); + + this.artifactId = dependencyElementJson.getString("artifactId"); + Objects.requireNonNull(this.artifactId, "artifactId cannot be null"); + + this.version = dependencyElementJson.getString("version"); + Objects.requireNonNull(this.version, "version cannot be null"); + + this.licenses = dependencyElementJson.getJsonArray("licenses") + .getValuesAs(JsonObject.class) + .stream() + .map(LicenseElement::new) + .collect(Collectors.toSet()); + } + + public DependencyElement(String groupId, String artifactId, String version, Set licenses) { + Objects.requireNonNull(groupId, "groupId cannot be null"); + Objects.requireNonNull(artifactId, "artifactId cannot be null"); + Objects.requireNonNull(version, "version cannot be null"); + Objects.requireNonNull(licenses, "licenses set cannot be null"); + this.groupId = groupId; + this.artifactId = artifactId; + this.version = version; + this.licenses = new HashSet<>(licenses.size()); + licenses.parallelStream().map(LicenseElement::new).forEach(this.licenses::add); + } + + public DependencyElement(DependencyElement dependencyElement, Set licenses) { + this(dependencyElement.groupId, dependencyElement.artifactId, dependencyElement.version, licenses); + } + + public String getGroupId() { + return groupId; + } + + @XmlElement + public void setGroupId(String groupId) { + this.groupId = groupId; + } + + public String getArtifactId() { + return artifactId; + } + + @XmlElement + public void setArtifactId(String artifactId) { + this.artifactId = artifactId; + } + + public String getVersion() { + return version; + } + + @XmlElement + public void setVersion(String version) { + this.version = version; + } + + public Set getLicenses() { + return licenses; + } + + @XmlElement(name = "license") + @XmlElementWrapper + public void setLicenses(Set licenses) { + this.licenses = Collections.unmodifiableSet(licenses); + } + + @Override + public String toString() { + return String.format( + "%s{groupId='%s', artifactId='%s', version='%s', licenses=%s}", + DependencyElement.class.getSimpleName(), + groupId, + artifactId, + version, + licenses); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + DependencyElement that = (DependencyElement) o; + + if (!groupId.equals(that.groupId)) { + return false; + } + if (!artifactId.equals(that.artifactId)) { + return false; + } + return version.equals(that.version); + } + + @Override + public int hashCode() { + int result = groupId.hashCode(); + result = 31 * result + artifactId.hashCode(); + result = 31 * result + version.hashCode(); + return result; + } + + public String toGavString() { + return String.format("%s:%s:%s", groupId, artifactId, version); + } + + @XmlTransient + public Artifact getArtifact() { + return artifact; + } +} diff --git a/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/xml/LicenseElement.java b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/xml/LicenseElement.java new file mode 100644 index 000000000..a3c7668af --- /dev/null +++ b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/xml/LicenseElement.java @@ -0,0 +1,131 @@ +/* + * Copyright 2016-2017 Red Hat, Inc, and individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jboss.pnc.bacon.licenses.xml; + +import org.apache.commons.lang3.StringUtils; +import org.apache.maven.model.License; + +import javax.json.JsonObject; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlTransient; + +/** + * @author Gytis Trikleris + */ +public class LicenseElement { + + private String name; + + private String url; + + private String textUrl; + + public LicenseElement() { + } + + public LicenseElement(License license) { + this(license.getName(), license.getUrl(), license.getUrl()); + } + + public LicenseElement(LicenseElement licenseElement) { + this.name = licenseElement.getName(); + this.url = licenseElement.getUrl(); + this.textUrl = licenseElement.getTextUrl(); + } + + public LicenseElement(JsonObject licenseElementJson) { + this(licenseElementJson.getString("name"), licenseElementJson.getString("url")); + } + + public LicenseElement(String name, String url) { + this(name, url, url); + } + + public LicenseElement(String name, String url, String textUrl) { + this.name = name; + this.url = url; + this.textUrl = textUrl; + } + + public String getName() { + return name; + } + + @XmlElement + public void setName(String name) { + this.name = name; + } + + public String getUrl() { + return url; + } + + @XmlElement + public void setUrl(String url) { + this.url = url; + } + + @XmlTransient + public void setTextUrl(String textUrl) { + this.textUrl = textUrl; + } + + public String getTextUrl() { + return textUrl; + } + + @Override + public String toString() { + return String.format( + "%s{name='%s', url='%s', textUrl=%s}", + LicenseElement.class.getSimpleName(), + name, + url, + textUrl); + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + + LicenseElement that = (LicenseElement) o; + + if (name != null ? !name.equals(that.name) : that.name != null) + return false; + if (url != null ? !url.equals(that.url) : that.url != null) + return false; + if (textUrl != null ? !textUrl.equals(that.textUrl) : that.textUrl != null) + return false; + + return true; + } + + @Override + public int hashCode() { + int result = name != null ? name.hashCode() : 0; + result = 31 * result + (url != null ? url.hashCode() : 0); + result = 31 * result + (textUrl != null ? textUrl.hashCode() : 0); + return result; + } + + public boolean isValid() { + return StringUtils.isNotBlank(url) && StringUtils.isNotBlank(name); + } +} diff --git a/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/xml/LicenseSummary.java b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/xml/LicenseSummary.java new file mode 100644 index 000000000..d0b983216 --- /dev/null +++ b/licenses-generator/src/main/java/org/jboss/pnc/bacon/licenses/xml/LicenseSummary.java @@ -0,0 +1,71 @@ +/* + * Copyright 2016-2017 Red Hat, Inc, and individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jboss.pnc.bacon.licenses.xml; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Marshaller; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElementWrapper; +import javax.xml.bind.annotation.XmlRootElement; + +import java.io.StringWriter; +import java.util.Collections; +import java.util.List; + +/** + * @author Gytis Trikleris + */ +@XmlRootElement +public class LicenseSummary { + + private List dependencies; + + public LicenseSummary() { + dependencies = Collections.emptyList(); + } + + public LicenseSummary(List dependencies) { + this.dependencies = Collections.unmodifiableList(dependencies); + } + + public List getDependencies() { + return dependencies; + } + + @XmlElement(name = "dependency") + @XmlElementWrapper + public void setDependencies(List dependencies) { + this.dependencies = Collections.unmodifiableList(dependencies); + } + + public String toXmlString() throws JAXBException { + StringWriter stringWriter = new StringWriter(); + JAXBContext jaxbContext = JAXBContext.newInstance(LicenseSummary.class); + Marshaller jaxbMarshaller = jaxbContext.createMarshaller(); + jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); + jaxbMarshaller.marshal(this, stringWriter); + + return stringWriter.toString(); + } + + @Override + public String toString() { + return String.format("%s{dependencies=%s}", LicenseSummary.class.getSimpleName(), dependencies); + } + +} diff --git a/licenses-generator/src/main/resources/generator.properties b/licenses-generator/src/main/resources/generator.properties new file mode 100644 index 000000000..e69de29bb diff --git a/licenses-generator/src/main/resources/licenses.qute b/licenses-generator/src/main/resources/licenses.qute new file mode 100644 index 000000000..6f37409ea --- /dev/null +++ b/licenses-generator/src/main/resources/licenses.qute @@ -0,0 +1,57 @@ + + + + + +

The following material has been provided for informational purposes only, and should not be relied upon or + construed as a legal opinion or legal advice.

+ + + + + {#for dependency in dependencies} + + + + + + + + {/for} +
Package GroupPackage ArtifactPackage VersionRemote LicensesLocal Licenses
{dependency.groupId}{dependency.artifactId}{dependency.version} + {#for license in dependency.licenses} + {license.name} +
+ {/for} +
+ {#for license in dependency.licenses} + {#if licenseFiles.containsKey(license.name)} + {license.name} +
+ {/if} + {/for} +
+ + diff --git a/licenses-generator/src/main/resources/rh-license-exceptions.json b/licenses-generator/src/main/resources/rh-license-exceptions.json new file mode 100644 index 000000000..239800e82 --- /dev/null +++ b/licenses-generator/src/main/resources/rh-license-exceptions.json @@ -0,0 +1,106 @@ +[ + { + "groupId": "org.apache.tomcat", + "artifactId": "servlet-api", + "version": "6.0.41", + "licenses": [ + { + "name": "Apache License 2.0", + "url": "http://www.apache.org/licenses/LICENSE-2.0.txt" + }, + { + "name": "Common Development and Distribution License 1.0", + "url": "http://repository.jboss.org/licenses/cddl.txt" + } + ] + }, + { + "groupId": "org.apache.tomcat", + "artifactId": "servlet-api", + "version": "6.0.41-redhat", + "licenses": [ + { + "name": "Apache License 2.0", + "url": "http://www.apache.org/licenses/LICENSE-2.0.txt" + }, + { + "name": "Common Development and Distribution License 1.0", + "url": "http://repository.jboss.org/licenses/cddl.txt" + } + ] + }, + { + "groupId": "antlr", + "artifactId": "antlr", + "version": "2.7.7", + "licenses": [ + { + "name": "The Antlr 2.7.7 License", + "url": "http://www.antlr2.org/license.html" + } + ] + }, + { + "groupId": "antlr", + "artifactId": "antlr", + "version": "2.7.7-redhat", + "licenses": [ + { + "name": "The Antlr 2.7.7 License", + "url": "http://www.antlr2.org/license.html" + } + ] + }, + { + "groupId": "dom4j", + "artifactId": "dom4j", + "version": "1.6.1", + "licenses": [ + { + "name": "Plexus Classworlds License", + "url": "https://raw.githubusercontent.com/dom4j/dom4j/dom4j_1_6_1/LICENSE.txt" + } + ] + }, + { + "groupId": "dom4j", + "artifactId": "dom4j", + "version": "1.6.1-redhat", + "licenses": [ + { + "name": "Plexus Classworlds License", + "url": "https://raw.githubusercontent.com/dom4j/dom4j/dom4j_1_6_1/LICENSE.txt" + } + ] + }, + { + "groupId": "com.h2database", + "artifactId": "h2", + "version": "1.4.196", + "licenses": [ + { + "name": "Eclipse Public License, Version 1.0", + "url": "http://repository.jboss.org/licenses/epl-1.0.txt" + }, + { + "name": "Mozilla Public License 2.0", + "url": "https://www.mozilla.org/en-US/MPL/2.0/" + } + ] + }, + { + "groupId": "com.h2database", + "artifactId": "h2", + "version": "1.4.197", + "licenses": [ + { + "name": "Eclipse Public License, Version 1.0", + "url": "http://repository.jboss.org/licenses/epl-1.0.txt" + }, + { + "name": "Mozilla Public License 2.0", + "url": "https://www.mozilla.org/en-US/MPL/2.0/" + } + ] + } +] diff --git a/licenses-generator/src/main/resources/rh-license-names.json b/licenses-generator/src/main/resources/rh-license-names.json new file mode 100644 index 000000000..77f9695bd --- /dev/null +++ b/licenses-generator/src/main/resources/rh-license-names.json @@ -0,0 +1,323 @@ +[ + { + "name": "The Antlr 2.7.7 License", + "url": "http://www.antlr2.org/license.html", + "aliases": [ + "The Antlr 2.7.7 License" + ], + "urlAliases": [ + "http://www.antlr2.org/license.html" + ] + }, + { + "name": "Apache License 2.0", + "url": "http://www.apache.org/licenses/LICENSE-2.0", + "textUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt", + "aliases": [ + "Apache Software License, Version 2.0", + "The Apache Software License, Version 2.0", + "Apache License, version 2.0", + "Apache License Version 2.0 ", + "Apache 2.0", + "Apache 2", + "Apache License", + "Apache License 2.0", + "ASL 2.0", + "ASL, version 2", + "Apache-2.0", + "AL2" + ], + "urlAliases": [ + "http://www.apache.org/licenses/LICENSE-2.0", + "http://www.apache.org/licenses/LICENSE-2.0.txt", + "http://www.apache.org/licenses/LICENSE-2.0.html" + ] + }, + { + "name": "GNU Lesser General Public License v2.1 only", + "textUrl": "http://repository.jboss.org/licenses/lgpl-2.1.txt", + "url": "http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html", + "aliases": [ + "GNU Lesser General Public License (LGPL), Version 2.1", + "GNU Lesser General Public License, Version 2.1", + "lgpl", + "LGPL 2.1", + "LGPL, version 2.1" + ], + "urlAliases": [ + "http://repository.jboss.org/licenses/lgpl-2.1.txt", + "https://www.gnu.org/licenses/lgpl-2.1.html", + "http://www.gnu.org/licenses/lgpl-2.1.html", + "https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html", + "http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html" + ] + }, + { + "name": "GNU Lesser General Public License, Version 3", + "url": "http://www.gnu.org/licenses/lgpl-3.0-standalone.html", + "aliases": [ + "GNU Lesser General Public License, Version 3", + "The GNU Lesser General Public License, version 3" + ], + "urlAliases": [ + "https://www.gnu.org/licenses/lgpl-3.0-standalone.html", + "http://www.gnu.org/licenses/lgpl-3.0-standalone.html", + "https://www.gnu.org/licenses/lgpl.html", + "http://www.gnu.org/licenses/lgpl.html", + "https://www.gnu.org/licenses/lgpl-3.0.txt", + "http://www.gnu.org/licenses/lgpl-3.0.txt" + ] + }, + { + "name": "GNU General Public License v2.0 only", + "url": "https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html", + "aliases": [ + "GNU General Public License v2.0 only", + "The GNU General Public License, Version 2" + ], + "urlAliases": [ + "https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html", + "http://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html", + "https://www.gnu.org/licenses/old-licenses/gpl-2.0.html", + "http://www.gnu.org/licenses/old-licenses/gpl-2.0.html", + "https://www.gnu.org/licenses/gpl-2.0.txt", + "http://www.gnu.org/licenses/gpl-2.0.txt" + ] + }, + { + "name": "GNU General Public License, Version 2 with the Classpath Exception", + "url": "http://repository.jboss.org/licenses/gpl-2.0-ce.txt", + "aliases": [ + "GNU General Public License, Version 2 with the Classpath Exception", + "GPL2 w/ CPE" + ], + "urlAliases": [ + "http://repository.jboss.org/licenses/gpl-2.0-ce.txt" + ] + }, + { + "name": "GNU General Public License v3.0 only", + "url": "https://www.gnu.org/licenses/gpl-3.0-standalone.html", + "aliases": [ + "GNU General Public License v3.0 only", + "GPLv3", + "GPL 3" + ], + "urlAliases": [ + "https://www.gnu.org/licenses/gpl-3.0-standalone.html", + "http://www.gnu.org/licenses/gpl-3.0-standalone.html" + ] + }, + { + "name": "MIT License", + "url": "https://opensource.org/licenses/MIT/", + "aliases": [ + "MIT License", + "The MIT License" + ], + "urlAliases": [ + "http://www.opensource.org/licenses/MIT", + "http://opensource.org/licenses/MIT", + "https://opensource.org/licenses/MIT", + "http://www.opensource.org/licenses/mit-license.php" + ] + }, + { + "name": "Common Development and Distribution License 1.0", + "url": "http://repository.jboss.org/licenses/cddl.txt", + "aliases": [ + "Common Development Distribution License", + "Common Development and Distribution License", + "Common Development and Distribution License 1.0", + "CDDL License", + "COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0" + ], + "urlAliases": [ + "http://repository.jboss.org/licenses/cddl.txt", + "http://www.sun.com/cddl/cddl.html", + "http://www.opensource.org/licenses/cddl1.php" + ] + }, + { + "name": "Common Development and Distribution License 1.1", + "url": "https://javaee.github.io/glassfish/LICENSE", + "aliases": [ + "Common Development and Distribution License 1.1", + "CDDL 1.1" + ], + "urlAliases": [ + "https://javaee.github.io/glassfish/LICENSE" + ] + }, + { + "name": "Common Development and Distribution License (CDDL) and GNU Public License v.2 w/Classpath Exception", + "url": "https://netbeans.org/cddl-gplv2.html", + "aliases": [ + "Common Development and Distribution License (CDDL) and GNU Public License v.2 w/Classpath Exception", + "CDDL + GPLv2 with classpath exception", + "CDDL or GPLv2 with exceptions" + ], + "urlAliases": [ + "https://netbeans.org/cddl-gplv2.html", + "https://glassfish.dev.java.net/nonav/public/CDDL+GPL.html" + ] + }, + { + "name": "Sax Public Domain Notice", + "url": "http://www.saxproject.org/copying.html", + "aliases": [ + "Sax Public Domain Notice", + "The SAX License" + ], + "urlAliases": [ + "http://www.saxproject.org/copying.html" + ] + }, + { + "name": "Eclipse Public License, Version 1.0", + "url": "http://repository.jboss.org/licenses/epl-1.0.txt", + "aliases": [ + "Eclipse Public License, Version 1.0", + "Eclipse Public License 1.0", + "Eclipse Public License v1.0", + "Eclipse Public License - v 1.0", + "Eclipse Public License (EPL), Version 1.0" + ], + "urlAliases": [ + "http://repository.jboss.org/licenses/epl-1.0.txt", + "http://www.eclipse.org/legal/epl-v10.html", + "http://www.eclipse.org/org/documents/epl-v10.php" + ] + }, + { + "name": "Eclipse Distribution License, Version 1.0", + "url": "http://repository.jboss.org/licenses/edl-1.0.txt", + "textUrl": "http://repository.jboss.org/licenses/edl-1.0.txt", + "aliases": [ + "Eclipse Distribution License, Version 1.0", + "Eclipse Distribution License (EDL), Version 1.0" + ], + "urlAliases": [ + "http://repository.jboss.org/licenses/edl-1.0.txt", + "http://www.eclipse.org/org/documents/edl-v10.php" + ] + }, + { + "name": "BSD 2-clause \"Simplified\" License", + "url": "https://opensource.org/licenses/BSD-2-Clause/", + "aliases": [ + "BSD 2-clause \"Simplified\" License", + "BSD-2-Clause" + ], + "urlAliases": [ + "http://www.opensource.org/licenses/BSD-2-Clause", + "https://opensource.org/licenses/BSD-2-Clause", + "http://www.opensource.org/licenses/bsd-license.php" + ] + }, + { + "name": "BSD 3-clause \"New\" or \"Revised\" License", + "url": "https://opensource.org/licenses/BSD-3-Clause/", + "aliases": [ + "BSD 3-clause \"New\" or \"Revised\" License", + "BSD 3-Clause", + "BSD 3-Clause License" + ], + "urlAliases": [ + "https://opensource.org/licenses/BSD-3-Clause", + "http://www.opensource.org/licenses/BSD-3-Clause", + "http://opensource.org/licenses/BSD-3-Clause", + "http://www.antlr.org/license.html", + "http://dom4j.sourceforge.net/dom4j-1.6.1/license.html" + ] + }, + { + "name": "The Asm BSD License", + "url": "http://asm.ow2.org/license.html", + "aliases": [ + "The Asm BSD License" + ], + "urlAliases": [ + "http://asm.ow2.org/license.html", + "http://asm.objectweb.org/license.html" + ] + }, + { + "name": "Mozilla Public License 1.1", + "url": "https://www.mozilla.org/en-US/MPL/1.1/", + "aliases": [ + "Mozilla Public License 1.1", + "MPL 1.1" + ], + "urlAliases": [ + "http://www.mozilla.org/MPL/MPL-1.1.html", + "https://www.mozilla.org/en-US/MPL/1.1" + ] + }, + { + "name": "Mozilla Public License 2.0", + "url": "https://www.mozilla.org/en-US/MPL/2.0/", + "aliases": [ + "Mozilla Public License 2.0" + ], + "urlAliases": [ + "https://www.mozilla.org/en-US/MPL/2.0", + "http://www.mozilla.org/MPL/2.0", + "https://www.mozilla.org/media/MPL/2.0/index.txt", + "http://www.mozilla.org/MPL/2.0/index.txt" + ] + }, + { + "name": "JSON License", + "url": "http://www.json.org/license.html", + "aliases": [ + "JSON License", + "The JSON License" + ], + "urlAliases": [ + "http://www.json.org/license.html" + ] + }, + { + "name": "Bouncy Castle Licence", + "url": "http://www.bouncycastle.org/licence.html", + "aliases": [ + "Bouncy Castle Licence" + ], + "urlAliases": [ + "http://www.bouncycastle.org/licence.html" + ] + }, + { + "name": "Common Public License, Version 1.0", + "url": "https://opensource.org/licenses/CPL-1.0", + "aliases": [ + "Common Public License, Version 1.0", + "Common Public License Version 1.0" + ], + "urlAliases": [ + "https://opensource.org/licenses/CPL-1.0", + "http://opensource.org/licenses/CPL-1.0", + "http://www.opensource.org/licenses/cpl1.0.txt" + ] + }, + { + "name": "The W3C License", + "url": "https://www.w3.org/Consortium/Legal/2002/copyright-software-20021231.html", + "aliases": [], + "urlAliases": [ + "http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/java-binding.zip", + "https://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/java-binding.zip" + ] + }, + { + "name": "Creative Commons Zero 1.0 Universal", + "url": "http://creativecommons.org/publicdomain/zero/1.0/legalcode", + "aliases": [ + "CC0" + ], + "urlAliases": [ + "http://creativecommons.org/publicdomain/zero/1.0" + ] + } +] diff --git a/licenses-generator/src/main/resources/simplelogger.properties b/licenses-generator/src/main/resources/simplelogger.properties new file mode 100644 index 000000000..64339877a --- /dev/null +++ b/licenses-generator/src/main/resources/simplelogger.properties @@ -0,0 +1,2 @@ +org.slf4j.simpleLogger.defaultLogLevel=info +org.slf4j.simpleLogger.log.me.snowdrop=info diff --git a/licenses-generator/src/test/java/org/jboss/pnc/bacon/licenses/ExternalLicensesTest.java b/licenses-generator/src/test/java/org/jboss/pnc/bacon/licenses/ExternalLicensesTest.java new file mode 100644 index 000000000..e238b44d7 --- /dev/null +++ b/licenses-generator/src/test/java/org/jboss/pnc/bacon/licenses/ExternalLicensesTest.java @@ -0,0 +1,125 @@ +package org.jboss.pnc.bacon.licenses; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.artifact.DefaultArtifact; +import org.apache.maven.artifact.handler.DefaultArtifactHandler; +import org.apache.maven.model.License; +import org.jboss.pnc.bacon.licenses.maven.MavenProjectFactoryException; +import org.jboss.pnc.bacon.licenses.properties.GeneratorProperties; +import org.jboss.pnc.bacon.licenses.xml.DependencyElement; +import org.jboss.pnc.bacon.licenses.xml.LicenseElement; +import org.jboss.pnc.bacon.licenses.xml.LicenseSummary; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +import java.util.Optional; +import java.util.Set; + +import static java.util.Collections.singleton; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +/** + * @author Michal Szynkiewicz, michal.l.szynkiewicz@gmail.com
+ * Date: 11/15/17 + */ +public class ExternalLicensesTest { + private static final String artifactWithLicenseInEap = "eap-known:artifact:1.0-redhat-1"; + private static final String artifactWithLicenseInFile = "eap-unknown:artifact:2.0.0-redhat-1"; + private static final String artifactWithLicenseInFileInCommunityVersion = "eap-unknown:artifact:1.0-redhat-1"; + public static final String APACHE_SOFTWARE_LICENSE_VERSION_2_0_NAME = "Apache Software License, Version 2.0"; + public static final String APACHE_SOFTWARE_LICENSE_VERSION_2_0_JSON = "{ \n" + " \"name\": \"" + + APACHE_SOFTWARE_LICENSE_VERSION_2_0_NAME + "\",\n" + + " \"url\": \"http://example.com/apache-license-url\",\n" + + " \"license_text_url\": \"http://example.com/apache-license/content.txt\"\n" + "}"; + public static final String ECLIPSE_LICENSE_NAME = "Eclipse Public License 1.0"; + public static final String ECLIPSE_LICENSE_LINK = "http://www.eclipse.org/legal/epl-v10.html"; + + private static String licenseServiceUrl; + private static LicenseServiceMock licenseServiceMock; + + private LicenseSummaryFactory summaryFactory; + + @BeforeAll + public static void setUp() { + licenseServiceMock = new LicenseServiceMock(); + licenseServiceMock.addLicenses(artifactWithLicenseInEap, APACHE_SOFTWARE_LICENSE_VERSION_2_0_JSON); + licenseServiceUrl = licenseServiceMock.start("/licensecheck"); + } + + @BeforeEach + public void before() throws LicensesGeneratorException { + GeneratorProperties properties = mock(GeneratorProperties.class); + + when(properties.getLicenseServiceUrl()).thenReturn(Optional.of(licenseServiceUrl)); + when(properties.getAliasesFilePath()).thenReturn("rh-license-names.json"); + when(properties.getExceptionsFilePath()).thenReturn("rh-license-exceptions.json"); + + LicensesGenerator generator = new LicensesGenerator(properties); + + summaryFactory = generator.createLicenseSummaryFactory(); + } + + @AfterAll + public static void tearDown() { + licenseServiceMock.stop(); + } + + @Test + public void shouldGetFromService() throws MavenProjectFactoryException { + Set licenses = getLicensesForGav(artifactWithLicenseInEap); + assertThat(licenses).hasSize(1); + + LicenseElement actual = licenses.iterator().next(); + assertThat(actual.getName()).isEqualTo(APACHE_SOFTWARE_LICENSE_VERSION_2_0_NAME); + assertThat(actual.getUrl()).isEqualTo("http://example.com/apache-license-url"); + assertThat(actual.getTextUrl()).isEqualTo("http://example.com/apache-license/content.txt"); + + } + + @Test + public void shouldGetFromFileIfNotAvailableViaService() throws MavenProjectFactoryException { + Set licenseElements = getLicensesForGav(artifactWithLicenseInFile); + assertThat(licenseElements).containsExactlyInAnyOrder( + new LicenseElement("Test License A", "http://test-license-a.com", "http://test-license-a.com")); + } + + @Test + @Disabled("Not implemented, a nice-to have feature") + public void shouldGetFromFileForCommunityVersionIfNotAvailableViaService() throws MavenProjectFactoryException { + Set licenseElements = getLicensesForGav(artifactWithLicenseInFileInCommunityVersion); + assertThat(licenseElements).containsExactlyInAnyOrder( + new LicenseElement("Test License B", "http://test-license-b.com", "http://test-license-b.com")); + } + + @Test + public void shouldGetFromMavenIfNotAvailableInFileOrService() throws MavenProjectFactoryException { + Set licenses = getLicensesForGav("junit:junit:4.12"); + assertThat(licenses).containsExactlyInAnyOrder( + new LicenseElement(ECLIPSE_LICENSE_NAME, ECLIPSE_LICENSE_LINK, ECLIPSE_LICENSE_LINK)); + } + + private Set getLicensesForGav(String gav) throws MavenProjectFactoryException { + LicenseSummary licenseSummary = summaryFactory.getLicenseSummary(singleton(artifact(gav))); + assertThat(licenseSummary.getDependencies()).hasSize(1); + + DependencyElement element = licenseSummary.getDependencies().get(0); + return element.getLicenses(); + } + + private Artifact artifact(String gavAsString) throws MavenProjectFactoryException { + String gav[] = gavAsString.split(":"); + return new DefaultArtifact(gav[0], gav[1], gav[2], "compile", "jar", "", new DefaultArtifactHandler()); + } + + private License mavenLicense(String name, String url) { + License license = new License(); + license.setName(name); + license.setUrl(url); + return license; + } +} diff --git a/licenses-generator/src/test/java/org/jboss/pnc/bacon/licenses/LicenseServiceMock.java b/licenses-generator/src/test/java/org/jboss/pnc/bacon/licenses/LicenseServiceMock.java new file mode 100644 index 000000000..19479882d --- /dev/null +++ b/licenses-generator/src/test/java/org/jboss/pnc/bacon/licenses/LicenseServiceMock.java @@ -0,0 +1,86 @@ +/* + * Copyright 2016-2017 Red Hat, Inc, and individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jboss.pnc.bacon.licenses; + +import io.undertow.Undertow; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @author Michal Szynkiewicz, michal.l.szynkiewicz@gmail.com
+ * Date: 10/23/17 + */ +public class LicenseServiceMock { + + public static final String LICENSES = "LICENSES"; + private static final String responseTemplate = "[\n" + " {\n" + " \"project\": \"antlr2:2.7.7.redhat-7\",\n" + + " \"root pom GAV\": \"antlr:antlr:2.7.7.redhat-7\",\n" + " \"scope\": \"PROJECT\",\n" + + " \"SCM info\": [\n" + " {\n" + " \"name\": \"internal\",\n" + + " \"type\": \"git\",\n" + " \"url\": \"git://git.app.eng.bos.redhat.com/antlr2.git\",\n" + + " \"revision\": \"bd0ab97\"\n" + " }\n" + " ],\n" + " \"licenses\": [\n" + " " + + LICENSES + " " + " ],\n" + " \"license determination type\": {\n" + " \"id\": \"14\",\n" + + " \"name\": \"License file, readme file, missing in pom file\"\n" + " },\n" + + " \"license determination hints\": [\n" + " {\n" + " \"name\": \"license file\",\n" + + " \"values\": [\n" + " \"LICENSE.txt\"\n" + " ]\n" + " },\n" + " {\n" + + " \"name\": \"pom file\",\n" + " \"value\": \"pom.xml\"\n" + " },\n" + " {\n" + + " \"name\": \"readme file\",\n" + " \"values\": [\n" + " \"README.txt:2:33\"\n" + + " ]\n" + " }\n" + " ],\n" + " \"determined by\": \"mminar\",\n" + + " \"determined date\": \"2017-07-19\"\n" + " }\n" + "]"; + + private final Map licensesPerGav = new HashMap<>(); + private Undertow server; + + public void addLicenses(String gav, String... licenses) { + String licensesAsString = Arrays.stream(licenses).collect(Collectors.joining(", ")); + String licenseData = responseTemplate.replace(LICENSES, licensesAsString); + licensesPerGav.put(gav, licenseData); + } + + /** + * expose endpoint at given path + * + * @return port number + */ + public String start(String path) { + server = Undertow.builder().addHttpListener(0, "localhost").setHandler(exchange -> { + if (!path.equals(exchange.getRelativePath())) { + exchange.setStatusCode(404); + } + String gav = exchange.getQueryParameters().get("gav").getFirst(); + String maybeLicenseInfo = licensesPerGav.get(gav); + if (maybeLicenseInfo == null) { + exchange.setStatusCode(404); + } else { + exchange.setStatusCode(200); + exchange.getResponseSender().send(maybeLicenseInfo); + } + }).build(); + server.start(); + return constructUrl(path); + } + + private String constructUrl(String path) { + Undertow.ListenerInfo listener = server.getListenerInfo().get(0); + return listener.getProtcol() + ":/" + listener.getAddress().toString() + path; + } + + public void stop() { + server.stop(); + } +} diff --git a/licenses-generator/src/test/java/org/jboss/pnc/bacon/licenses/LicenseSummaryFactoryTest.java b/licenses-generator/src/test/java/org/jboss/pnc/bacon/licenses/LicenseSummaryFactoryTest.java new file mode 100644 index 000000000..dddf17c06 --- /dev/null +++ b/licenses-generator/src/test/java/org/jboss/pnc/bacon/licenses/LicenseSummaryFactoryTest.java @@ -0,0 +1,94 @@ +package org.jboss.pnc.bacon.licenses; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.model.License; +import org.apache.maven.project.MavenProject; +import org.jboss.pnc.bacon.licenses.maven.MavenProjectFactory; +import org.jboss.pnc.bacon.licenses.sanitiser.LicenseSanitiser; +import org.jboss.pnc.bacon.licenses.sanitiser.MavenSanitiser; +import org.jboss.pnc.bacon.licenses.xml.DependencyElement; +import org.jboss.pnc.bacon.licenses.xml.LicenseElement; +import org.jboss.pnc.bacon.licenses.xml.LicenseSummary; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.util.Collection; +import java.util.Collections; +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +/** + * @author Gytis Trikleris + */ +public class LicenseSummaryFactoryTest { + + @Mock + private Artifact mockArtifact; + @Mock + private MavenProject mockMavenProject; + + @Mock + private License mockLicense; + @Mock + private LicenseSanitiser mockLicenseSanitiser; + @Mock + private MavenProjectFactory projectFactoryMock; + + private LicenseSummaryFactory licenseSummaryFactory; + private MavenSanitiser mavenSanitiser; + + @BeforeEach + public void before() { + MockitoAnnotations.initMocks(this); + when(mockLicenseSanitiser.fix(any())).then(a -> a.getArgument(0)); + + mavenSanitiser = new MavenSanitiser(projectFactoryMock, mockLicenseSanitiser); + licenseSummaryFactory = new LicenseSummaryFactory(mavenSanitiser); + } + + @Test + public void shouldGetLicenseSummary() { + when(mockArtifact.getGroupId()).thenReturn("testGroupId"); + when(mockArtifact.getArtifactId()).thenReturn("testArtifactId"); + when(mockArtifact.getVersion()).thenReturn("testVersion"); + + when(mockMavenProject.getGroupId()).thenReturn("testGroupId"); + when(mockMavenProject.getArtifactId()).thenReturn("testArtifactId"); + when(mockMavenProject.getVersion()).thenReturn("testVersion"); + when(mockMavenProject.getLicenses()).thenReturn(Collections.singletonList(mockLicense)); + + when(projectFactoryMock.getMavenProject(any(), eq(false))).thenReturn(Optional.of(mockMavenProject)); + + when(mockLicense.getName()).thenReturn("testLicenseName"); + when(mockLicense.getUrl()).thenReturn("testLicenseUrl"); + + Collection mavenProjects = Collections.singleton(mockArtifact); + LicenseSummary licenseSummary = licenseSummaryFactory.getLicenseSummary(mavenProjects); + + assertThat(licenseSummary).isNotNull(); + assertThat(licenseSummary.getDependencies()).hasSize(1); + + DependencyElement dependencyElement = licenseSummary.getDependencies() + .get(0); + assertThat(dependencyElement.getGroupId()).isEqualTo("testGroupId"); + assertThat(dependencyElement.getArtifactId()).isEqualTo("testArtifactId"); + assertThat(dependencyElement.getVersion()).isEqualTo("testVersion"); + assertThat(dependencyElement.getLicenses()).hasSize(1); + + LicenseElement licenseElement = dependencyElement.getLicenses() + .iterator() + .next(); + assertThat(licenseElement.getName()).isEqualTo("testLicenseName"); + assertThat(licenseElement.getUrl()).isEqualTo("testLicenseUrl"); + + verify(mockLicenseSanitiser).fix(dependencyElement); + } + +} diff --git a/licenses-generator/src/test/java/org/jboss/pnc/bacon/licenses/maven/MavenProjectFactoryTest.java b/licenses-generator/src/test/java/org/jboss/pnc/bacon/licenses/maven/MavenProjectFactoryTest.java new file mode 100644 index 000000000..3273a5544 --- /dev/null +++ b/licenses-generator/src/test/java/org/jboss/pnc/bacon/licenses/maven/MavenProjectFactoryTest.java @@ -0,0 +1,159 @@ +package org.jboss.pnc.bacon.licenses.maven; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.project.MavenProject; +import org.apache.maven.project.ProjectBuilder; +import org.apache.maven.project.ProjectBuildingException; +import org.apache.maven.project.ProjectBuildingRequest; +import org.apache.maven.project.ProjectBuildingResult; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.io.File; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +/** + * @author Gytis Trikleris + */ +public class MavenProjectFactoryTest { + + @Mock + private File mockFile; + + @Mock + private Artifact mockArtifact; + + @Mock + private ProjectBuilder mockProjectBuilder; + + @Mock + private ProjectBuildingRequestFactory mockProjectBuildingRequestFactory; + + @Mock + private ProjectBuildingRequest mockProjectBuildingRequest; + + @Mock + private ProjectBuildingResult mockProjectBuildingResult; + + @Mock + private MavenProject mockMavenProject; + + private MavenProjectFactory mavenProjectFactory; + + @BeforeEach + public void before() throws ProjectBuildingException { + MockitoAnnotations.initMocks(this); + + when(mockProjectBuildingRequestFactory.getProjectBuildingRequest()).thenReturn(mockProjectBuildingRequest); + when(mockProjectBuilder.build(any(Artifact.class), eq(mockProjectBuildingRequest))) + .thenReturn(mockProjectBuildingResult); + when(mockProjectBuilder.build(eq(mockFile), eq(mockProjectBuildingRequest))) + .thenReturn(mockProjectBuildingResult); + when( + mockProjectBuilder + .build(eq(Collections.singletonList(mockFile)), eq(true), eq(mockProjectBuildingRequest))) + .thenReturn(Collections.singletonList(mockProjectBuildingResult)); + when(mockProjectBuildingResult.getProject()).thenReturn(mockMavenProject); + when(mockMavenProject.getFile()).thenReturn(mockFile); + + mavenProjectFactory = new MavenProjectFactory(mockProjectBuilder, mockProjectBuildingRequestFactory); + } + + @Test + public void shouldGetMavenProjectFromArtifactWithoutDependencies() throws ProjectBuildingException { + Optional mavenProjectOptional = mavenProjectFactory.getMavenProject(mockArtifact, false); + + assertThat(mavenProjectOptional.isPresent()).isTrue(); + assertThat(mavenProjectOptional.get()).isEqualTo(mockMavenProject); + + verify(mockProjectBuildingRequestFactory).getProjectBuildingRequest(); + verify(mockProjectBuildingRequest).setResolveDependencies(false); + verify(mockProjectBuilder).build(mockArtifact, mockProjectBuildingRequest); + verify(mockProjectBuildingResult).getProject(); + } + + @Test + public void shouldGetMavenProjectFromArtifactWithDependencies() throws ProjectBuildingException { + Optional mavenProjectOptional = mavenProjectFactory.getMavenProject(mockArtifact, true); + + assertThat(mavenProjectOptional.isPresent()).isTrue(); + assertThat(mavenProjectOptional.get()).isEqualTo(mockMavenProject); + + verify(mockProjectBuildingRequestFactory).getProjectBuildingRequest(); + verify(mockProjectBuildingRequest).setResolveDependencies(true); + verify(mockProjectBuilder).build(mockArtifact, mockProjectBuildingRequest); + verify(mockProjectBuildingResult).getProject(); + } + + @Test + public void shouldNotGetProjectFromArtifactInCaseOfException() throws ProjectBuildingException { + when(mockProjectBuilder.build(any(Artifact.class), eq(mockProjectBuildingRequest))).thenThrow( + ProjectBuildingException.class); + Optional mavenProjectOptional = mavenProjectFactory.getMavenProject(mockArtifact, true); + + assertThat(mavenProjectOptional.isPresent()).isFalse(); + } + + @Test + public void shouldGetMavenProjectFromPomWithoutDependencies() throws ProjectBuildingException { + List mavenProjects = mavenProjectFactory.getMavenProjects(mockFile, false); + + assertThat(mavenProjects).containsOnly(mockMavenProject); + + verify(mockProjectBuildingRequestFactory).getProjectBuildingRequest(); + verify(mockProjectBuildingRequest).setResolveDependencies(false); + verify(mockProjectBuilder).build(Collections.singletonList(mockFile), true, mockProjectBuildingRequest); + verify(mockProjectBuildingResult).getProject(); + } + + @Test + public void shouldGetMavenProjectsFromPomWithDependencies() throws ProjectBuildingException { + List mavenProjects = mavenProjectFactory.getMavenProjects(mockFile, true); + + assertThat(mavenProjects).containsOnly(mockMavenProject); + + verify(mockProjectBuildingRequestFactory).getProjectBuildingRequest(); + verify(mockProjectBuildingRequest).setResolveDependencies(true); + verify(mockProjectBuilder).build(Collections.singletonList(mockFile), true, mockProjectBuildingRequest); + verify(mockProjectBuildingResult, times(2)).getProject(); + } + + @Test + public void shouldGetMavenProjectsFromPomWithModules() throws ProjectBuildingException { + when(mockProjectBuilder.build(eq(Collections.singletonList(mockFile)), eq(true), + eq(mockProjectBuildingRequest))).thenReturn( + Arrays.asList(mockProjectBuildingResult, mockProjectBuildingResult)); + + List mavenProjects = mavenProjectFactory.getMavenProjects(mockFile, true); + + assertThat(mavenProjects).hasSize(2); + assertThat(mavenProjects).containsOnly(mockMavenProject); + + verify(mockProjectBuildingRequestFactory).getProjectBuildingRequest(); + verify(mockProjectBuildingRequest).setResolveDependencies(true); + verify(mockProjectBuilder).build(Collections.singletonList(mockFile), true, mockProjectBuildingRequest); + verify(mockProjectBuildingResult, times(4)).getProject(); + } + + @Test + public void shouldNotGetProjectsFromPomInCaseOfException() throws ProjectBuildingException { + when(mockProjectBuilder.build(eq(Collections.singletonList(mockFile)), eq(true), + eq(mockProjectBuildingRequest))).thenThrow(ProjectBuildingException.class); + List mavenProjects = mavenProjectFactory.getMavenProjects(mockFile, false); + + assertThat(mavenProjects).isEmpty(); + } + +} diff --git a/licenses-generator/src/test/java/org/jboss/pnc/bacon/licenses/properties/GeneratorPropertiesTest.java b/licenses-generator/src/test/java/org/jboss/pnc/bacon/licenses/properties/GeneratorPropertiesTest.java new file mode 100644 index 000000000..5af7c8fa3 --- /dev/null +++ b/licenses-generator/src/test/java/org/jboss/pnc/bacon/licenses/properties/GeneratorPropertiesTest.java @@ -0,0 +1,71 @@ +/* + * Copyright 2016-2017 Red Hat, Inc, and individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jboss.pnc.bacon.licenses.properties; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Gytis Trikleris + */ +public class GeneratorPropertiesTest { + + @Test + public void shouldGetDefaultProperties() { + GeneratorProperties properties = new GeneratorProperties("test_properties/empty.properties"); + assertThat(properties.getRepositories()).containsOnlyKeys("Maven Central") + .containsValues("https://repo1.maven.org/maven2"); + assertThat(properties.getLicenseServiceUrl()).isEmpty(); + } + + @Test + public void shouldGetModifiedProperties() { + GeneratorProperties properties = new GeneratorProperties("test_properties/modified.properties"); + assertThat(properties.getRepositories()).containsOnlyKeys("testRepositoryName1", "testRepositoryName2") + .containsValues("testRepositoryUrl1", "testRepositoryUrl2"); + assertThat(properties.getLicenseServiceUrl()).contains("http://10.10.10.10/find-license-check-record"); + } + + @Test + public void shouldFailToGetWrongRepositories() { + Assertions.assertThrows(GeneratorPropertiesException.class, () -> { + GeneratorProperties properties = new GeneratorProperties("test_properties/wrong-repositories.properties"); + properties.getRepositories(); + }); + } + + @Test + public void shouldGetAliasesFilePath() { + GeneratorProperties properties = new GeneratorProperties(); + assertThat(properties.getAliasesFilePath()).isEqualTo("rh-license-names.json"); + + properties.setAliasesFilePath("another-license-names.json"); + assertThat(properties.getAliasesFilePath()).isEqualTo("another-license-names.json"); + } + + @Test + public void shouldGetExceptionsFilePath() { + GeneratorProperties properties = new GeneratorProperties(); + assertThat(properties.getExceptionsFilePath()).isEqualTo("rh-license-exceptions.json"); + + properties.setExceptionsFilePath("another-license-exceptions.json"); + assertThat(properties.getExceptionsFilePath()).isEqualTo("another-license-exceptions.json"); + } + +} diff --git a/licenses-generator/src/test/java/org/jboss/pnc/bacon/licenses/sanitiser/AliasLicenseSanitiserTest.java b/licenses-generator/src/test/java/org/jboss/pnc/bacon/licenses/sanitiser/AliasLicenseSanitiserTest.java new file mode 100644 index 000000000..a846ef539 --- /dev/null +++ b/licenses-generator/src/test/java/org/jboss/pnc/bacon/licenses/sanitiser/AliasLicenseSanitiserTest.java @@ -0,0 +1,188 @@ +package org.jboss.pnc.bacon.licenses.sanitiser; + +import org.jboss.pnc.bacon.licenses.xml.DependencyElement; +import org.jboss.pnc.bacon.licenses.xml.LicenseElement; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + +/** + * @author Gytis Trikleris + */ +public class AliasLicenseSanitiserTest { + + @Mock + private LicenseSanitiser mockLicenseSanitiser; + + private AliasLicenseSanitiser aliasLicenseSanitiser; + + @BeforeEach + public void before() { + MockitoAnnotations.initMocks(this); + + aliasLicenseSanitiser = new AliasLicenseSanitiser("rh-license-names.json", mockLicenseSanitiser); + } + + @Test + public void shouldFixLicenseNameWithAlias() { + LicenseElement licenseElement = new LicenseElement("Test License Alias", "http://test-license.com"); + DependencyElement dependencyElement = new DependencyElement("", "", "", Collections.singleton(licenseElement)); + + DependencyElement fixedDependencyElement = aliasLicenseSanitiser.fix(dependencyElement); + + assertThat(fixedDependencyElement).isEqualTo(dependencyElement); + assertThat(fixedDependencyElement.getLicenses()).hasSize(1); + + Collection fixedLicenseElements = fixedDependencyElement.getLicenses(); + assertThat(fixedLicenseElements) + .containsOnly(new LicenseElement("Test License Name", "http://test-license.com")); + + verify(mockLicenseSanitiser, times(0)).fix(any()); + } + + @Test + public void shouldFixLicenseNameWithAliasAndNullUrl() { + LicenseElement licenseElement = new LicenseElement("Test License Alias", null); + DependencyElement dependencyElement = new DependencyElement("", "", "", Collections.singleton(licenseElement)); + + DependencyElement fixedDependencyElement = aliasLicenseSanitiser.fix(dependencyElement); + + assertThat(fixedDependencyElement).isEqualTo(dependencyElement); + assertThat(fixedDependencyElement.getLicenses()).hasSize(1); + + Collection fixedLicenseElements = fixedDependencyElement.getLicenses(); + assertThat(fixedLicenseElements) + .containsOnly(new LicenseElement("Test License Name", "http://test-license.com")); + + verify(mockLicenseSanitiser, times(0)).fix(any()); + } + + @Test + public void shouldFixLicenseUrlWithAlias() { + LicenseElement licenseElement = new LicenseElement( + "Test License Name", + "http://test-license-alias.com", + "http://text-url.example.com"); + DependencyElement dependencyElement = new DependencyElement("", "", "", Collections.singleton(licenseElement)); + + DependencyElement fixedDependencyElement = aliasLicenseSanitiser.fix(dependencyElement); + + assertThat(fixedDependencyElement).isEqualTo(dependencyElement); + assertThat(fixedDependencyElement.getLicenses()).hasSize(1); + + Collection fixedLicenseElements = fixedDependencyElement.getLicenses(); + assertThat(fixedLicenseElements).containsOnly( + new LicenseElement("Test License Name", "http://test-license.com", "http://test-license.com")); + + verify(mockLicenseSanitiser, times(0)).fix(any()); + } + + @Test + public void shouldFixLicenseUrlWithAliasAndNullName() { + LicenseElement licenseElement = new LicenseElement( + null, + "http://test-license-alias.com", + "http://text-url.com"); + DependencyElement dependencyElement = new DependencyElement("", "", "", Collections.singleton(licenseElement)); + + DependencyElement fixedDependencyElement = aliasLicenseSanitiser.fix(dependencyElement); + + assertThat(fixedDependencyElement).isEqualTo(dependencyElement); + assertThat(fixedDependencyElement.getLicenses()).hasSize(1); + + Collection fixedLicenseElements = fixedDependencyElement.getLicenses(); + assertThat(fixedLicenseElements).containsOnly( + new LicenseElement("Test License Name", "http://test-license.com", "http://test-license.com")); + + verify(mockLicenseSanitiser, times(0)).fix(any()); + } + + @Test + public void shouldFixTwoLicenses() { + List licenseElements = Arrays.asList( + new LicenseElement("Test License Alias", "http://test-license-alias.com", "http://text-url.com"), + new LicenseElement("Test License Alias 2", "http://test-license-alias-2.com", "http://text-url.com")); + + DependencyElement dependencyElement = new DependencyElement("", "", "", new HashSet<>(licenseElements)); + DependencyElement fixedDependencyElement = aliasLicenseSanitiser.fix(dependencyElement); + + assertThat(fixedDependencyElement).isEqualTo(dependencyElement); + assertThat(fixedDependencyElement.getLicenses()).hasSize(2); + + Collection fixedLicenseElements = fixedDependencyElement.getLicenses(); + assertThat(fixedLicenseElements).containsOnly( + new LicenseElement("Test License Name", "http://test-license.com", "http://test-license.com"), + new LicenseElement("Test License Name 2", "http://test-license-2.com", "http://test-license-2.com")); + + verify(mockLicenseSanitiser, times(0)).fix(any()); + } + + @Test + public void shouldFixOneLicenseAndDelegate() { + when(mockLicenseSanitiser.fix(any(DependencyElement.class))).then(a -> a.getArgument(0)); + + List licenseElements = Arrays.asList( + new LicenseElement("Test License Alias", "http://test-license-alias.com"), + new LicenseElement("Unknown name", "http://unknown.com") + ); + + DependencyElement dependencyElement = new DependencyElement("", "", "", new HashSet<>(licenseElements)); + DependencyElement fixedDependencyElement = aliasLicenseSanitiser.fix(dependencyElement); + + assertThat(fixedDependencyElement).isEqualTo(dependencyElement); + assertThat(fixedDependencyElement.getLicenses()).hasSize(2); + + Collection fixedLicenseElements = fixedDependencyElement.getLicenses(); + assertThat(fixedLicenseElements).containsOnly( + new LicenseElement("Test License Name", "http://test-license.com", "http://test-license.com"), + new LicenseElement("Unknown name", "http://unknown.com", "http://unknown.com")); + + verify(mockLicenseSanitiser, times(1)).fix(any()); + } + + @Test + public void shouldDelegateUnknownLicense() { + LicenseElement licenseElement = new LicenseElement("Unknown name", "http://unknown.com"); + DependencyElement dependencyElement = new DependencyElement("", "", "", Collections.singleton(licenseElement)); + + DependencyElement fixedDependencyElement = aliasLicenseSanitiser.fix(dependencyElement); + + assertThat(fixedDependencyElement).isNull(); + + verify(mockLicenseSanitiser).fix(dependencyElement); + } + + @Test + public void shouldUseTextUrl() { + Set licenseElements = Collections + .singleton(new LicenseElement("Test License Name 3", "wrong-url")); + + DependencyElement dependencyElement = new DependencyElement("", "", "", licenseElements); + DependencyElement fixedDependencyElement = aliasLicenseSanitiser.fix(dependencyElement); + + assertThat(fixedDependencyElement).isEqualTo(dependencyElement); + assertThat(fixedDependencyElement.getLicenses()).hasSize(1); + + Collection fixedLicenseElements = fixedDependencyElement.getLicenses(); + assertThat(fixedLicenseElements).containsOnly( + new LicenseElement( + "Test License Name 3", + "http://test-license-3.com/licens.html", + "http://internal-host/license3.txt")); + + verify(mockLicenseSanitiser, times(0)).fix(any()); + } + +} diff --git a/licenses-generator/src/test/java/org/jboss/pnc/bacon/licenses/sanitiser/ExceptionLicenseSanitiserTest.java b/licenses-generator/src/test/java/org/jboss/pnc/bacon/licenses/sanitiser/ExceptionLicenseSanitiserTest.java new file mode 100644 index 000000000..28c4b2714 --- /dev/null +++ b/licenses-generator/src/test/java/org/jboss/pnc/bacon/licenses/sanitiser/ExceptionLicenseSanitiserTest.java @@ -0,0 +1,127 @@ +package org.jboss.pnc.bacon.licenses.sanitiser; + +import org.jboss.pnc.bacon.licenses.xml.DependencyElement; +import org.jboss.pnc.bacon.licenses.xml.LicenseElement; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.util.Collection; +import java.util.Collections; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +/** + * @author Gytis Trikleris + */ +public class ExceptionLicenseSanitiserTest { + + @Mock + private LicenseSanitiser mockLicenseSanitiser; + + private ExceptionLicenseSanitiser exceptionLicenseSanitiser; + + @BeforeEach + public void before() { + MockitoAnnotations.initMocks(this); + + exceptionLicenseSanitiser = new ExceptionLicenseSanitiser("rh-license-exceptions.json", mockLicenseSanitiser); + } + + @Test + public void shouldFixDependencyWithSingleLicense() { + DependencyElement dependencyElement = new DependencyElement( + "testGroupId", + "testArtifactId", + "testVersion", + Collections.emptySet()); + + DependencyElement fixedDependencyElement = exceptionLicenseSanitiser.fix(dependencyElement); + + assertThat(fixedDependencyElement).isEqualTo(dependencyElement); + assertThat(fixedDependencyElement.getLicenses()).hasSize(1); + + Collection fixedLicenseElements = fixedDependencyElement.getLicenses(); + assertThat(fixedLicenseElements) + .containsOnly(new LicenseElement("Test License Name", "http://test-license.com")); + + verify(mockLicenseSanitiser, times(0)).fix(any()); + } + + @Test + public void shouldFixDependencyWithTwoLicenses() { + DependencyElement dependencyElement = new DependencyElement( + "testGroupId2", + "testArtifactId2", + "testVersion2", + Collections.emptySet()); + + DependencyElement fixedDependencyElement = exceptionLicenseSanitiser.fix(dependencyElement); + + assertThat(fixedDependencyElement).isEqualTo(dependencyElement); + assertThat(fixedDependencyElement.getLicenses()).hasSize(2); + + Collection fixedLicenseElements = fixedDependencyElement.getLicenses(); + assertThat(fixedLicenseElements).containsOnly( + new LicenseElement("Test License Name", "http://test-license.com"), + new LicenseElement("Test License Name 2", "http://test-license-2.com")); + + verify(mockLicenseSanitiser, times(0)).fix(any()); + } + + @Test + public void shouldFixDependencyFallingIntoVersionRange() { + DependencyElement dependencyElement = new DependencyElement( + "testGroupId3", + "testArtifactId3", + "1.5.0", + Collections.emptySet()); + + DependencyElement fixedDependencyElement = exceptionLicenseSanitiser.fix(dependencyElement); + + assertThat(fixedDependencyElement).isEqualTo(dependencyElement); + assertThat(fixedDependencyElement.getLicenses()).hasSize(1); + + Collection fixedLicenseElements = fixedDependencyElement.getLicenses(); + assertThat(fixedLicenseElements) + .containsOnly(new LicenseElement("Test License Name", "http://test-license.com")); + + verify(mockLicenseSanitiser, times(0)).fix(any()); + } + + @Test + public void shouldFixDependencyMatchingVersionRegexp() { + DependencyElement dependencyElement = new DependencyElement( + "testGroupId4", + "testArtifactId4", + "1.0.0-redhat-1", + Collections.emptySet()); + + DependencyElement fixedDependencyElement = exceptionLicenseSanitiser.fix(dependencyElement); + + assertThat(fixedDependencyElement).isEqualTo(dependencyElement); + assertThat(fixedDependencyElement.getLicenses()).hasSize(1); + + Collection fixedLicenseElements = fixedDependencyElement.getLicenses(); + assertThat(fixedLicenseElements) + .containsOnly(new LicenseElement("Test License Name", "http://test-license.com")); + + verify(mockLicenseSanitiser, times(0)).fix(any()); + } + + @Test + public void shouldDelegateUnknownLicense() { + DependencyElement dependencyElement = new DependencyElement("", "", "", Collections.emptySet()); + + DependencyElement fixedDependencyElement = exceptionLicenseSanitiser.fix(dependencyElement); + + assertThat(fixedDependencyElement).isNull(); + + verify(mockLicenseSanitiser).fix(dependencyElement); + } + +} diff --git a/licenses-generator/src/test/java/org/jboss/pnc/bacon/licenses/sanitiser/NoopLicenseSanitiserTest.java b/licenses-generator/src/test/java/org/jboss/pnc/bacon/licenses/sanitiser/NoopLicenseSanitiserTest.java new file mode 100644 index 000000000..5a4581c6e --- /dev/null +++ b/licenses-generator/src/test/java/org/jboss/pnc/bacon/licenses/sanitiser/NoopLicenseSanitiserTest.java @@ -0,0 +1,30 @@ +package org.jboss.pnc.bacon.licenses.sanitiser; + +import org.jboss.pnc.bacon.licenses.xml.DependencyElement; +import org.jboss.pnc.bacon.licenses.xml.LicenseElement; +import org.junit.jupiter.api.Test; + +import java.util.Collections; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Gytis Trikleris + */ +public class NoopLicenseSanitiserTest { + + @Test + public void shouldDoNothing() { + NoopLicenseSanitiser sanitiser = new NoopLicenseSanitiser(); + DependencyElement dependencyElement = new DependencyElement( + "testGroupId", + "testArtifactId", + "testVersion", + Collections.singleton(new LicenseElement("testLicenseName", "testLicenseUrl"))); + + DependencyElement sanitisedDependencyElement = sanitiser.fix(dependencyElement); + + assertThat(sanitisedDependencyElement).isEqualTo(dependencyElement); + assertThat(sanitisedDependencyElement.getLicenses()).isEqualTo(dependencyElement.getLicenses()); + } +} diff --git a/licenses-generator/src/test/java/org/jboss/pnc/bacon/licenses/sanitiser/RedHatLicenseTest.java b/licenses-generator/src/test/java/org/jboss/pnc/bacon/licenses/sanitiser/RedHatLicenseTest.java new file mode 100644 index 000000000..32047512f --- /dev/null +++ b/licenses-generator/src/test/java/org/jboss/pnc/bacon/licenses/sanitiser/RedHatLicenseTest.java @@ -0,0 +1,85 @@ +package org.jboss.pnc.bacon.licenses.sanitiser; + +import org.jboss.pnc.bacon.licenses.xml.LicenseElement; +import org.junit.jupiter.api.Test; + +import javax.json.Json; +import javax.json.JsonObject; + +import java.util.Arrays; + +import static org.assertj.core.api.Assertions.assertThat; + +public class RedHatLicenseTest { + + private static JsonObject LICENSE_WITH_ALIASES = Json.createObjectBuilder() + .add("name", "Apache License 2.0") + .add("url", "http://www.apache.org/licenses/LICENSE-2.0") + .add("textUrl", "http://www.apache.org/licenses/LICENSE-2.0.txt") + .add("aliases", Json.createArrayBuilder(Arrays.asList("Apache License", " ASL 2.0 "))) + .add( + "urlAliases", + Json.createArrayBuilder( + Arrays.asList( + "http://www.apache.org/licenses/LICENSE-2.0/", + "https://apache.org/licenses/LICENSE-2.0", + "www.apache.org/licenses/LICENSE-2.0.txt "))) + .build(); + + private static JsonObject LICENSE_WITHOUT_ALIASES = Json.createObjectBuilder() + .add("name", "MIT License") + .add("url", "https://opensource.org/licenses/MIT") + .build(); + + @Test + public void shouldLoadSanitisedData() { + RedHatLicense redHatLicense = new RedHatLicense(LICENSE_WITH_ALIASES); + assertThat(redHatLicense.getName()).isEqualTo("Apache License 2.0"); + assertThat(redHatLicense.getUrl()).isEqualTo("http://www.apache.org/licenses/LICENSE-2.0"); + assertThat(redHatLicense.getTextUrl()).isEqualTo("http://www.apache.org/licenses/LICENSE-2.0.txt"); + assertThat(redHatLicense.getAliases()).containsOnly("apache license", "asl 2.0"); + assertThat(redHatLicense.getUrlAliases()) + .containsOnly("apache.org/licenses/license-2.0", "apache.org/licenses/license-2.0.txt"); + + redHatLicense = new RedHatLicense(LICENSE_WITHOUT_ALIASES); + assertThat(redHatLicense.getName()).isEqualTo("MIT License"); + assertThat(redHatLicense.getUrl()).isEqualTo("https://opensource.org/licenses/MIT"); + assertThat(redHatLicense.getTextUrl()).isEqualTo("https://opensource.org/licenses/MIT"); + assertThat(redHatLicense.getAliases()).isEmpty(); + assertThat(redHatLicense.getUrlAliases()).isEmpty(); + } + + @Test + public void shouldGetLicenseElement() { + RedHatLicense redHatLicense = new RedHatLicense(LICENSE_WITH_ALIASES); + LicenseElement licenseElement = redHatLicense.toLicenseElement(); + + assertThat(licenseElement.getName()).isEqualTo("Apache License 2.0"); + assertThat(licenseElement.getUrl()).isEqualTo("http://www.apache.org/licenses/LICENSE-2.0"); + assertThat(licenseElement.getTextUrl()).isEqualTo("http://www.apache.org/licenses/LICENSE-2.0.txt"); + } + + @Test + public void shouldRecogniseNameAlias() { + RedHatLicense redHatLicense = new RedHatLicense(LICENSE_WITH_ALIASES); + LicenseElement licenseElement = new LicenseElement("APACHE LICENSE", "example.com"); + + assertThat(redHatLicense.isAliasTo(licenseElement)).isTrue(); + } + + @Test + public void shouldRecogniseUrlAlias() { + RedHatLicense redHatLicense = new RedHatLicense(LICENSE_WITH_ALIASES); + LicenseElement licenseElement = new LicenseElement("Example", "https://apache.org/licenses/LICENSE-2.0/"); + + assertThat(redHatLicense.isAliasTo(licenseElement)).isTrue(); + } + + @Test + public void shouldNotRecognisedUnknownLicense() { + RedHatLicense redHatLicense = new RedHatLicense(LICENSE_WITH_ALIASES); + LicenseElement licenseElement = new LicenseElement("Example", "example.com"); + + assertThat(redHatLicense.isAliasTo(licenseElement)).isFalse(); + } +} diff --git a/licenses-generator/src/test/java/org/jboss/pnc/bacon/licenses/sanitiser/exceptions/ExactVersionMatcherTest.java b/licenses-generator/src/test/java/org/jboss/pnc/bacon/licenses/sanitiser/exceptions/ExactVersionMatcherTest.java new file mode 100644 index 000000000..7a6ecbf1e --- /dev/null +++ b/licenses-generator/src/test/java/org/jboss/pnc/bacon/licenses/sanitiser/exceptions/ExactVersionMatcherTest.java @@ -0,0 +1,29 @@ +package org.jboss.pnc.bacon.licenses.sanitiser.exceptions; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class ExactVersionMatcherTest { + private VersionMatcher matcher = new ExactVersionMatcher("1.0.0"); + + @Test + public void matchingString() throws Exception { + assertThat(matcher.matches("1.0.0")).isTrue(); + } + + @Test + public void nonmatchingString() throws Exception { + assertThat(matcher.matches("2.0.0")).isFalse(); + } + + @Test + public void nullString() throws Exception { + assertThat(matcher.matches(null)).isFalse(); + } + + @Test + public void whitespaceDifference() throws Exception { + assertThat(matcher.matches("1.0.0 ")).isFalse(); + } +} diff --git a/licenses-generator/src/test/java/org/jboss/pnc/bacon/licenses/sanitiser/exceptions/RangeVersionMatcherTest.java b/licenses-generator/src/test/java/org/jboss/pnc/bacon/licenses/sanitiser/exceptions/RangeVersionMatcherTest.java new file mode 100644 index 000000000..0e5982915 --- /dev/null +++ b/licenses-generator/src/test/java/org/jboss/pnc/bacon/licenses/sanitiser/exceptions/RangeVersionMatcherTest.java @@ -0,0 +1,63 @@ +package org.jboss.pnc.bacon.licenses.sanitiser.exceptions; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class RangeVersionMatcherTest { + @Test + public void singleVersion() throws Exception { + VersionMatcher matcher = new RangeVersionMatcher("1.0.0"); + assertThat(matcher.matches("1.0.0")).isTrue(); + assertThat(matcher.matches("1.0.0-redhat")).isFalse(); + assertThat(matcher.matches("2.0.0")).isFalse(); + } + + @Test + public void lowerBoundInclusive_upperBoundInclusive() throws Exception { + VersionMatcher matcher = new RangeVersionMatcher("[1.0.0, 2.0.0]"); + assertThat(matcher.matches("0.5.0")).isFalse(); + assertThat(matcher.matches("1.0.0")).isTrue(); + assertThat(matcher.matches("1.0.0-redhat")).isTrue(); + assertThat(matcher.matches("1.5.0")).isTrue(); + assertThat(matcher.matches("2.0.0")).isTrue(); + assertThat(matcher.matches("2.0.0-redhat")).isFalse(); + assertThat(matcher.matches("2.5.0")).isFalse(); + } + + @Test + public void lowerBoundExclusive_upperBoundInclusive() throws Exception { + VersionMatcher matcher = new RangeVersionMatcher("(1.0.0, 2.0.0]"); + assertThat(matcher.matches("0.5.0")).isFalse(); + assertThat(matcher.matches("1.0.0")).isFalse(); + assertThat(matcher.matches("1.0.0-redhat")).isTrue(); + assertThat(matcher.matches("1.5.0")).isTrue(); + assertThat(matcher.matches("2.0.0")).isTrue(); + assertThat(matcher.matches("2.0.0-redhat")).isFalse(); + assertThat(matcher.matches("2.5.0")).isFalse(); + } + + @Test + public void lowerBoundInclusive_upperBoundExclusive() throws Exception { + VersionMatcher matcher = new RangeVersionMatcher("[1.0.0, 2.0.0)"); + assertThat(matcher.matches("0.5.0")).isFalse(); + assertThat(matcher.matches("1.0.0")).isTrue(); + assertThat(matcher.matches("1.0.0-redhat")).isTrue(); + assertThat(matcher.matches("1.5.0")).isTrue(); + assertThat(matcher.matches("2.0.0")).isFalse(); + assertThat(matcher.matches("2.0.0-redhat")).isFalse(); + assertThat(matcher.matches("2.5.0")).isFalse(); + } + + @Test + public void lowerBoundExclusive_upperBoundExclusive() throws Exception { + VersionMatcher matcher = new RangeVersionMatcher("(1.0.0, 2.0.0)"); + assertThat(matcher.matches("0.5.0")).isFalse(); + assertThat(matcher.matches("1.0.0")).isFalse(); + assertThat(matcher.matches("1.0.0-redhat")).isTrue(); + assertThat(matcher.matches("1.5.0")).isTrue(); + assertThat(matcher.matches("2.0.0")).isFalse(); + assertThat(matcher.matches("2.0.0-redhat")).isFalse(); + assertThat(matcher.matches("2.5.0")).isFalse(); + } +} diff --git a/licenses-generator/src/test/java/org/jboss/pnc/bacon/licenses/sanitiser/exceptions/RegexpVersionMatcherTest.java b/licenses-generator/src/test/java/org/jboss/pnc/bacon/licenses/sanitiser/exceptions/RegexpVersionMatcherTest.java new file mode 100644 index 000000000..64fe5a60a --- /dev/null +++ b/licenses-generator/src/test/java/org/jboss/pnc/bacon/licenses/sanitiser/exceptions/RegexpVersionMatcherTest.java @@ -0,0 +1,31 @@ +package org.jboss.pnc.bacon.licenses.sanitiser.exceptions; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class RegexpVersionMatcherTest { + private VersionMatcher matcher = new RegexpVersionMatcher("1.0.0(-redhat-\\d+)?"); + + @Test + public void matchingString() throws Exception { + assertThat(matcher.matches("1.0.0")).isTrue(); + assertThat(matcher.matches("1.0.0-redhat-1")).isTrue(); + assertThat(matcher.matches("1.0.0-redhat-999")).isTrue(); + } + + @Test + public void nonmatchingString() throws Exception { + assertThat(matcher.matches("2.0.0")).isFalse(); + } + + @Test + public void nullString() throws Exception { + assertThat(matcher.matches(null)).isFalse(); + } + + @Test + public void whitespaceDifference() throws Exception { + assertThat(matcher.matches("1.0.0 ")).isFalse(); + } +} diff --git a/licenses-generator/src/test/java/org/jboss/pnc/bacon/licenses/xml/LicenseSummaryTest.java b/licenses-generator/src/test/java/org/jboss/pnc/bacon/licenses/xml/LicenseSummaryTest.java new file mode 100644 index 000000000..f32b5c08d --- /dev/null +++ b/licenses-generator/src/test/java/org/jboss/pnc/bacon/licenses/xml/LicenseSummaryTest.java @@ -0,0 +1,59 @@ +package org.jboss.pnc.bacon.licenses.xml; + +import org.junit.jupiter.api.Test; + +import javax.xml.bind.JAXBException; + +import java.util.Collections; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Gytis Trikleris + */ +public class LicenseSummaryTest { + + @Test + public void shouldGetDependencies() { + DependencyElement dependency = new DependencyElement("testG", "testA", "testV", Collections.emptySet()); + LicenseSummary summary = new LicenseSummary(Collections.singletonList(dependency)); + assertThat(summary.getDependencies()).containsOnly(dependency); + } + + @Test + public void shouldSetDependencies() { + DependencyElement dependency = new DependencyElement("testG", "testA", "testV", Collections.emptySet()); + LicenseSummary summary = new LicenseSummary(); + assertThat(summary.getDependencies()).isEmpty(); + + summary.setDependencies(Collections.singletonList(dependency)); + assertThat(summary.getDependencies()).containsOnly(dependency); + } + + @Test + public void shouldGetXmlWithoutLicenses() throws JAXBException { + DependencyElement dependency = new DependencyElement("testG", "testA", "testV", Collections.emptySet()); + LicenseSummary summary = new LicenseSummary(Collections.singletonList(dependency)); + String xml = summary.toXmlString(); + assertThat(xml).isXmlEqualTo( + "" + "" + "" + + "" + "testG" + "testA" + + "testV" + "" + "" + "" + + ""); + } + + @Test + public void shouldGetXmlWithLicense() throws JAXBException { + LicenseElement license = new LicenseElement("licenseName", "licenseUrl"); + DependencyElement dependency = new DependencyElement("testG", "testA", "testV", Collections.singleton(license)); + LicenseSummary summary = new LicenseSummary(Collections.singletonList(dependency)); + String xml = summary.toXmlString(); + assertThat(xml).isXmlEqualTo( + "" + "" + "" + + "" + "testG" + "testA" + + "testV" + "" + "" + "licenseName" + + "licenseUrl" + "" + "" + "" + "" + + ""); + } + +} diff --git a/licenses-generator/src/test/resources/rh-license-exceptions.json b/licenses-generator/src/test/resources/rh-license-exceptions.json new file mode 100644 index 000000000..0dac8fb09 --- /dev/null +++ b/licenses-generator/src/test/resources/rh-license-exceptions.json @@ -0,0 +1,72 @@ +[ + { + "groupId": "testGroupId", + "artifactId": "testArtifactId", + "version": "testVersion", + "licenses": [ + { + "name": "Test License Name", + "url": "http://test-license.com" + } + ] + }, + { + "groupId": "testGroupId2", + "artifactId": "testArtifactId2", + "version": "testVersion2", + "licenses": [ + { + "name": "Test License Name", + "url": "http://test-license.com" + }, + { + "name": "Test License Name 2", + "url": "http://test-license-2.com" + } + ] + }, + { + "groupId": "testGroupId3", + "artifactId": "testArtifactId3", + "version-range": "[1.0.0,2.0.0]", + "licenses": [ + { + "name": "Test License Name", + "url": "http://test-license.com" + } + ] + }, + { + "groupId": "testGroupId4", + "artifactId": "testArtifactId4", + "version-regexp": "1.0.0(-redhat-\\d+)?", + "licenses": [ + { + "name": "Test License Name", + "url": "http://test-license.com" + } + ] + }, + { + "groupId": "eap-unknown", + "artifactId": "artifact", + "version": "2.0.0-redhat-1", + "licenses": [ + { + "name": "Test License A", + "url": "http://test-license-a.com" + } + ] + }, + { + "groupId": "eap-unknown", + "artifactId": "artifact", + "version": "1.0", + "licenses": [ + { + "name": "Test License B", + "url": "http://test-license-b.com" + } + ] + } +] diff --git a/licenses-generator/src/test/resources/rh-license-names.json b/licenses-generator/src/test/resources/rh-license-names.json new file mode 100644 index 000000000..30219a6ef --- /dev/null +++ b/licenses-generator/src/test/resources/rh-license-names.json @@ -0,0 +1,33 @@ +[ + { + "name": "Test License Name", + "url": "http://test-license.com", + "aliases": [ + "Test License Alias" + ], + "urlAliases": [ + "http://test-license-alias.com" + ] + }, + { + "name": "Test License Name 2", + "url": "http://test-license-2.com", + "aliases": [ + "Test License Alias 2" + ], + "urlAliases": [ + "http://test-license-alias-2.com" + ] + }, + { + "name": "Test License Name 3", + "url": "http://test-license-3.com/licens.html", + "textUrl": "http://internal-host/license3.txt", + "aliases": [ + "Test License Name 3" + ], + "urlAliases": [ + "http://test-license-3.com/licens.html" + ] + } +] diff --git a/licenses-generator/src/test/resources/test-pom-with-exceptions.xml b/licenses-generator/src/test/resources/test-pom-with-exceptions.xml new file mode 100644 index 000000000..19e7c3091 --- /dev/null +++ b/licenses-generator/src/test/resources/test-pom-with-exceptions.xml @@ -0,0 +1,23 @@ + + 4.0.0 + + test + test + 1.0 + + + + + junit + junit + 4.12 + + + org.apache.tomcat + servlet-api + 6.0.41 + + + diff --git a/licenses-generator/src/test/resources/test-pom.xml b/licenses-generator/src/test/resources/test-pom.xml new file mode 100644 index 000000000..e1fc5bd9b --- /dev/null +++ b/licenses-generator/src/test/resources/test-pom.xml @@ -0,0 +1,17 @@ + + 4.0.0 + + test + test + 1.0 + + + + junit + junit + 4.12 + + + diff --git a/licenses-generator/src/test/resources/test_properties/empty.properties b/licenses-generator/src/test/resources/test_properties/empty.properties new file mode 100644 index 000000000..e69de29bb diff --git a/licenses-generator/src/test/resources/test_properties/modified.properties b/licenses-generator/src/test/resources/test_properties/modified.properties new file mode 100644 index 000000000..a0be118e6 --- /dev/null +++ b/licenses-generator/src/test/resources/test_properties/modified.properties @@ -0,0 +1,3 @@ +repository.names=testRepositoryName1,testRepositoryName2 +repository.urls=testRepositoryUrl1,testRepositoryUrl2 +licenseServiceUrl=http://10.10.10.10/find-license-check-record diff --git a/licenses-generator/src/test/resources/test_properties/wrong-repositories.properties b/licenses-generator/src/test/resources/test_properties/wrong-repositories.properties new file mode 100644 index 000000000..503ecf53c --- /dev/null +++ b/licenses-generator/src/test/resources/test_properties/wrong-repositories.properties @@ -0,0 +1 @@ +repository.urls=testRepositoryUrl1,testRepositoryUrl2 diff --git a/pig/pom.xml b/pig/pom.xml index d63b6bf0d..37c4fc881 100644 --- a/pig/pom.xml +++ b/pig/pom.xml @@ -59,7 +59,7 @@ org.eclipse.sisu.inject - me.snowdrop + org.jboss.pnc.bacon licenses-generator diff --git a/pig/src/main/java/org/jboss/pnc/bacon/pig/impl/license/LicenseGenerator.java b/pig/src/main/java/org/jboss/pnc/bacon/pig/impl/license/LicenseGenerator.java index b7ab2ae52..1c5e66e92 100644 --- a/pig/src/main/java/org/jboss/pnc/bacon/pig/impl/license/LicenseGenerator.java +++ b/pig/src/main/java/org/jboss/pnc/bacon/pig/impl/license/LicenseGenerator.java @@ -18,12 +18,12 @@ package org.jboss.pnc.bacon.pig.impl.license; -import me.snowdrop.licenses.LicensesGenerator; -import me.snowdrop.licenses.LicensesGeneratorException; -import me.snowdrop.licenses.properties.GeneratorProperties; -import me.snowdrop.licenses.utils.Gav; import org.jboss.pnc.bacon.config.Config; import org.jboss.pnc.bacon.config.PigConfig; +import org.jboss.pnc.bacon.licenses.LicensesGenerator; +import org.jboss.pnc.bacon.licenses.LicensesGeneratorException; +import org.jboss.pnc.bacon.licenses.properties.GeneratorProperties; +import org.jboss.pnc.bacon.licenses.utils.Gav; import org.jboss.pnc.bacon.pig.impl.PigContext; import org.jboss.pnc.bacon.pig.impl.utils.FileUtils; import org.jboss.pnc.bacon.pig.impl.utils.GAV; diff --git a/pom.xml b/pom.xml index 81ab51809..a28226c1a 100644 --- a/pom.xml +++ b/pom.xml @@ -59,6 +59,7 @@ common config da + licenses-generator pig pnc experimental @@ -74,13 +75,23 @@ + 3.21.0 + 1.9.4 + 2.7 + 2.7 3.8.1 0.0.102 + 2.3.1 + 1.1.4 2.13.1 2.2.11 + + 3.15 + 1.1.4 5.8.2 3.8.1 1.6.3 + 3.5.3 11 11 @@ -92,8 +103,12 @@ 2.5.0 UTF-8 - 2.16.12.Final + ${quarkus.version} + 2.16.12.Final + ${quarkus.version} + + 2.2.8.Final @@ -130,6 +145,11 @@ da ${project.version} + + org.jboss.pnc.bacon + licenses-generator + ${project.version} + org.jboss.pnc.bacon pig @@ -210,11 +230,86 @@ org.jboss.resteasy resteasy-client 3.14.0.Final + + + com.sun.activation + jakarta.activation + + + org.jboss.spec.javax.xml.bind + jboss-jaxb-api_2.3_spec + + org.jboss.resteasy resteasy-jackson2-provider 3.12.1.Final + + + jakarta.activation + jakarta.activation-api + + + + + + + org.apache.commons + commons-configuration2 + ${commons-configuration2.version} + + + commons-logging + commons-logging + + + + + commons-beanutils + commons-beanutils + ${commons-beanutils.version} + + + commons-logging + commons-logging + + + + + commons-io + commons-io + ${commons-io.version} + + + io.quarkus.qute + qute-core + ${qute.version} + + + org.jenkins-ci.lib + lib-jenkins-maven-embedder + ${jenkins-maven-embedder.version} + + + javax.annotation + jsr250-api + + + org.apache.maven + * + + + + + org.glassfish.jaxb + jaxb-runtime + ${glassfish-jaxb.version} + + + org.glassfish + javax.json + ${glassfish-json.version} @@ -323,11 +418,6 @@ org.eclipse.jgit 6.6.1.202309021850-r - - me.snowdrop - licenses-generator - 1.2.0 - org.jboss.pnc.build.finder core @@ -540,6 +630,26 @@ maven-resolver-transport-wagon ${maven-resolver.version} + + org.apache.maven.wagon + wagon-file + ${maven-wagon.version} + + + org.apache.maven.wagon + wagon-http + ${maven-wagon.version} + + + org.slf4j + slf4j-api + + + commons-io + commons-io + + + org.eclipse.sisu org.eclipse.sisu.inject @@ -569,6 +679,17 @@ hadoop-hdfs-client 3.3.4 + + io.undertow + undertow-servlet + ${undertow.version} + + + org.jboss.spec.javax.annotation + jboss-annotations-api_1.3_spec + + + org.projectlombok @@ -605,7 +726,7 @@ org.assertj assertj-core - 3.21.0 + ${assertj.version} test