diff --git a/.asf.yaml b/.asf.yaml new file mode 100644 index 000000000..8896f727f --- /dev/null +++ b/.asf.yaml @@ -0,0 +1,11 @@ +github: + description: "Apache Creadur RAT - Release Audit Tool" + homepage: https://creadur.apache.org/ + labels: + - maven + - java + - cli + - licensechecker + - apache + - creadur + - rat diff --git a/.buildtools/formatPom b/.buildtools/formatPom new file mode 100755 index 000000000..484b8a5f9 --- /dev/null +++ b/.buildtools/formatPom @@ -0,0 +1,20 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You 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. +# +for pom in `find . -name \pom.xml` +do + xmllint --format $pom > /tmp/w + mv /tmp/w $pom +done diff --git a/.buildtools/generateStagingSiteInWebpageRepo b/.buildtools/generateStagingSiteInWebpageRepo new file mode 100755 index 000000000..f870f6cc9 --- /dev/null +++ b/.buildtools/generateStagingSiteInWebpageRepo @@ -0,0 +1,17 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You 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. +# +mvn clean site:site site:stage +cp -rvf target/staging/* ../creadur-site/rat0161/ diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 852632387..516c09e33 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -33,24 +33,38 @@ jobs: # Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target # # Java 17 disabled, because we are running into https://bugs.openjdk.java.net/browse/JDK-8270866 - java: [8, 11, 12, 13, 14, 15, 16] + java: [8, 11, 12, 13, 14, 15, 16, 21] fail-fast: false runs-on: ${{ matrix.os }} steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 + + - name: Configura artifact caching + uses: actions/cache@v4.0.0 + with: + path: ~/.m2/repository + key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} + restore-keys: | + ${{ runner.os }}-maven- - name: Set up JDK - uses: actions/setup-java@v3.4.1 + uses: actions/setup-java@v4.0.0 with: distribution: adopt java-version: ${{ matrix.java }} cache: 'maven' - name: Build with Maven - run: mvn -e -B -V clean package site + run: ./mvnw -e -B -V -ntp clean install + + - name: Build site + run: ./mvnw -e -B -V -ntp site:site + + - name: Generate javadoc + run: ./mvnw -e -B -V -ntp javadoc:javadoc # as of 20220505: Invalid workflow file # The workflow is not valid. .github/workflows/maven.yml (Line: 55, Col: 1): Unexpected value 'notifications' diff --git a/.gitignore b/.gitignore index 25e619a33..6d7b8e738 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,4 @@ */.idea /target/ **/.gitignore +**/lib/ diff --git a/.mvn/maven.config b/.mvn/maven.config new file mode 100644 index 000000000..df145f3d4 --- /dev/null +++ b/.mvn/maven.config @@ -0,0 +1 @@ +-V diff --git a/.mvn/wrapper/maven-wrapper.jar b/.mvn/wrapper/maven-wrapper.jar new file mode 100644 index 000000000..cb28b0e37 Binary files /dev/null and b/.mvn/wrapper/maven-wrapper.jar differ diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 000000000..346d645fd --- /dev/null +++ b/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,18 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.6/apache-maven-3.9.6-bin.zip +wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 1b56d79bd..000000000 --- a/.travis.yml +++ /dev/null @@ -1,9 +0,0 @@ -language: java -dist: focal -sudo: required - -jobs: - include: - - name: "Java 16" - jdk: openjdk16 - script: mvn -e -B -V clean package site diff --git a/BUILD.txt b/BUILD.txt index 562bb7a9e..6ca6dc3d7 100644 --- a/BUILD.txt +++ b/BUILD.txt @@ -5,14 +5,17 @@ There is a maven default goal configured that builds and installs a fresh artifa or Normal development: - mvn install + mvn install OR + ./mvnw install Normal development without running tests: - mvn -Dmaven.test.skip=true install + mvn -Dmaven.test.skip=true install OR + ./mvnw -Dmaven.test.skip=true install Build apache release - mvn clean install -Papache-release + mvn clean install -Papache-release OR + ./mvnw clean install -Papache-release RAT uses the previos release version during the build to verify it complies its own rules. diff --git a/Jenkinsfile b/Jenkinsfile index 4ff77fb3b..dc08c1ce3 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -19,8 +19,8 @@ */ pipeline { -// agent { label 'ubuntu' } - agent any + agent { label 'ubuntu' } +// arm does not have JDK8 anymore: agent any environment { // It seems the login the jenkins slave uses, doesn't pick up the environment changes, @@ -78,14 +78,14 @@ pipeline { stage('Build Parent-pom') { steps { echo 'Building parent pom only' - sh 'mvn clean install -N -e -B' + sh './mvnw clean install -N -e -B' } } stage('Print available updates') { steps { echo 'Show available plugin and dependency updates' - sh 'mvn clean versions:display-dependency-updates versions:display-plugin-updates enforcer:display-info -U -B' + sh './mvnw clean versions:display-dependency-updates versions:display-plugin-updates -U -B' } } @@ -93,7 +93,7 @@ pipeline { steps { echo 'Building the whole project' // clean package -B -U -e -fae -V for making sure it just builds - sh 'mvn -B -U -V clean deploy' + sh './mvnw -B -U -V clean deploy' } post { always { @@ -106,7 +106,7 @@ pipeline { stage('Ensure site build works') { steps { echo 'Verify site build is okay ....' - sh 'mvn site:site' + sh './mvnw site:site' } } } diff --git a/NOTICE b/NOTICE index 2c2d58d97..c6b887455 100644 --- a/NOTICE +++ b/NOTICE @@ -1,5 +1,6 @@ Apache Creadur Rat -Copyright 2006-2021 The Apache Software Foundation +Copyright 2006-2024 The Apache Software Foundation +https://creadur.apache.org This product includes software developed at The Apache Software Foundation (https://www.apache.org/). diff --git a/README.md b/README.md index c32836205..177f6e9f7 100644 --- a/README.md +++ b/README.md @@ -2,12 +2,8 @@ ASF Jenkins: [![ASF Jenkins Build Status](https://ci-builds.apache.org/buildStatus/icon?job=Creadur%2FCreadur-Rat)](https://ci-builds.apache.org/job/Creadur/job/Creadur-Rat/) -Travis: [![Build Status](https://app.travis-ci.com/apache/creadur-rat.svg?branch=master)](https://app.travis-ci.com/apache/creadur-rat) - GA: [![Github Action master branch status](https://github.com/apache/creadur-rat/actions/workflows/maven.yml/badge.svg?branch=master)](https://github.com/apache/creadur-rat/actions) -Due to a bug in the Travis build infrastructure the builds fail regularly because Travis selects a JDK that fails animal-sniffer-plugin runs as it is not the one specified in the build. - ## What is RAT? Apache Rat is developed by the Apache Creadur project of the Apache Software diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt index b1d93d6b1..3168c5205 100644 --- a/RELEASE-NOTES.txt +++ b/RELEASE-NOTES.txt @@ -1,7 +1,7 @@ - Apache Creadur Rat 0.15 + Apache Creadur Rat 0.16 RELEASE NOTES -The Apache Creadur Rat team is pleased to announce the release of Apache Creadur Rat 0.15 +The Apache Creadur Rat team is pleased to announce the release of Apache Creadur Rat 0.16 Apache Rat is a release audit tool. It improves accuracy and efficiency when checking releases. It is heuristic in nature: making guesses about possible problems. It @@ -15,30 +15,59 @@ Note that binary compatibility is not guaranteed between 0.x releases. Apache Rat is developed by the Apache Creadur project, a language and build agnostic home for software distribution comprehension and audit tools. -This release fixes a warning during site builds and updates various dependencies. +Apart from dependency updates and multiple bugfixes, this release brings the ability to use SPDX license identifiers and enhances the .gitignore-exclusion filterung during RAT runs. +Furthermore new CLI options were added and new file types can be used by default. This release makes RAT a fully Maven3-compatible plugin and removes deprecated Maven2 completely. +Thanks to all new contributors for improving RAT! Changes in this version include: +New features: +o RAT-338: Update minimal build Maven version to 3.2.5 and maven dependencies to 3.9.6. Remove pre-JDK8 code constructs and minor refactorings. Thanks to Tamás Cservenák. +o RAT-335: Enhance .gitignore handling; support multiple .gitignore files and allow a more complete parsing of Git's ignore files. Thanks to Niels Basjes. +o RAT-322: Add configuration option to scan hidden directories: --scan-hidden-directories on the command line and scanHiddenDirectories as a Maven plugin parameter. Thanks to Jean-Baptiste Onofré. +o RAT-320: Add new command line option -o/--output to write RAT's output to a file. Thanks to Jean-Baptiste Onofré. +o RAT-329: Add markdown (MD) and yaml (YML/YAML) as a recognized extension for file and license processing. Thanks to Claude Warren. +o RAT-316: Add default exclusion of MANIFEST.MF as it must not contain comment lines to include a license. +o RAT-321: Allow text-based XML configuration of RAT. Thanks to Claude Warren. + Fixed Bugs: -o RAT-309: Site builds could not be generated properly due to API changes: solution was to upgrade Maven Reporting API to 3.1.1 and use details of Maven Reporting Implementation 3.2.0 in RAT's Mojo hierarchy. Thanks to Michael Osipov, Gary Gregory. -o RAT-309: Updated internal data structures from deprecated ArrayStack to JDK's ArrayDeque. -o RAT-306: Add note about hierarchy of changelogs in RAT project structure when publishing the project webpage. -o RAT-307: Update to focal (Ubuntu 20.04) on Travis to circumvent build errors and be able to use more modern JDK versions. Deprecate openJDK8 build with focal as it is not supported on Travis. +o RAT-326: Fix existing javadoc build errors and add javadoc generation to existing GithubActions to not introduce build errors via merge requests. +o RAT-328: Ensure that System.out does not get closed during report generation and updated javadocs. Thanks to Claude Warren. +o RAT-311: Update commons-compress to 1.24.0 in order to circumvent CVE-2023-42503. +o RAT-251: Added SPDX processing for default licenses. Thanks to Claude Warren. +o RAT-315: Fix warnings when using RAT with newer Maven versions as methods from Maven v2 are deprecated. Minimum version of required Maven changed to 3.2.5. Thanks to Guillaume Nodet. +o RAT-317: Change log output level of SCM ignore parser from info to debug in order to produce less log output in RAT runs. Thanks to Gary Gregory. +o RAT-314: Add default recursive exclusion for maven-induced build artifacts in folder .mvn. Thanks to François Guillot. +o RAT-312: Remove Travis build as it is unreliable. Builds with ASF Jenkins and Github Actions remain as before. Changes: -o RAT-305: Update maven-project-info-reports-plugin from 3.3.0 to 3.4.1. Thanks to dependabot. -o RAT-305: Update maven-javadoc-plugin from 3.4.0 to 3.4.1. Thanks to dependabot. -o RAT-305: Update maven-jxr-plugin from 3.2.0 to 3.3.0. Thanks to dependabot. -o RAT-305: Update animal-sniffer-maven-plugin from 1.21 to 1.22. Thanks to dependabot. -o RAT-305: Update maven-site-plugin from 3.12.0 to 3.12.1. Thanks to dependabot. -o RAT-305: Update maven-pmd-plugin from 3.16.0 to 3.18.0. Thanks to dependabot. -o RAT-305: Update mockito-core from 4.6.0 to 4.7.0. Thanks to dependabot. -o RAT-305: Update extra-enforcer-rules from 1.5.1 to 1.6.1. Thanks to dependabot. -o RAT-305: Update Apache parent pom from 26 to 27. Thanks to dependabot. -o RAT-305: Update wagon-ssh from 3.5.1 to 3.5.2. Thanks to dependabot. -o RAT-305: Update maven-enforcer-plugin from 3.0.0 to 3.1.0. Thanks to dependabot. -o RAT-305: Update actions/setup-java from 3.3.0 to 3.4.1. Thanks to dependabot. -o RAT-310: Fix deprecation warnings in tests. Use hamcrest's annotations instead of ones from JUnit. +o RAT-311: Update actions/setup-java from 3.4.1 to 4.0.0. Thanks to dependabot. +o RAT-311: Update actions/cache from 3.0.11 to 3.3.2 Thanks to dependabot. +o RAT-311: Update actions/checkout from 3 to 4. Thanks to dependabot. +o RAT-311: Update mockito-core from 4.7.0 to 4.11.0, newer versions 5.x cannot be applied due to our JDK8-compatibility restriction. Thanks to dependabot. +o RAT-311: Update plexus-utils from 3.4.2 to 3.5.1, versions 4.x are for upcoming Maven4 and must not be applied here. Thanks to dependabot. +o RAT-311: Update maven-plugin-version from 3.6.4 to 3.8.2. Thanks to dependabot. +o RAT-311: Update wagon-ssh from 3.5.2 to 3.5.3. Thanks to dependabot. +o RAT-311: Update Ant from 1.10.12 to 1.10.14. Thanks to dependabot. +o RAT-311: Update ASF parent pom from 27 to 31 and update multiple maven plugin versions implicitly (surefire, release, project-info, enforcer, jxr). Thanks to dependabot. +o RAT-311: Update doxiaVersion from 1.11.1 to 1.12.0. Thanks to dependabot. +o RAT-311: Update maven-shared-utils from 3.3.4 to 3.4.2. Thanks to dependabot. +o RAT-311: Update org.slf4j:slf4j-simple from 1.7.36 to 2.0.9. Thanks to dependabot. +o RAT-311: Update commons-lang3 from 3.5 to 3.14.0. Thanks to dependabot. +o RAT-311: Update commons-compress from 1.21 to 1.25. Thanks to dependabot. +o RAT-311: Update commons-io from 2.11.0 to 2.15.1. Thanks to dependabot. +o RAT-311: Update commons-cli from 1.5.0 to 1.6.0. Thanks to dependabot. +o RAT-311: Update maven-pmd-plugin from 3.18.0 to 3.21.2. Thanks to dependabot. +o RAT-311: Update maven-dependency-plugin from 3.3.0 to 3.6.1. Thanks to dependabot. +o RAT-311: Update maven-compiler-plugin from 3.10.1 to 3.12.1. Thanks to dependabot. +o RAT-311: Update maven-javadoc-plugin from 3.4.1 to 3.6.3. Thanks to dependabot. +o RAT-311: Update maven-release-plugin from 2.5.3 to 3.0.1. Thanks to dependabot. +o RAT-311: Update maven-enforcer-plugin from 3.1.0 to 3.4.1. Thanks to dependabot. +o RAT-311: Update extra-enforcer-rules from 1.6.1 to 1.7.0 Thanks to dependabot. +o RAT-311: Update maven-release-plugin from 2.5.3 to 3.0.1. Thanks to dependabot. +o RAT-311: Update animal-sniffer-maven-plugin from 1.22 to 1.23. Thanks to dependabot. +o RAT-311: Update maven-project-info-reports-plugin from 3.4.1 to 3.5.0. Thanks to dependabot. +o RAT-311: Update maven-surefire-plugin from 3.2.2 to 3.2.3. Thanks to dependabot. Historical list of changes: https://creadur.apache.org/rat/changes-report.html diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index c88e22a94..3fd8df1cb 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -1,3 +1,57 @@ +Rat 0.16 +======== +Apart from dependency updates and multiple bugfixes, this release brings the ability to use SPDX license identifiers and enhances the .gitignore-exclusion filterung during RAT runs. +Furthermore new CLI options were added and new file types can be used by default. This release makes RAT a fully Maven3-compatible plugin and removes deprecated Maven2 completely. +Thanks to all new contributors for improving RAT! + +New features: +o RAT-338: Update minimal build Maven version to 3.2.5 and maven dependencies to 3.9.6. Remove pre-JDK8 code constructs and minor refactorings. Thanks to Tamás Cservenák. +o RAT-335: Enhance .gitignore handling; support multiple .gitignore files and allow a more complete parsing of Git's ignore files. Thanks to Niels Basjes. +o RAT-322: Add configuration option to scan hidden directories: --scan-hidden-directories on the command line and scanHiddenDirectories as a Maven plugin parameter. Thanks to Jean-Baptiste Onofré. +o RAT-320: Add new command line option -o/--output to write RAT's output to a file. Thanks to Jean-Baptiste Onofré. +o RAT-329: Add markdown (MD) and yaml (YML/YAML) as a recognized extension for file and license processing. Thanks to Claude Warren. +o RAT-316: Add default exclusion of MANIFEST.MF as it must not contain comment lines to include a license. +o RAT-321: Allow text-based XML configuration of RAT. Thanks to Claude Warren. + +Fixed Bugs: +o RAT-326: Fix existing javadoc build errors and add javadoc generation to existing GithubActions to not introduce build errors via merge requests. +o RAT-328: Ensure that System.out does not get closed during report generation and updated javadocs. Thanks to Claude Warren. +o RAT-311: Update commons-compress to 1.24.0 in order to circumvent CVE-2023-42503. +o RAT-251: Added SPDX processing for default licenses. Thanks to Claude Warren. +o RAT-315: Fix warnings when using RAT with newer Maven versions as methods from Maven v2 are deprecated. Minimum version of required Maven changed to 3.2.5. Thanks to Guillaume Nodet. +o RAT-317: Change log output level of SCM ignore parser from info to debug in order to produce less log output in RAT runs. Thanks to Gary Gregory. +o RAT-314: Add default recursive exclusion for maven-induced build artifacts in folder .mvn. Thanks to François Guillot. +o RAT-312: Remove Travis build as it is unreliable. Builds with ASF Jenkins and Github Actions remain as before. + +Changes: +o RAT-311: Update actions/setup-java from 3.4.1 to 4.0.0. Thanks to dependabot. +o RAT-311: Update actions/cache from 3.0.11 to 3.3.2 Thanks to dependabot. +o RAT-311: Update actions/checkout from 3 to 4. Thanks to dependabot. +o RAT-311: Update mockito-core from 4.7.0 to 4.11.0, newer versions 5.x cannot be applied due to our JDK8-compatibility restriction. Thanks to dependabot. +o RAT-311: Update plexus-utils from 3.4.2 to 3.5.1, versions 4.x are for upcoming Maven4 and must not be applied here. Thanks to dependabot. +o RAT-311: Update maven-plugin-version from 3.6.4 to 3.8.2. Thanks to dependabot. +o RAT-311: Update wagon-ssh from 3.5.2 to 3.5.3. Thanks to dependabot. +o RAT-311: Update Ant from 1.10.12 to 1.10.14. Thanks to dependabot. +o RAT-311: Update ASF parent pom from 27 to 31 and update multiple maven plugin versions implicitly (surefire, release, project-info, enforcer, jxr). Thanks to dependabot. +o RAT-311: Update doxiaVersion from 1.11.1 to 1.12.0. Thanks to dependabot. +o RAT-311: Update maven-shared-utils from 3.3.4 to 3.4.2. Thanks to dependabot. +o RAT-311: Update org.slf4j:slf4j-simple from 1.7.36 to 2.0.9. Thanks to dependabot. +o RAT-311: Update commons-lang3 from 3.5 to 3.14.0. Thanks to dependabot. +o RAT-311: Update commons-compress from 1.21 to 1.25. Thanks to dependabot. +o RAT-311: Update commons-io from 2.11.0 to 2.15.1. Thanks to dependabot. +o RAT-311: Update commons-cli from 1.5.0 to 1.6.0. Thanks to dependabot. +o RAT-311: Update maven-pmd-plugin from 3.18.0 to 3.21.2. Thanks to dependabot. +o RAT-311: Update maven-dependency-plugin from 3.3.0 to 3.6.1. Thanks to dependabot. +o RAT-311: Update maven-compiler-plugin from 3.10.1 to 3.12.1. Thanks to dependabot. +o RAT-311: Update maven-javadoc-plugin from 3.4.1 to 3.6.3. Thanks to dependabot. +o RAT-311: Update maven-release-plugin from 2.5.3 to 3.0.1. Thanks to dependabot. +o RAT-311: Update maven-enforcer-plugin from 3.1.0 to 3.4.1. Thanks to dependabot. +o RAT-311: Update extra-enforcer-rules from 1.6.1 to 1.7.0 Thanks to dependabot. +o RAT-311: Update maven-release-plugin from 2.5.3 to 3.0.1. Thanks to dependabot. +o RAT-311: Update animal-sniffer-maven-plugin from 1.22 to 1.23. Thanks to dependabot. +o RAT-311: Update maven-project-info-reports-plugin from 3.4.1 to 3.5.0. Thanks to dependabot. +o RAT-311: Update maven-surefire-plugin from 3.2.2 to 3.2.3. Thanks to dependabot. + Rat 0.15 ======== This release fixes a warning during site builds and updates various dependencies. diff --git a/ant-task-examples.xml b/ant-task-examples.xml index 2a2ee699a..343f073b5 100644 --- a/ant-task-examples.xml +++ b/ant-task-examples.xml @@ -25,7 +25,7 @@ - + diff --git a/apache-rat-api/.gitignore b/apache-rat-api/.gitignore deleted file mode 100644 index 22e11310c..000000000 --- a/apache-rat-api/.gitignore +++ /dev/null @@ -1,19 +0,0 @@ -*.ipr -*.iws -/target/* -**/target/* -.svn -**/.svn -.project -*/.project -.classpath -*/.classpath -.settings -*/.settings -*.iml -*/*.iml -*/*.ipr -*/*.iws -.idea/* -*/.idea -/target/ diff --git a/apache-rat-api/src/main/java/org/apache/rat/api/domain/LicenseFamily.java b/apache-rat-api/src/main/java/org/apache/rat/api/domain/LicenseFamily.java deleted file mode 100644 index 187b7aa83..000000000 --- a/apache-rat-api/src/main/java/org/apache/rat/api/domain/LicenseFamily.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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.apache.rat.api.domain; - -/** - * Licenses are grouped into families. Each family has similar legal semantics, - * though some small details may differ. - *

- * For example, the 3 - * clause BSD license is in a family where members differ by <OWNER>, - * <ORGANIZATION> and <YEAR> parameters. - * - */ -public final class LicenseFamily { - - /** - * Further information associated with the license family. Human readable. - * Possibly null. - */ - private final String notes; - /** - * Names of the category containing this license family. Choosing a suitable - * URI is recommended. Possibly null; - */ - private final String category; - /** - * Uniquely identifies this family. Choosing a suitable URI is recommended. - * Not null. - */ - private final String name; - - /** - * Constructs an immutable license family. - * - * @param name - * the name uniquely identifying this family. Recommended that - * this be an URI. Not null. - * @param category - * the name of the category containing this license family. - * Recommended that this be an URI. Possibly null. - * @param notes - * further information associated with the license family. Human - * readable. Possibly null. - */ - public LicenseFamily(final String name, final String category, - final String notes) { - super(); - this.notes = notes; - this.category = category; - this.name = name; - } - - /** - * Gets further information associated with the license family. Human - * readable. - * - * @return possibly null - */ - public String getNotes() { - return this.notes; - } - - /** - * Gets the name of the category containing this license family. Recommended - * that this be an URI. - * - * @return possibly null - */ - public String getCategory() { - return this.category; - } - - /** - * Gets the name uniquely identifying this family. Recommended that this be - * an URI. - * - * @return not null - */ - public String getName() { - return this.name; - } - -} diff --git a/apache-rat-api/src/main/java/org/apache/rat/api/domain/LicenseFamilyBuilder.java b/apache-rat-api/src/main/java/org/apache/rat/api/domain/LicenseFamilyBuilder.java deleted file mode 100644 index 9d58a968b..000000000 --- a/apache-rat-api/src/main/java/org/apache/rat/api/domain/LicenseFamilyBuilder.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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.apache.rat.api.domain; - -/** - * Builds {@link LicenseFamily} instances. - */ -public final class LicenseFamilyBuilder { - - /** - * Begins to build a license family. - * - * @return a builder for a license family, not null - */ - public static LicenseFamilyBuilder aLicenseFamily() { - return new LicenseFamilyBuilder(); - } - - /** Further information associated with the license family. Human readable. */ - private String notes; - /** - * Names of the category containing this license family. Recommended that - * this be an URI. - */ - private String category; - /** Uniquely identifies this family. Choosing a suitable URI is recommended */ - private String name; - - /** Use {@link #aLicenseFamily() */ - private LicenseFamilyBuilder() { - } - - /** - * Builds a family. - * - * @return not null - */ - public LicenseFamily build() { - return new LicenseFamily(this.name, this.category, this.notes); - } - - /** - * Builds family with further information associated with the license - * family. Human readable. - * - * @param notes - * possibly null - * @return this instance, not null - */ - public LicenseFamilyBuilder withNotes(final String notes) { - this.notes = notes; - return this; - } - - /** - * Builds family with category containing this license family. Choosing a - * suitable URI is recommended - * - * @param category - * possible null - * @return this instance, not null - */ - public LicenseFamilyBuilder withCategory(final String category) { - this.category = category; - return this; - } - - /** - * - * Uniquely identifies this family. Choosing a suitable URI is recommended. - * - * @param name - * not null - * @return this instance, not null - */ - public LicenseFamilyBuilder withName(final String name) { - this.name = name; - return this; - } -} diff --git a/apache-rat-api/src/main/java/org/apache/rat/api/domain/RatLicenseFamily.java b/apache-rat-api/src/main/java/org/apache/rat/api/domain/RatLicenseFamily.java deleted file mode 100644 index 8f1f22307..000000000 --- a/apache-rat-api/src/main/java/org/apache/rat/api/domain/RatLicenseFamily.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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.apache.rat.api.domain; - -import static org.apache.rat.api.domain.LicenseFamilyBuilder.aLicenseFamily; - -/** - * Enumerates standard license families known to Rat. - */ -public enum RatLicenseFamily { - - APACHE( - "Apache License Version 2.0", - "AL ", - "Note that APACHE requires a NOTICE. All modifications require notes. See http://www.apache.org/licenses/LICENSE-2.0."), - GPL1( - "GNU General Public License, version 1", - "GPL1 ", - "Note that GPL1 requires a NOTICE. All modifications require notes. See http://www.gnu.org/licenses/gpl-1.0.html."), - GPL2( - "GNU General Public License, version 2", - "GPL2 ", - "Note that GPL2 requires a NOTICE. All modifications require notes. See http://www.gnu.org/licenses/gpl-2.0.html."), - GPL3( - "GNU General Public License, version 3", - "GPL3 ", - "Note that GPL3 requires a NOTICE. All modifications require notes. See http://www.gnu.org/licenses/gpl-3.0.html."), - MIT( - "The MIT License", - "MIT ", - "Note that MIT requires a NOTICE. All modifications require notes. See http://opensource.org/licenses/MIT."), - CDDL1( - "COMMON DEVELOPMENT AND DISTRIBUTION LICENSE Version 1.0", - "CDDL1", - "Note that CDDL1 requires a NOTICE. All modifications require notes. See https://oss.oracle.com/licenses/CDDL."), - OASIS( - "OASIS Open License", - "OASIS", - "Note that OASIS requires a NOTICE. All modifications require notes. See https://www.oasis-open.org/policies-guidelines/ipr."), - TMF854( - "Modified BSD License", - "TMF ", - "Note that TMF854 requires a NOTICE. All modifications require notes. See http://opensource.org/licenses/BSD-3-Clause."), - DOJO( - "Modified BSD License", - "DOJO ", - "Note that DOJO requires a NOTICE. All modifications require notes. See http://dojotoolkit.org/community/licensing.shtml."), - W3C( - "W3C Software Copyright", - "W3C ", - "Note that W3C requires a NOTICE. All modifications require notes. See http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231."), - - W3C_DOCUMENTATION( - "W3C Document Copyright", - "W3CD ", - "Note that W3CD does not allow modifications. See http://www.w3.org/Consortium/Legal/2002/copyright-documents-20021231."); - - /** @see LicenseFamily#getName() */ - private final String name; - /** @see LicenseFamily#getCategory() */ - private final String category; - /** @see LicenseFamily#getNotes() */ - private final String notes; - /** Constructed from other data */ - private final LicenseFamily licenseFamily; - - /** - * Constructs an instance. - * - * @param name - * not null - * @param category - * not null - * @param notes - * not null - */ - RatLicenseFamily(final String name, final String category, - final String notes) { - this.name = name; - this.category = category; - this.notes = notes; - this.licenseFamily = aLicenseFamily().withCategory(getCategory()) - .withName(getName()).withNotes(getNotes()).build(); - } - - /** - * @see LicenseFamily#getName() - * - * @return not null - */ - public String getName() { - return this.name; - } - - /** - * @see LicenseFamily#getCategory() - * - * @return possibly null - */ - public String getCategory() { - return this.category; - } - - /** - * @see LicenseFamily#getNotes() - * - * @return possibly null - */ - public String getNotes() { - return this.notes; - } - - /** - * Gets a {@link LicenseFamily} representing this data. - * - * @return not null - */ - public LicenseFamily licenseFamily() { - return this.licenseFamily; - } -} diff --git a/apache-rat-api/src/site/apt/index.apt.vm b/apache-rat-api/src/site/apt/index.apt.vm deleted file mode 100644 index 482070358..000000000 --- a/apache-rat-api/src/site/apt/index.apt.vm +++ /dev/null @@ -1,26 +0,0 @@ -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -~~ Licensed to the Apache Software Foundation (ASF) under one or more -~~ contributor license agreements. See the NOTICE file distributed with -~~ this work for additional information regarding copyright ownership. -~~ The ASF licenses this file to You 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. -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - -------------------------- - API Module - -------------------------- - -About Apache Rat API - - - The Rat API module provides the public interface, which license developers should adhere to. - diff --git a/apache-rat-api/src/site/site.xml b/apache-rat-api/src/site/site.xml deleted file mode 100644 index cb413e4fd..000000000 --- a/apache-rat-api/src/site/site.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - ]]> - - -

- - - diff --git a/apache-rat-api/src/test/java/org/apache/rat/api/domain/LicenseFamilyBuilderTest.java b/apache-rat-api/src/test/java/org/apache/rat/api/domain/LicenseFamilyBuilderTest.java deleted file mode 100644 index 3883e90a4..000000000 --- a/apache-rat-api/src/test/java/org/apache/rat/api/domain/LicenseFamilyBuilderTest.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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.apache.rat.api.domain; - -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.Assert.assertNotNull; - -import org.junit.Test; - -public class LicenseFamilyBuilderTest { - - @Test - public void testBuilderBuilds() { - final LicenseFamily family = - LicenseFamilyBuilder.aLicenseFamily().build(); - assertNotNull("Builder should build", family); - } - - @Test - public void testWithNotes() { - final String someNotes = "Some notes"; - final LicenseFamily family = - LicenseFamilyBuilder.aLicenseFamily().withNotes(someNotes) - .build(); - assertThat(family.getNotes(), is(someNotes)); - } - - @Test - public void testWithCategory() { - final String someCategory = "Some license category"; - final LicenseFamily family = - LicenseFamilyBuilder.aLicenseFamily() - .withCategory(someCategory).build(); - assertThat(family.getCategory(), is(someCategory)); - } - - @Test - public void testWithName() { - final String someName = "A name for a license"; - final LicenseFamily family = - LicenseFamilyBuilder.aLicenseFamily().withName(someName) - .build(); - assertThat(family.getName(), is(someName)); - - } -} diff --git a/apache-rat-api/src/test/java/org/apache/rat/api/domain/RatLicenseFamilyTest.java b/apache-rat-api/src/test/java/org/apache/rat/api/domain/RatLicenseFamilyTest.java deleted file mode 100644 index 9270510e7..000000000 --- a/apache-rat-api/src/test/java/org/apache/rat/api/domain/RatLicenseFamilyTest.java +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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.apache.rat.api.domain; - -import static org.apache.rat.api.domain.RatLicenseFamily.APACHE; -import static org.apache.rat.api.domain.RatLicenseFamily.CDDL1; -import static org.apache.rat.api.domain.RatLicenseFamily.DOJO; -import static org.apache.rat.api.domain.RatLicenseFamily.GPL1; -import static org.apache.rat.api.domain.RatLicenseFamily.GPL2; -import static org.apache.rat.api.domain.RatLicenseFamily.GPL3; -import static org.apache.rat.api.domain.RatLicenseFamily.MIT; -import static org.apache.rat.api.domain.RatLicenseFamily.OASIS; -import static org.apache.rat.api.domain.RatLicenseFamily.TMF854; -import static org.apache.rat.api.domain.RatLicenseFamily.W3C; -import static org.apache.rat.api.domain.RatLicenseFamily.W3C_DOCUMENTATION; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.MatcherAssert.assertThat; - -import org.junit.Test; - -public class RatLicenseFamilyTest { - - @Test - public void testW3CLicenseFamilyCategory() { - assertThat(W3C.getCategory(), is("W3C ")); - } - - @Test - public void testW3CLicenseFamilyName() { - assertThat(W3C.getName(), is("W3C Software Copyright")); - } - - @Test - public void testW3CLicenseFamilyNotes() { - assertThat( - W3C.getNotes(), - is("Note that W3C requires a NOTICE. All modifications require notes. See http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231.")); - } - - @Test - public void testW3CDocLicenseFamilyCategory() { - assertThat(W3C_DOCUMENTATION.getCategory(), is("W3CD ")); - } - - @Test - public void testW3CDocLicenseFamilyName() { - assertThat(W3C_DOCUMENTATION.getName(), is("W3C Document Copyright")); - } - - @Test - public void testW3CDocLicenseFamilyNotes() { - assertThat( - W3C_DOCUMENTATION.getNotes(), - is("Note that W3CD does not allow modifications. See http://www.w3.org/Consortium/Legal/2002/copyright-documents-20021231.")); - } - - @Test - public void testAPACHELicenseFamilyCategory() { - assertThat(APACHE.getCategory(), is("AL ")); - } - - @Test - public void testAPACHELicenseFamilyName() { - assertThat(APACHE.getName(), is("Apache License Version 2.0")); - } - - @Test - public void testAPACHELicenseFamilyNotes() { - assertThat( - APACHE.getNotes(), - is("Note that APACHE requires a NOTICE. All modifications require notes. See http://www.apache.org/licenses/LICENSE-2.0.")); - } - - @Test - public void testGPL1LicenseFamilyCategory() { - assertThat(GPL1.getCategory(), is("GPL1 ")); - } - - @Test - public void testGPL1LicenseFamilyName() { - assertThat(GPL1.getName(), is("GNU General Public License, version 1")); - } - - @Test - public void testGPL1LicenseFamilyNotes() { - assertThat( - GPL1.getNotes(), - is("Note that GPL1 requires a NOTICE. All modifications require notes. See http://www.gnu.org/licenses/gpl-1.0.html.")); - } - - @Test - public void testGPL2LicenseFamilyCategory() { - assertThat(GPL2.getCategory(), is("GPL2 ")); - } - - @Test - public void testGPL2LicenseFamilyName() { - assertThat(GPL2.getName(), is("GNU General Public License, version 2")); - } - - @Test - public void testGPL2LicenseFamilyNotes() { - assertThat( - GPL2.getNotes(), - is("Note that GPL2 requires a NOTICE. All modifications require notes. See http://www.gnu.org/licenses/gpl-2.0.html.")); - } - - @Test - public void testGPL3LicenseFamilyCategory() { - assertThat(GPL3.getCategory(), is("GPL3 ")); - } - - @Test - public void testGPL3LicenseFamilyName() { - assertThat(GPL3.getName(), is("GNU General Public License, version 3")); - } - - @Test - public void testGPL3LicenseFamilyNotes() { - assertThat( - GPL3.getNotes(), - is("Note that GPL3 requires a NOTICE. All modifications require notes. See http://www.gnu.org/licenses/gpl-3.0.html.")); - } - - @Test - public void testMITLicenseFamilyCategory() { - assertThat(MIT.getCategory(), is("MIT ")); - } - - @Test - public void testMITLicenseFamilyName() { - assertThat(MIT.getName(), is("The MIT License")); - } - - @Test - public void testMITLicenseFamilyNotes() { - assertThat( - MIT.getNotes(), - is("Note that MIT requires a NOTICE. All modifications require notes. See http://opensource.org/licenses/MIT.")); - } - - @Test - public void testCDDL1LicenseFamilyCategory() { - assertThat(CDDL1.getCategory(), is("CDDL1")); - } - - @Test - public void testCDDL1LicenseFamilyName() { - assertThat(CDDL1.getName(), - is("COMMON DEVELOPMENT AND DISTRIBUTION LICENSE Version 1.0")); - } - - @Test - public void testCDDL1LicenseFamilyNotes() { - assertThat( - CDDL1.getNotes(), - is("Note that CDDL1 requires a NOTICE. All modifications require notes. See https://oss.oracle.com/licenses/CDDL.")); - } - - @Test - public void testOASISLicenseFamilyCategory() { - assertThat(OASIS.getCategory(), is("OASIS")); - } - - @Test - public void testOASISLicenseFamilyName() { - assertThat(OASIS.getName(), is("OASIS Open License")); - } - - @Test - public void testOASISLicenseFamilyNotes() { - assertThat( - OASIS.getNotes(), - is("Note that OASIS requires a NOTICE. All modifications require notes. See https://www.oasis-open.org/policies-guidelines/ipr.")); - } - - @Test - public void testTMF854LicenseFamilyCategory() { - assertThat(TMF854.getCategory(), is("TMF ")); - } - - @Test - public void testTMF854LicenseFamilyName() { - assertThat(TMF854.getName(), is("Modified BSD License")); - } - - @Test - public void testTMF854LicenseFamilyNotes() { - assertThat( - TMF854.getNotes(), - is("Note that TMF854 requires a NOTICE. All modifications require notes. See http://opensource.org/licenses/BSD-3-Clause.")); - } - - @Test - public void testDOJOLicenseFamilyCategory() { - assertThat(DOJO.getCategory(), is("DOJO ")); - } - - @Test - public void testDOJOLicenseFamilyName() { - assertThat(DOJO.getName(), is("Modified BSD License")); - } - - @Test - public void testDOJOLicenseFamilyNotes() { - assertThat( - DOJO.getNotes(), - is("Note that DOJO requires a NOTICE. All modifications require notes. See http://dojotoolkit.org/community/licensing.shtml.")); - } -} diff --git a/apache-rat-core/architecture_notes.md b/apache-rat-core/architecture_notes.md new file mode 100644 index 000000000..dfbb2b0b5 --- /dev/null +++ b/apache-rat-core/architecture_notes.md @@ -0,0 +1,68 @@ + +# RAT Architecture notes. + +## Source definition + +In this document source files are the files that RAT is checking. They can be individual source files, document files, +configuration files, archives, etc. The use of the term "source" does not specify application source files per. se. + +## License definitions + +Licenses comprise a unique ID, a name, and a series of tests. + + * The uniqueID and name are defined in the interface `ILicenseFamiy` + * The tests are defined in the interface `IHeaderMatcher` + * If any of the tests are matched then the license is detected. + * tests may be multiplexing tests that containt more than one test. Multiplexing tests are either + * `AND` tests where all the the sub tests must be true for the test to be true; or + * `OR` tests where one the the sub-tests being true makes the entire test true. + + + When source files are tested for the presence of a license all the license checks are performed in parallel. + + ## Tests + + There are several implementations of tests + + ### Text + + Text is specified, the complete text must be located in the source file. + + ### SPDX + + The SPDX keyword must be found within the source file. SPDX keyword have the form `SPDX-License-Identifier:\\s([A-Za-z0-9\\.\\-]+)` + when defining the SPDX matcher onlyt the variable alpha-numeric phrase may be specified (eg the 'Apache-2.0' in the SPDX + identifier 'SPDX-License-Identifier: Apache-2.0` + + ### Copyright + + The copyright must match a specific date(range) and owner. + + ### Multiplex + + Multiplex tests comprise several tests. How the test is evaluated depends upon the type. + + #### ANY-Multiplex (aka OR-Multiplex) + If any of the tests comprising the ANY-Multiplex test pass then the ANY-Multiplex test passes. + + #### ALL-Multiplex (aka AND-Multiplex) +Only if all of the tests comprising the ALL-Multiplex test pass will the ALL-Multiplex test pass. + + ### License test + All licenses are defined as ANY-Multiplex tests. Licenses therefore be uses as tests within other tests. However, this + only makes sense in the context of an ALL-Multiplex test. diff --git a/apache-rat-core/pom.xml b/apache-rat-core/pom.xml index 60f4de006..3ea99ec71 100644 --- a/apache-rat-core/pom.xml +++ b/apache-rat-core/pom.xml @@ -1,4 +1,4 @@ - + src/test/resources/appliedAL20/bad/*.* src/test/resources/oasis/bad/*.* - + src/test/resources/elements/Source.java src/test/resources/elements/ILoggerFactory.java src/test/resources/elements/sub/Empty.txt @@ -67,21 +65,26 @@ src/test/resources/binaries/Image-png.not src/test/resources/elements/TextHttps.txt - - src/test/resources/elements/plain.json + + + org.apache.maven.plugins + maven-jar-plugin + + + + test-jar + + + + + - - - - org.apache.rat - apache-rat-api - org.apache.commons commons-collections4 @@ -106,14 +109,34 @@ - junit - junit - test + org.junit.jupiter + junit-jupiter-api + + + org.junit.jupiter + junit-jupiter-engine + + + org.junit.jupiter + junit-jupiter-params - commons-cli commons-cli + + commons-beanutils + commons-beanutils + + + org.mockito + mockito-core + test + + + org.assertj + assertj-core + test + diff --git a/apache-rat-core/src/test/java/org/apache/rat/analysis/MockLicenseMatcher.java b/apache-rat-core/src/main/java/org/apache/rat/ConfigurationException.java similarity index 68% rename from apache-rat-core/src/test/java/org/apache/rat/analysis/MockLicenseMatcher.java rename to apache-rat-core/src/main/java/org/apache/rat/ConfigurationException.java index 75da1c6a2..c635d245e 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/analysis/MockLicenseMatcher.java +++ b/apache-rat-core/src/main/java/org/apache/rat/ConfigurationException.java @@ -15,27 +15,26 @@ * KIND, either express or implied. See the License for the * * specific language governing permissions and limitations * * under the License. * - */ -package org.apache.rat.analysis; + */ +package org.apache.rat; -import org.apache.rat.api.Document; +/** + * An exception thrown when there is an issue with the Configuration. + */ +public class ConfigurationException extends RuntimeException { -import java.util.ArrayList; -import java.util.List; + private static final long serialVersionUID = 7257245932787579431L; -public class MockLicenseMatcher implements IHeaderMatcher { - - public final List lines = new ArrayList<>(); - public int resets = 0; - public boolean result = true; + public ConfigurationException(String message, Throwable cause) { + super(message, cause); + } - public boolean match(Document subject, String line) { - lines.add(line); - return result; + public ConfigurationException(String message) { + super(message); } - public void reset() { - resets++; + public ConfigurationException(Throwable cause) { + super(cause); } } diff --git a/apache-rat-core/src/main/java/org/apache/rat/Defaults.java b/apache-rat-core/src/main/java/org/apache/rat/Defaults.java index 68fb5ec09..c5aff0748 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/Defaults.java +++ b/apache-rat-core/src/main/java/org/apache/rat/Defaults.java @@ -18,91 +18,233 @@ */ package org.apache.rat; -import org.apache.rat.analysis.IHeaderMatcher; -import org.apache.rat.analysis.generation.GeneratedLicenseNotRequired; -import org.apache.rat.analysis.generation.JavaDocLicenseNotRequired; -import org.apache.rat.analysis.license.ApacheSoftwareLicense20; -import org.apache.rat.analysis.license.CDDL1License; -import org.apache.rat.analysis.license.DojoLicenseHeader; -import org.apache.rat.analysis.license.GPL1License; -import org.apache.rat.analysis.license.GPL2License; -import org.apache.rat.analysis.license.GPL3License; -import org.apache.rat.analysis.license.MITLicense; -import org.apache.rat.analysis.license.OASISLicense; -import org.apache.rat.analysis.license.TMF854LicenseHeader; -import org.apache.rat.analysis.license.W3CDocLicense; -import org.apache.rat.analysis.license.W3CLicense; -import org.apache.rat.analysis.util.HeaderMatcherMultiplexer; -import org.apache.rat.api.MetaData; - +import java.io.File; import java.io.InputStream; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Collection; +import java.util.Comparator; +import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; +import org.apache.commons.io.function.IOSupplier; +import org.apache.rat.configuration.Format; +import org.apache.rat.configuration.LicenseReader; +import org.apache.rat.configuration.MatcherReader; +import org.apache.rat.license.ILicense; +import org.apache.rat.license.ILicenseFamily; +import org.apache.rat.license.LicenseSetFactory; +import org.apache.rat.license.LicenseSetFactory.LicenseFilter; /** - * Utility class that holds constants shared by the CLI tool and the Ant tasks. + * A class that holds the list of licenses and approved licenses from one or more configuration files. */ public class Defaults { + + /** + * The default configuration file from the package. + */ + private static final URL DEFAULT_CONFIG_URL = Defaults.class.getResource("/org/apache/rat/default.xml"); + /** + * The default XSLT stylesheet to produce a text output file. + */ + public static final String PLAIN_STYLESHEET = "org/apache/rat/plain-rat.xsl"; + /** + * The default XSLT stylesheet to produce a list of unapproved licenses. + */ + public static final String UNAPPROVED_LICENSES_STYLESHEET = "org/apache/rat/unapproved-licenses.xsl"; + + private final LicenseSetFactory setFactory; + + /** + * Initialize the system configuration reader.. + */ + public static void init() { + Format fmt = Format.fromURL(DEFAULT_CONFIG_URL); + MatcherReader mReader = fmt.matcherReader(); + mReader.addMatchers(DEFAULT_CONFIG_URL); + mReader.readMatcherBuilders(); + } + /** - * no instances + * Builder constructs instances. */ - private Defaults() { + private Defaults(Set urls) { + this.setFactory = Defaults.readConfigFiles(urls); } /** - * The standard list of licenses to include in the reports. - * Needs to match configuration in {@link org.apache.rat.policy.DefaultPolicy}. + * Gets a builder for a Defaults object. + * @return the Builder. */ - public static final List DEFAULT_MATCHERS = Collections.unmodifiableList( - Arrays.asList(new ApacheSoftwareLicense20(), - new GPL1License(), - new GPL2License(), - new GPL3License(), - new MITLicense(), - new W3CLicense(), - new W3CDocLicense(), - new OASISLicense(), - new JavaDocLicenseNotRequired(), // does not have a MetaData.RAT_LICENSE_FAMILY_NAME_VALUE_... entry - new GeneratedLicenseNotRequired(), // does not have a MetaData.RAT_LICENSE_FAMILY_NAME_VALUE_... entry - new DojoLicenseHeader(), - new TMF854LicenseHeader(), - new CDDL1License())); - - // all classes in license package implementing ILicenseFamily - public static final List DEFAULT_LICENSE_FAMILIES = Collections.unmodifiableList( - Arrays.asList( - MetaData.RAT_LICENSE_FAMILY_NAME_VALUE_ACADEMIC_FREE_LICENSE_VERSION_2_1, // - MetaData.RAT_LICENSE_FAMILY_NAME_VALUE_APACHE_LICENSE_VERSION_2_0, // - MetaData.RAT_LICENSE_FAMILY_NAME_VALUE_CDDL1, // - MetaData.RAT_LICENSE_FAMILY_NAME_VALUE_GPL_VERSION_1, // - MetaData.RAT_LICENSE_FAMILY_NAME_VALUE_GPL_VERSION_2, // - MetaData.RAT_LICENSE_FAMILY_NAME_VALUE_GPL_VERSION_3, // - MetaData.RAT_LICENSE_FAMILY_NAME_VALUE_MIT, // - MetaData.RAT_LICENSE_FAMILY_NAME_VALUE_MODIFIED_BSD_LICENSE, // - MetaData.RAT_LICENSE_FAMILY_NAME_VALUE_OASIS_OPEN_LICENSE, // - MetaData.RAT_LICENSE_FAMILY_NAME_VALUE_W3C_DOCUMENT_COPYRIGHT, // - MetaData.RAT_LICENSE_FAMILY_NAME_VALUE_W3C_SOFTWARE_COPYRIGHT - // - )); + public static Builder builder() { + return new Builder(); + } - public static final String PLAIN_STYLESHEET = "org/apache/rat/plain-rat.xsl"; - public static final String UNAPPROVED_LICENSES_STYLESHEET = "org/apache/rat/unapproved-licenses.xsl"; + /** + * Reads the configuration files. + * @param urls the URLs to read. + */ + private static LicenseSetFactory readConfigFiles(Collection urls) { + + SortedSet licenses = LicenseSetFactory.emptyLicenseSet(); + + SortedSet approvedLicenseIds = new TreeSet<>(); + + for (URL url : urls) { + Format fmt = Format.fromURL(url); + MatcherReader mReader = fmt.matcherReader(); + if (mReader != null) { + mReader.addMatchers(url); + mReader.readMatcherBuilders(); + } + + LicenseReader lReader = fmt.licenseReader(); + if (lReader != null) { + lReader.addLicenses(url); + licenses.addAll(lReader.readLicenses()); + lReader.approvedLicenseId().stream().map(ILicenseFamily::makeCategory).forEach(approvedLicenseIds::add); + } + } + return new LicenseSetFactory(licenses, approvedLicenseIds); + } + + /** + * Gets a supplier for the "plain" text stylesheet. + * @return an IOSupplier for the plain text stylesheet. + */ + public static IOSupplier getPlainStyleSheet() { + return () -> Defaults.class.getClassLoader().getResourceAsStream(Defaults.PLAIN_STYLESHEET); + } - public static InputStream getPlainStyleSheet() { - return Defaults.class.getClassLoader().getResourceAsStream(Defaults.PLAIN_STYLESHEET); + /** + * Gets a supplier for the unapproved licences list stylesheet + * @return an IOSupplier for the unapproved licenses list stylesheet. + */ + public static IOSupplier getUnapprovedLicensesStyleSheet() { + return () -> Defaults.class.getClassLoader().getResourceAsStream(Defaults.UNAPPROVED_LICENSES_STYLESHEET); } - public static InputStream getUnapprovedLicensesStyleSheet() { - return Defaults.class.getClassLoader().getResourceAsStream(Defaults.UNAPPROVED_LICENSES_STYLESHEET); + /** + * Gets the sorted set of approved licenses for a given filter condition. + * @param filter define which type of licenses to return. + * @return sorted set of licenses. + */ + public SortedSet getLicenses(LicenseFilter filter) { + return setFactory.getLicenses(filter); + } + + /** + * Gets the sorted set of approved licenses for a given filter condition. + * @param filter define which type of licenses to return. + * @return sorted set of license families. + */ + public SortedSet getLicenseFamilies(LicenseFilter filter) { + return setFactory.getLicenseFamilies(filter); } - public static InputStream getDefaultStyleSheet() { - return getPlainStyleSheet(); + /** + * Gets the sorted set of approved license ids for a given filter condition. + * If no licenses have been explicitly listed as approved, all licenses are assumed to be approved. + * @param filter define which type of licenses to return. + * @return The sorted set of approved licenseIds. + */ + public SortedSet getLicenseIds(LicenseFilter filter) { + return setFactory.getLicenseFamilyIds(filter); } + + /** + * The Defaults builder. + */ + public static class Builder { + private final Set fileNames = new TreeSet<>(Comparator.comparing(URL::toString)); + + private Builder() { + fileNames.add(DEFAULT_CONFIG_URL); + } + + /** + * Adds a URL to a configuration file to be read. + * + * @param url the URL to add + * @return this Builder for chaining + */ + public Builder add(URL url) { + fileNames.add(url); + return this; + } + + /** + * Adds the name of a configuration file to be read. + * + * @param fileName the name of the file to add. + * @return this Builder for chaining + * @throws MalformedURLException in case the fileName cannot be found. + */ + public Builder add(String fileName) throws MalformedURLException { + return add(new File(fileName)); + } + + /** + * Adds a configuration file to be read. + * + * @param file the File to add. + * @return this Builder for chaining + * @throws MalformedURLException in case the file cannot be found. + */ + public Builder add(File file) throws MalformedURLException { + return add(file.toURI().toURL()); + } + + /** + * Removes a file from the list of configuration files to process. + * + * @param url the URL of the file to remove. + * @return this Builder for chaining + */ + public Builder remove(URL url) { + fileNames.remove(url); + return this; + } + + /** + * Removes a file name from the list of configuration files to process. + * + * @param fileName the fileName of the file to remove. + * @return this Builder for chaining + * @throws MalformedURLException in case the fileName cannot be found. + */ + public Builder remove(String fileName) throws MalformedURLException { + return remove(new File(fileName)); + } + + /** + * Removes a file from the list of configuration files to process. + * + * @param file the File of the file to remove. + * @return this Builder for chaining + * @throws MalformedURLException in case the file cannot be found. + */ + public Builder remove(File file) throws MalformedURLException { + return remove(file.toURI().toURL()); + } + + /** + * Removes the default definitions from the list of files to process. + * + * @return this Builder for chaining + */ + public Builder noDefault() { + return remove(DEFAULT_CONFIG_URL); + } - public static IHeaderMatcher createDefaultMatcher() { - return new HeaderMatcherMultiplexer(Defaults.DEFAULT_MATCHERS); + /** + * Builds the defaults object. + * @return the current defaults object. + */ + public Defaults build() { + return new Defaults(fileNames); + } } } diff --git a/apache-rat-core/src/main/java/org/apache/rat/Report.java b/apache-rat-core/src/main/java/org/apache/rat/Report.java index 4dff5798a..1db814a64 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/Report.java +++ b/apache-rat-core/src/main/java/org/apache/rat/Report.java @@ -18,49 +18,136 @@ */ package org.apache.rat; -import org.apache.commons.cli.*; +import java.io.File; +import java.io.FilenameFilter; +import java.io.IOException; +import java.io.PrintStream; +import java.io.Serializable; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; +import java.util.regex.PatternSyntaxException; +import java.util.stream.Collectors; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.DefaultParser; +import org.apache.commons.cli.HelpFormatter; +import org.apache.commons.cli.Option; +import org.apache.commons.cli.OptionGroup; +import org.apache.commons.cli.Options; +import org.apache.commons.cli.ParseException; import org.apache.commons.io.FileUtils; -import org.apache.commons.io.filefilter.*; +import org.apache.commons.io.filefilter.NameFileFilter; +import org.apache.commons.io.filefilter.NotFileFilter; +import org.apache.commons.io.filefilter.OrFileFilter; +import org.apache.commons.io.filefilter.RegexFileFilter; +import org.apache.commons.io.filefilter.WildcardFileFilter; import org.apache.commons.lang3.StringUtils; -import org.apache.rat.api.RatException; +import org.apache.rat.config.AddLicenseHeaders; +import org.apache.rat.license.LicenseSetFactory.LicenseFilter; import org.apache.rat.report.IReportable; -import org.apache.rat.report.RatReport; -import org.apache.rat.report.claim.ClaimStatistic; -import org.apache.rat.report.xml.XmlReportFactory; -import org.apache.rat.report.xml.writer.IXmlWriter; -import org.apache.rat.report.xml.writer.impl.base.XmlWriter; +import org.apache.rat.utils.DefaultLog; +import org.apache.rat.utils.Log; +import org.apache.rat.utils.Log.Level; import org.apache.rat.walker.ArchiveWalker; import org.apache.rat.walker.DirectoryWalker; -import javax.xml.transform.TransformerConfigurationException; -import java.io.*; -import java.nio.charset.Charset; -import java.util.Arrays; -import java.util.List; -import java.util.regex.PatternSyntaxException; - - +/** + * The CLI based configuration object for report generation. + */ public class Report { + /** + * Adds license headers to files missing headers. + */ + private static final String ADD = "A"; + private static final String ADD_OLD = "a"; + /** + * Forces changes to be written to new files. + */ + private static final String FORCE = "f"; + /** + * Defines the copyright header to add to the file. + */ + private static final String COPYRIGHT = "c"; + /** + * Name of File to exclude from report consideration. + */ private static final String EXCLUDE_CLI = "e"; + /** + * Name of file that contains a list of files to exclude from report + * consideration. + */ private static final String EXCLUDE_FILE_CLI = "E"; + /** + * The stylesheet to use to style the XML output. + */ private static final String STYLESHEET_CLI = "s"; + /** + * Produce help + */ private static final String HELP = "h"; + /** + * Flag to identify a file with license definitions. + */ + private static final String LICENSES = "licenses"; + /** + * Do not use the default files. + */ + private static final String NO_DEFAULTS = "no-default-licenses"; + /** + * Scan hidden directories. + */ + private static final String SCAN_HIDDEN_DIRECTORIES = "scan-hidden-directories"; + /** + * List the licenses that were used for the run. + */ + private static final String LIST_LICENSES = "list-licenses"; - public static final void main(String[] args) throws Exception { - final ReportConfiguration configuration = new ReportConfiguration(); - configuration.setHeaderMatcher(Defaults.createDefaultMatcher()); - configuration.setApproveDefaultLicenses(true); - Options opts = buildOptions(); + /** + * List the all families for the run. + */ + private static final String LIST_FAMILIES = "list-families"; + + private static final String LOG_LEVEL = "log-level"; - CommandLine cl = null; + /** + * Set unstyled XML output + */ + private static final String XML = "x"; + + + /** + * Processes the command line and builds a configuration and executes the + * report. + * + * @param args the arguments. + * @throws Exception on error. + */ + public static void main(String[] args) throws Exception { + Options opts = buildOptions(); + CommandLine cl; try { cl = new DefaultParser().parse(opts, args); } catch (ParseException e) { - System.err.println("Please use the \"--help\" option to see a list of valid commands and options"); + DefaultLog.INSTANCE.error(e.getMessage()); + DefaultLog.INSTANCE.error("Please use the \"--help\" option to see a list of valid commands and options"); System.exit(1); - return; // dummy return (won't be reached) to avoid Eclipse complaint about possible NPE for "cl" + return; // dummy return (won't be reached) to avoid Eclipse complaint about possible NPE + // for "cl" } + if (cl.hasOption(LOG_LEVEL)) { + try { + Log.Level level = Log.Level.valueOf(cl.getOptionValue(LOG_LEVEL).toUpperCase()); + DefaultLog.INSTANCE.setLevel(level); + } catch (IllegalArgumentException e) { + DefaultLog.INSTANCE.warn(String.format("Invalid Log Level (%s) specified.", cl.getOptionValue(LOG_LEVEL))); + DefaultLog.INSTANCE.warn(String.format("Log level set at: %s", DefaultLog.INSTANCE.getLevel())); + } + } if (cl.hasOption(HELP)) { printUsage(opts); } @@ -69,351 +156,285 @@ public static final void main(String[] args) throws Exception { if (args == null || args.length != 1) { printUsage(opts); } else { - Report report = new Report(args[0]); + ReportConfiguration configuration = createConfiguration(args[0], cl); + configuration.validate(DefaultLog.INSTANCE::error); + + boolean dryRun = false; + + if (cl.hasOption(LIST_FAMILIES)) { + LicenseFilter f = LicenseFilter.fromText(cl.getOptionValue(LIST_FAMILIES)); + if (f != LicenseFilter.none) { + dryRun = true; + Reporter.listLicenseFamilies(configuration, f); + } + } + if (cl.hasOption(LIST_LICENSES)) { + LicenseFilter f = LicenseFilter.fromText(cl.getOptionValue(LIST_LICENSES)); + if (f != LicenseFilter.none) { + dryRun = true; + Reporter.listLicenses(configuration, f); + } + } + + if (!dryRun) { + Reporter.report(configuration); + } + } + } + + static ReportConfiguration createConfiguration(String baseDirectory, CommandLine cl) throws IOException { + final ReportConfiguration configuration = new ReportConfiguration(DefaultLog.INSTANCE); + + if (cl.hasOption('o')) { + configuration.setOut(new File(cl.getOptionValue('o'))); + } + + if (cl.hasOption(SCAN_HIDDEN_DIRECTORIES)) { + configuration.setDirectoryFilter(null); + } + + if (cl.hasOption('a') || cl.hasOption('A')) { + configuration.setAddLicenseHeaders(cl.hasOption('f') ? AddLicenseHeaders.FORCED : AddLicenseHeaders.TRUE); + configuration.setCopyrightMessage(cl.getOptionValue("c")); + } - if (cl.hasOption('a') || cl.hasOption('A')) { - configuration.setAddingLicenses(true); - configuration.setAddingLicensesForced(cl.hasOption('f')); - configuration.setCopyrightMessage(cl.getOptionValue("c")); + if (cl.hasOption(EXCLUDE_CLI)) { + String[] excludes = cl.getOptionValues(EXCLUDE_CLI); + if (excludes != null) { + final FilenameFilter filter = parseExclusions(Arrays.asList(excludes)); + configuration.setInputFileFilter(filter); + } + } else if (cl.hasOption(EXCLUDE_FILE_CLI)) { + String excludeFileName = cl.getOptionValue(EXCLUDE_FILE_CLI); + if (excludeFileName != null) { + final FilenameFilter filter = parseExclusions( + FileUtils.readLines(new File(excludeFileName), StandardCharsets.UTF_8)); + configuration.setInputFileFilter(filter); } + } - if (cl.hasOption(EXCLUDE_CLI)) { - String[] excludes = cl.getOptionValues(EXCLUDE_CLI); - if (excludes != null) { - final FilenameFilter filter = parseExclusions(Arrays.asList(excludes)); - report.setInputFileFilter(filter); - } - } else if (cl.hasOption(EXCLUDE_FILE_CLI)) { - String excludeFileName = cl.getOptionValue(EXCLUDE_FILE_CLI); - if (excludeFileName != null) { - final FilenameFilter filter = parseExclusions(FileUtils.readLines(new File(excludeFileName), Charset.forName("UTF-8"))); - report.setInputFileFilter(filter); + if (cl.hasOption(XML)) { + configuration.setStyleReport(false); + } else { + configuration.setStyleReport(true); + if (cl.hasOption(STYLESHEET_CLI)) { + String[] style = cl.getOptionValues(STYLESHEET_CLI); + if (style.length != 1) { + DefaultLog.INSTANCE.error("Please specify a single stylesheet"); + System.exit(1); } + configuration.setStyleSheet(() -> Files.newInputStream(Paths.get(style[0]))); } - if (cl.hasOption('x')) { - report.report(System.out, configuration); - } else { - if (!cl.hasOption(STYLESHEET_CLI)) { - report.styleReport(System.out, configuration); - } else { - String[] style = cl.getOptionValues(STYLESHEET_CLI); - if (style.length != 1) { - System.err.println("please specify a single stylesheet"); - System.exit(1); - } - try { - report(System.out, - report.getDirectory(System.out), - new FileInputStream(style[0]), - configuration); - } catch (FileNotFoundException fnfe) { - System.err.println("stylesheet " + style[0] - + " doesn't exist"); - System.exit(1); - } - } + } + + Defaults.Builder defaultBuilder = Defaults.builder(); + if (cl.hasOption(NO_DEFAULTS)) { + defaultBuilder.noDefault(); + } + if (cl.hasOption(LICENSES)) { + for (String fn : cl.getOptionValues(LICENSES)) { + defaultBuilder.add(fn); } } + Defaults defaults = defaultBuilder.build(); + configuration.setFrom(defaults); + configuration.setReportable(getDirectory(baseDirectory, configuration)); + return configuration; } - - static FilenameFilter parseExclusions(List excludes) throws IOException { + + /** + * Creates a filename filter from patterns to exclude. + * + * @param excludes the list of patterns to exclude. + * @return the FilenameFilter tht excludes the patterns + */ + static FilenameFilter parseExclusions(List excludes) { final OrFileFilter orFilter = new OrFileFilter(); int ignoredLines = 0; for (String exclude : excludes) { try { // skip comments - if(exclude.startsWith("#") || StringUtils.isEmpty(exclude)) { + if (exclude.startsWith("#") || StringUtils.isEmpty(exclude)) { ignoredLines++; continue; } String exclusion = exclude.trim(); - // interpret given patterns as regular expression, direct file names or wildcards to give users more choices to configure exclusions + // interpret given patterns as regular expression, direct file names or + // wildcards to give users more choices to configure exclusions orFilter.addFileFilter(new RegexFileFilter(exclusion)); orFilter.addFileFilter(new NameFileFilter(exclusion)); - orFilter.addFileFilter(new WildcardFileFilter(exclusion)); - } catch(PatternSyntaxException e) { - System.err.println("Will skip given exclusion '" + exclude + "' due to " + e); + orFilter.addFileFilter(WildcardFileFilter.builder().setWildcards(exclusion).get()); + } catch (PatternSyntaxException e) { + DefaultLog.INSTANCE.error("Will skip given exclusion '" + exclude + "' due to " + e); } } - System.err.println("Ignored " + ignoredLines + " lines in your exclusion files as comments or empty lines."); + DefaultLog.INSTANCE.error("Ignored " + ignoredLines + " lines in your exclusion files as comments or empty lines."); return new NotFileFilter(orFilter); } - private static Options buildOptions() { - Options opts = new Options(); + static Options buildOptions() { + String licFilterValues = String.join(", ", + Arrays.stream(LicenseFilter.values()).map(LicenseFilter::name).collect(Collectors.toList())); - Option help = new Option(HELP, "help", false, - "Print help for the RAT command line interface and exit"); - opts.addOption(help); + Options opts = new Options() + + .addOption( + Option.builder().hasArg(true).longOpt(LIST_FAMILIES) + .desc("List the defined license families (default is none). Valid options are: "+licFilterValues+".") + .build()) + .addOption( + Option.builder().hasArg(true).longOpt(LIST_LICENSES) + .desc("List the defined licenses (default is none). Valid options are: "+licFilterValues+".") + .build()) + + .addOption(new Option(HELP, "help", false, "Print help for the RAT command line interface and exit.")); + + + Option out = new Option("o", "out", true, + "Define the output file where to write a report to (default is System.out)."); + opts.addOption(out); + + String defaultHandlingText = " By default all approved default licenses are used"; + Option noDefaults = new Option(null, NO_DEFAULTS, false, "Ignore default configuration." + defaultHandlingText); + opts.addOption(noDefaults); + + opts.addOption(null, LICENSES, true, "File names or URLs for license definitions"); + opts.addOption(null, SCAN_HIDDEN_DIRECTORIES, false, "Scan hidden directories"); OptionGroup addLicenseGroup = new OptionGroup(); - String addLicenseDesc = "Add the default license header to any file with an unknown license that is not in the exclusion list. " + - "By default new files will be created with the license header, " + - "to force the modification of existing files use the --force option."; - - // RAT-85/RAT-203: Deprecated! added only for convenience and for backwards compatibility - Option addLicence = new Option( - "a", - "addLicence", - false, - addLicenseDesc); + String addLicenseDesc = "Add the default license header to any file with an unknown license that is not in the exclusion list. " + + "By default new files will be created with the license header, " + + "to force the modification of existing files use the --force option."; + + // RAT-85/RAT-203: Deprecated! added only for convenience and for backwards + // compatibility + Option addLicence = new Option(ADD_OLD, "addLicence", false, addLicenseDesc); addLicenseGroup.addOption(addLicence); - Option addLicense = new Option( - "A", - "addLicense", - false, - addLicenseDesc); + Option addLicense = new Option(ADD, "addLicense", false, addLicenseDesc); addLicenseGroup.addOption(addLicense); opts.addOptionGroup(addLicenseGroup); - Option write = new Option( - "f", - "force", - false, - "Forces any changes in files to be written directly to the source files (i.e. new files are not created)"); + Option write = new Option(FORCE, "force", false, + "Forces any changes in files to be written directly to the source files (i.e. new files are not created)."); opts.addOption(write); - Option copyright = new Option( - "c", - "copyright", - true, + Option copyright = new Option(COPYRIGHT, "copyright", true, "The copyright message to use in the license headers, usually in the form of \"Copyright 2008 Foo\""); opts.addOption(copyright); - final Option exclude = Option.builder(EXCLUDE_CLI) - .argName("expression") - .longOpt("exclude") - .hasArgs() - .desc("Excludes files matching wildcard . " + - "Note that --dir is required when using this parameter. " + - "Allows multiple arguments.") + final Option exclude = Option.builder(EXCLUDE_CLI).argName("expression").longOpt("exclude").hasArgs() + .desc("Excludes files matching wildcard . " + + "Note that --dir is required when using this parameter. " + "Allows multiple arguments.") .build(); opts.addOption(exclude); - final Option excludeFile = Option.builder(EXCLUDE_FILE_CLI) - .argName("fileName") - .longOpt("exclude-file") - .hasArgs() - .desc("Excludes files matching regular expression in " + - "Note that --dir is required when using this parameter. ") + final Option excludeFile = Option.builder(EXCLUDE_FILE_CLI).argName("fileName").longOpt("exclude-file") + .hasArgs().desc("Excludes files matching regular expression in " + + "Note that --dir is required when using this parameter. ") .build(); opts.addOption(excludeFile); - Option dir = new Option( - "d", - "dir", - false, - "Used to indicate source when using --exclude"); + Option dir = new Option("d", "dir", false, "Used to indicate source when using --exclude"); opts.addOption(dir); + opts.addOption( Option.builder().argName("level").longOpt(LOG_LEVEL) + .hasArgs().desc("sets the log level. Valid options are: DEBUG, INFO, WARN, ERROR, OFF") + .build() ); + OptionGroup outputType = new OptionGroup(); - Option xml = new Option( - "x", - "xml", - false, - "Output the report in raw XML format. Not compatible with -s"); + Option xml = new Option(XML, "xml", false, "Output the report in raw XML format. Not compatible with -s"); outputType.addOption(xml); - Option xslt = new Option(STYLESHEET_CLI, - "stylesheet", - true, - "XSLT stylesheet to use when creating the" - + " report. Not compatible with -x"); + Option xslt = new Option(STYLESHEET_CLI, "stylesheet", true, + "XSLT stylesheet to use when creating the" + " report. Not compatible with -x"); outputType.addOption(xslt); opts.addOptionGroup(outputType); + + return opts; } private static void printUsage(Options opts) { HelpFormatter f = new HelpFormatter(); + f.setOptionComparator(new OptionComparator()); String header = "\nAvailable options"; - String footer = "\nNOTE:\n" + - "Rat is really little more than a grep ATM\n" + - "Rat is also rather memory hungry ATM\n" + - "Rat is very basic ATM\n" + - "Rat highlights possible issues\n" + - "Rat reports require interpretation\n" + - "Rat often requires some tuning before it runs well against a project\n" + - "Rat relies on heuristics: it may miss issues\n"; - - f.printHelp("java -jar apache-rat/target/apache-rat-CURRENT-VERSION.jar [options] [DIR|TARBALL]", - header, opts, footer, false); - System.exit(0); - } - - private final String baseDirectory; - - private FilenameFilter inputFileFilter = null; - - private Report(String baseDirectory) { - this.baseDirectory = baseDirectory; - } + String footer = "\nNOTE:\n" + "Rat is really little more than a grep ATM\n" + + "Rat is also rather memory hungry ATM\n" + "Rat is very basic ATM\n" + + "Rat highlights possible issues\n" + "Rat reports require interpretation\n" + + "Rat often requires some tuning before it runs well against a project\n" + + "Rat relies on heuristics: it may miss issues\n"; - /** - * Sets the current filter used to select files. - * - * @param inputFileFilter filter, or null when no filter has been set - */ - public void setInputFileFilter(FilenameFilter inputFileFilter) { - this.inputFileFilter = inputFileFilter; + f.printHelp("java -jar apache-rat/target/apache-rat-CURRENT-VERSION.jar [options] [DIR|TARBALL]", header, opts, + footer, false); + System.exit(0); } - /** - * @param out - the output stream to receive the styled report - * @return the currently collected numerical statistics. - * @throws Exception in case of errors. - * @deprecated use {@link #report(PrintStream, ReportConfiguration)} instead - */ - @Deprecated - public ClaimStatistic report(PrintStream out) throws Exception { - final ReportConfiguration configuration = new ReportConfiguration(); - configuration.setHeaderMatcher(Defaults.createDefaultMatcher()); - configuration.setApproveDefaultLicenses(true); - return report(out, configuration); + private Report() { + // do not instantiate } /** - * @param out - the output stream to receive the styled report - * @param configuration - current configuration options. - * @return the currently collected numerical statistics. - * @throws Exception in case of errors. - * @since Rat 0.8 + * Creates an IReportable object from the directory name and ReportConfiguration + * object. + * + * @param baseDirectory the directory that contains the files to report on. + * @param config the ReportConfiguration. + * @return the IReportable instance containing the files. */ - public ClaimStatistic report(PrintStream out, - ReportConfiguration configuration) - throws Exception { - final IReportable base = getDirectory(out); - if (base != null) { - return report(base, new OutputStreamWriter(out), configuration); - } - return null; - } - - private IReportable getDirectory(PrintStream out) { - File base = new File(baseDirectory); - if (!base.exists()) { - out.print("ERROR: "); - out.print(baseDirectory); - out.print(" does not exist.\n"); - return null; - } + private static IReportable getDirectory(String baseDirectory, ReportConfiguration config) { + try (PrintStream out = new PrintStream(config.getOutput().get())) { + File base = new File(baseDirectory); + + if (!base.exists()) { + config.getLog().log(Level.ERROR, "Directory '"+baseDirectory+"' does not exist"); + return null; + } - if (base.isDirectory()) { - return new DirectoryWalker(base, inputFileFilter); - } + if (base.isDirectory()) { + return new DirectoryWalker(base, config.getInputFileFilter(), config.getDirectoryFilter()); + } - try { - return new ArchiveWalker(base, inputFileFilter); - } catch (IOException ex) { - out.print("ERROR: "); - out.print(baseDirectory); - out.print(" is not valid gzip data.\n"); - return null; + try { + return new ArchiveWalker(base, config.getInputFileFilter()); + } catch (IOException ex) { + config.getLog().log(Level.ERROR, "file '"+baseDirectory+"' is not valid gzip data."); + return null; + } + } catch (IOException e) { + throw new ConfigurationException("Error opening output", e); } } /** - * Output a report in the default style and default license - * header matcher. - * - * @param out - the output stream to receive the styled report - * @throws Exception in case of errors. - * @deprecated use {@link #styleReport(PrintStream, ReportConfiguration)} instead - */ - @Deprecated - public void styleReport(PrintStream out) throws Exception { - final ReportConfiguration configuration = new ReportConfiguration(); - configuration.setHeaderMatcher(Defaults.createDefaultMatcher()); - configuration.setApproveDefaultLicenses(true); - styleReport(out, configuration); - } - - /** - * Output a report in the default style and default license - * header matcher. - * - * @param out - the output stream to receive the styled report - * @param configuration the configuration to use - * @throws Exception in case of errors. - * @since Rat 0.8 + * This class implements the {@code Comparator} interface for comparing Options. */ - public void styleReport(PrintStream out, - ReportConfiguration configuration) - throws Exception { - final IReportable base = getDirectory(out); - if (base != null) { - InputStream style = Defaults.getDefaultStyleSheet(); - report(out, base, style, configuration); + private static class OptionComparator implements Comparator