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, Serializable {
+ /** The serial version UID. */
+ private static final long serialVersionUID = 5305467873966684014L;
+
+ private String getKey(Option opt) {
+ String key = opt.getOpt();
+ key = key == null ? opt.getLongOpt() : key;
+ return key;
}
- }
-
- /**
- * Output a report that is styled using a defined stylesheet.
- *
- * @param out the stream to write the report to
- * @param base the files or directories to report on
- * @param style an input stream representing the stylesheet to use for styling the report
- * @param pConfiguration current report configuration.
- * @throws IOException in case of I/O errors.
- * @throws TransformerConfigurationException in case of XML errors.
- * @throws InterruptedException in case of threading errors.
- * @throws RatException in case of internal errors.
- */
- public static void report(PrintStream out, IReportable base, final InputStream style,
- ReportConfiguration pConfiguration)
- throws IOException, TransformerConfigurationException, InterruptedException, RatException {
- report(new OutputStreamWriter(out), base, style, pConfiguration);
- }
- /**
- * Output a report that is styled using a defined stylesheet.
- *
- * @param out the writer to write the report to
- * @param base the files or directories to report on
- * @param style an input stream representing the stylesheet to use for styling the report
- * @param pConfiguration current report configuration.
- * @return the currently collected numerical statistics.
- * @throws IOException in case of I/O errors.
- * @throws TransformerConfigurationException in case of XML errors.
- * @throws InterruptedException in case of threading errors.
- * @throws RatException in case of internal errors.
- */
- public static ClaimStatistic report(Writer out, IReportable base, final InputStream style,
- ReportConfiguration pConfiguration)
- throws IOException, TransformerConfigurationException, InterruptedException, RatException {
- PipedReader reader = new PipedReader();
- PipedWriter writer = new PipedWriter(reader);
- ReportTransformer transformer = new ReportTransformer(out, style, reader);
- Thread transformerThread = new Thread(transformer);
- transformerThread.start();
- final ClaimStatistic statistic = report(base, writer, pConfiguration);
- writer.flush();
- writer.close();
- transformerThread.join();
- return statistic;
- }
-
- /**
- * @param container the files or directories to report on
- * @param out the writer to write the report to
- * @param pConfiguration current report configuration.
- * @return the currently collected numerical statistics.
- * @throws IOException in case of I/O errors.
- * @throws RatException in case of internal errors.
- */
- public static ClaimStatistic report(final IReportable container, final Writer out,
- ReportConfiguration pConfiguration) throws IOException, RatException {
- IXmlWriter writer = new XmlWriter(out);
- final ClaimStatistic statistic = new ClaimStatistic();
- RatReport report = XmlReportFactory.createStandardReport(writer, statistic, pConfiguration);
- report.startReport();
- container.run(report);
- report.endReport();
- writer.closeDocument();
- return statistic;
+ /**
+ * Compares its two arguments for order. Returns a negative integer, zero, or a
+ * positive integer as the first argument is less than, equal to, or greater
+ * than the second.
+ *
+ * @param opt1 The first Option to be compared.
+ * @param opt2 The second Option to be compared.
+ * @return a negative integer, zero, or a positive integer as the first argument
+ * is less than, equal to, or greater than the second.
+ */
+ @Override
+ public int compare(final Option opt1, final Option opt2) {
+ return getKey(opt1).compareToIgnoreCase(getKey(opt2));
+ }
}
}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/ReportConfiguration.java b/apache-rat-core/src/main/java/org/apache/rat/ReportConfiguration.java
index f4043c881..572a7f5e5 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/ReportConfiguration.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/ReportConfiguration.java
@@ -18,87 +18,439 @@
*/
package org.apache.rat;
-import org.apache.rat.analysis.IHeaderMatcher;
-import org.apache.rat.license.ILicenseFamily;
-
-import java.util.List;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Objects;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import java.util.function.Consumer;
+import org.apache.commons.io.filefilter.FalseFileFilter;
+import org.apache.commons.io.filefilter.IOFileFilter;
+import org.apache.commons.io.function.IOSupplier;
+import org.apache.rat.config.AddLicenseHeaders;
+import org.apache.rat.license.ILicense;
+import org.apache.rat.license.ILicenseFamily;
+import org.apache.rat.license.LicenseFamilySetFactory;
+import org.apache.rat.license.LicenseSetFactory;
+import org.apache.rat.license.LicenseSetFactory.LicenseFilter;
+import org.apache.rat.report.IReportable;
+import org.apache.rat.utils.Log;
+import org.apache.rat.utils.ReportingSet;
+import org.apache.rat.walker.NameBasedHiddenFileFilter;
/**
- * A configuration object is used by the frontend to invoke the
- * {@link Report}. Basically, the sole purpose of the frontends is
- * to create the configuration and invoke the {@link Report}.
+ * A configuration object is used by the front end to invoke the
+ * {@link Reporter}. The sole purpose of the front ends is to create the
+ * configuration and invoke the {@link Reporter}.
*/
public class ReportConfiguration {
- private IHeaderMatcher headerMatcher;
- private ILicenseFamily[] approvedLicenseNames;
+ private final ReportingSet families;
+ private final ReportingSet licenses;
+ private final SortedSet approvedLicenseCategories;
+ private final SortedSet removedLicenseCategories;
private boolean addingLicenses;
private boolean addingLicensesForced;
private String copyrightMessage;
- private boolean approveDefaultLicenses = true;
+ private IOSupplier out;
+ private boolean styleReport;
+ private IOSupplier styleSheet;
+ private IReportable reportable;
+ private FilenameFilter inputFileFilter;
+ private IOFileFilter directoryFilter;
+ private Log log;
+
+
+ /**
+ * Constructor
+ * @param log The Log implementation that messages will be written to.
+ */
+ public ReportConfiguration(Log log) {
+ this.log = log;
+ families = new ReportingSet<>(LicenseFamilySetFactory.emptyLicenseFamilySet()).setLog(log)
+ .setMsgFormat( s -> String.format("Duplicate LicenseFamily category: %s", s.getFamilyCategory()));
+ licenses = new ReportingSet<>(LicenseSetFactory.emptyLicenseSet()).setLog(log)
+ .setMsgFormat( s -> String.format( "Duplicate License %s (%s) of type %s", s.getName(), s.getId(), s.getLicenseFamily().getFamilyCategory()));
+ approvedLicenseCategories = new TreeSet<>();
+ removedLicenseCategories = new TreeSet<>();
+ directoryFilter = NameBasedHiddenFileFilter.HIDDEN;
+ styleReport = true;
+ }
+
+ /**
+ * Retrieves the Log that was provided in the constructor.
+ * @return the Log for the system.
+ */
+ public Log getLog() {
+ return log;
+ }
+ /**
+ * Set the log level for reporting collisions in the set of license families.
+ * NOTE: should be set before licenses or license families are added.
+ * @param level The log level to use.
+ */
+ public void logFamilyCollisions(Log.Level level) {
+ families.setLogLevel(level);
+ }
+
+ /**
+ * Sets the reporting option for duplicate license families.
+ * @param state The ReportingSet.Option to use for reporting.
+ */
+ public void familyDuplicateOption(ReportingSet.Options state) {
+ families.setDuplicateOption(state);
+ }
+
+ /**
+ * Sets the log level for reporting license collisions.
+ * @param level The log level.
+ */
+ public void logLicenseCollisions(Log.Level level) {
+ licenses.setLogLevel(level);
+ }
+
+ /**
+ * Sets the reporting option for duplicate licenses.
+ * @param state the ReportingSt.Option to use for reporting.
+ */
+ public void licenseDuplicateOption(ReportingSet.Options state) {
+ licenses.setDuplicateOption(state);
+ }
+
+ /**
+ * @return The filename filter for the potential input files.
+ */
+ public FilenameFilter getInputFileFilter() {
+ return inputFileFilter;
+ }
+
+ /**
+ * @param inputFileFilter the filename filter to filter the input files.
+ */
+ public void setInputFileFilter(FilenameFilter inputFileFilter) {
+ this.inputFileFilter = inputFileFilter;
+ }
+
+ public IOFileFilter getDirectoryFilter() {
+ return directoryFilter;
+ }
+
+ public void setDirectoryFilter(IOFileFilter directoryFilter) {
+ if (directoryFilter == null) {
+ this.directoryFilter = FalseFileFilter.FALSE;
+ } else {
+ this.directoryFilter = directoryFilter;
+ }
+ }
+
+ public void addDirectoryFilter(IOFileFilter directoryFilter) {
+ this.directoryFilter = this.directoryFilter.and(directoryFilter);
+ }
/**
- * @return whether default licenses shall be approved by default.
+ * @return the thing being reported on.
*/
- public boolean isApproveDefaultLicenses() {
- return approveDefaultLicenses;
+ public IReportable getReportable() {
+ return reportable;
}
- public void setApproveDefaultLicenses(boolean approveDefaultLicenses) {
- this.approveDefaultLicenses = approveDefaultLicenses;
+ /**
+ * @param reportable the thing being reported on.
+ */
+ public void setReportable(IReportable reportable) {
+ this.reportable = reportable;
}
/**
- * Returns the header matcher.
+ * @return the Supplier of the InputStream that is the XSLT style sheet to style
+ * the report with.
+ */
+ public IOSupplier getStyleSheet() {
+ return styleSheet;
+ }
+
+ /**
+ * Sets the style sheet for custom processing. The IOSupplier may be called
+ * multiple times, so the input stream must be able to be opened and closed
+ * multiple times.
+ *
+ * @param styleSheet the XSLT style sheet to style the report with.
+ */
+ public void setStyleSheet(IOSupplier styleSheet) {
+ this.styleSheet = styleSheet;
+ }
+
+ /**
+ * Adds the licenses and approved licenses from the defaults object to the
+ * configuration. Side effect: if the report should be styled and no
+ * style sheet has been set the plain stylesheet from the defaults will be used.
+ *
+ * @param defaults The defaults to set.
+ */
+ public void setFrom(Defaults defaults) {
+ addLicensesIfNotPresent(defaults.getLicenses(LicenseFilter.all));
+ addApprovedLicenseCategories(defaults.getLicenseIds(LicenseFilter.approved));
+ if (isStyleReport() && getStyleSheet() == null) {
+ setStyleSheet(Defaults.getPlainStyleSheet());
+ }
+ }
+
+ /**
+ *
+ * @param styleSheet the XSLT style sheet to style the report with.
+ */
+ public void setStyleSheet(File styleSheet) {
+ Objects.requireNonNull(styleSheet, "styleSheet file should not be null");
+ setStyleSheet(styleSheet.toURI());
+ }
+
+ /**
+ * Sets the style sheet for custom processing. The stylesheet may be opened
+ * multiple times so the URI must be capable of being opened multiple times.
+ *
+ * @param styleSheet the URI of the XSLT style sheet to style the report with.
+ */
+ public void setStyleSheet(URI styleSheet) {
+ Objects.requireNonNull(styleSheet, "styleSheet file should not be null");
+ try {
+ setStyleSheet(styleSheet.toURL());
+ } catch (MalformedURLException e) {
+ throw new ConfigurationException("Unable to process stylesheet", e);
+ }
+ }
+
+ /**
+ * Sets the style sheet for custom processing. The stylesheet may be opened
+ * multiple times so the URL must be capable of being opened multiple times.
+ *
+ * @param styleSheet the URL of the XSLT style sheet to style the report with.
+ */
+ public void setStyleSheet(URL styleSheet) {
+ Objects.requireNonNull(styleSheet, "styleSheet file should not be null");
+ setStyleSheet(styleSheet::openStream);
+ }
+
+ /**
+ * @return {@code true} if the XML report should be styled.
+ */
+ public boolean isStyleReport() {
+ return styleReport;
+ }
+
+ /**
+ * @param styleReport specifies whether the XML report should be styled.
+ */
+ public void setStyleReport(boolean styleReport) {
+ this.styleReport = styleReport;
+ }
+
+ /**
+ * Sets the supplier for the output stream. The supplier may be called multiple
+ * times to provide the stream. Suppliers should prepare streams that are
+ * appended to and that can be closed. If an {@code OutputStream} should not be
+ * closed consider wrapping it in a {@code NoCloseOutputStream}
+ *
+ * @param out The OutputStream supplier that provides the output stream to write
+ * the report to. A null value will use System.out.
+ * @see NoCloseOutputStream
+ */
+ public void setOut(IOSupplier out) {
+ this.out = out;
+ }
+
+ /**
+ * Sets the OutputStream supplier to use the specified file. The file may be
+ * opened and closed several times. File is opened in append mode.
+ *
+ * @see #setOut(IOSupplier)
+ * @param file The file to create the supplier with.
+ */
+ public void setOut(File file) {
+ Objects.requireNonNull(file, "output file should not be null");
+ setOut(() -> new FileOutputStream(file, true));
+ }
+
+ /**
+ * Returns the output stream supplier. If no stream has been set returns a
+ * supplier for System.out.
+ *
+ * @return The supplier of the output stream to write the report to.
+ */
+ public IOSupplier getOutput() {
+ return out == null ? () -> new NoCloseOutputStream(System.out) : out;
+ }
+
+ /**
+ * @return A supplier for a PrintWriter that wraps the output stream.
+ * @see #getOutput()
+ */
+ public IOSupplier getWriter() {
+ return () -> new PrintWriter(new OutputStreamWriter(getOutput().get(), StandardCharsets.UTF_8));
+ }
+
+ /**
+ * Adds a license to the list of licenses. Does not add the license to the list
+ * of approved licenses.
+ *
+ * @param license The license to add to the list of licenses.
+ */
+ public void addLicense(ILicense license) {
+ if (license != null) {
+ this.licenses.add(license);
+ this.families.addIfNotPresent(license.getLicenseFamily());
+ }
+ }
+
+ /**
+ * Adds a license to the list of licenses. Does not add the license to the list
+ * of approved licenses.
+ *
+ * @param builder The license builder to build and add to the list of licenses.
+ */
+ public ILicense addLicense(ILicense.Builder builder) {
+ if (builder != null) {
+ ILicense license = builder.build(families);
+ this.licenses.add(license);
+ return license;
+ }
+ return null;
+ }
+
+ /**
+ * Adds multiple licenses to the list of licenses. Does not add the licenses to
+ * the list of approved licenses.
*
- * @return the header matcher.
+ * @param licenses The licenses to add.
*/
- public IHeaderMatcher getHeaderMatcher() {
- return headerMatcher;
+ public void addLicenses(Collection licenses) {
+ this.licenses.addAll(licenses);
+ licenses.stream().map(ILicense::getLicenseFamily).forEach(families::add);
}
/**
- * Sets the header matcher.
+ * Adds multiple licenses to the list of licenses. Does not add the licenses to
+ * the list of approved licenses.
*
- * @param headerMatcher header matcher.
+ * @param licenses The licenses to add.
+ */
+ public void addLicensesIfNotPresent(Collection licenses) {
+ this.licenses.addAllIfNotPresent(licenses);
+ licenses.stream().map(ILicense::getLicenseFamily).forEach(families::addIfNotPresent);
+ }
+
+ /**
+ * Adds a license family to the list of families. Does not add the family to the
+ * list of approved licenses.
+ *
+ * @param family The license family to add to the list of license families.
*/
- public void setHeaderMatcher(IHeaderMatcher headerMatcher) {
- this.headerMatcher = headerMatcher;
+ public void addFamily(ILicenseFamily family) {
+ if (family != null) {
+ this.families.add(family);
+ }
}
/**
- * Returns the set of approved license names.
+ * Adds a license family to the list of families. Does not add the family to the
+ * list of approved licenses.
+ *
+ * @param builder The licenseFamily.Builder to build and add to the list of
+ * licenses.
+ */
+ public void addFamily(ILicenseFamily.Builder builder) {
+ if (builder != null) {
+ this.families.add(builder.build());
+ }
+ }
+
+ /**
+ * Adds multiple families to the list of license families. Does not add the
+ * licenses to the list of approved licenses.
*
- * @return the set of approved license names.
+ * @param families The license families to add.
*/
- public ILicenseFamily[] getApprovedLicenseNames() {
- return approvedLicenseNames;
+ public void addFamilies(Collection families) {
+ this.families.addAll(families);
}
/**
- * Sets the set of approved license names.
+ * Adds an ILicenseFamily to the list of approved licenses.
*
- * @param approvedLicenseNames set of approved license names.
+ * @param approvedILicenseFamily the LicenseFamily to add.
*/
- public void setApprovedLicenseNames(ILicenseFamily[] approvedLicenseNames) {
- this.approvedLicenseNames = approvedLicenseNames;
+ public void addApprovedLicenseCategory(ILicenseFamily approvedILicenseFamily) {
+ approvedLicenseCategories.add(approvedILicenseFamily.getFamilyCategory());
}
/**
- * Sets the set of approved license names (convenience).
+ * Adds a license family category (id) to the list of approved licenses
+ *
+ * @param familyCategory the category to add.
+ */
+ public void addApprovedLicenseCategory(String familyCategory) {
+ approvedLicenseCategories.add(ILicenseFamily.makeCategory(familyCategory));
+ }
+
+ /**
+ * Adds a collection of license family categories to the set of approved license
+ * names.
*
- * @param approvedLicenseNames set of approved license names.
+ * @param approvedLicenseCategories set of approved license categories.
*/
- public void setApprovedLicenseNames(List approvedLicenseNames) {
- if (approvedLicenseNames != null && approvedLicenseNames.size() > 0) {
- setApprovedLicenseNames(approvedLicenseNames.toArray(new ILicenseFamily[approvedLicenseNames.size()]));
- }
+ public void addApprovedLicenseCategories(Collection approvedLicenseCategories) {
+ approvedLicenseCategories.forEach(this::addApprovedLicenseCategory);
}
/**
- * @return If Rat is adding license headers: Returns the optional
- * copyright message. This value is ignored, if no
- * license headers are added.
+ * Adds a license family category to the list of approved licenses. Once a
+ * license has been removed from the approved list it cannot be re-added
+ *
+ * @param familyCategory the category to add.
+ */
+ public void removeApprovedLicenseCategory(String familyCategory) {
+ removedLicenseCategories.add(ILicenseFamily.makeCategory(familyCategory));
+ }
+
+ /**
+ * Removes a license family category from the list of approved licenses.
+ * Once a license has been removed from the approved list it cannot be
+ * re-added
+ *
+ * @param familyCategory the family category to remove.
+ */
+ public void removeApprovedLicenseCategories(Collection familyCategory) {
+ familyCategory.forEach(this::removeApprovedLicenseCategory);
+ }
+
+ /**
+ * Gets the SortedSet of approved license categories. Once a license has
+ * been removed from the approved list it cannot be re-added
+ *
+ * @return the Sorted set of approved license categories.
+ */
+ public SortedSet getApprovedLicenseCategories() {
+ SortedSet result = new TreeSet<>(approvedLicenseCategories);
+ result.removeAll(removedLicenseCategories);
+ return result;
+ }
+
+ /**
+ * Returns the optional license copyright being added if RAT is adding headers.
+ * This value is ignored, if no license headers are added.
+ *
+ * @return the optional copyright message.
* @see #isAddingLicenses()
*/
public String getCopyrightMessage() {
@@ -106,21 +458,20 @@ public String getCopyrightMessage() {
}
/**
- * If Rat is adding license headers: Sets the optional
- * copyright message. This value is ignored, if no
- * license headers are added.
+ * Sets the optional copyright message used if RAT is adding license headers.
+ * This value is ignored, if no license headers are added.
*
* @param copyrightMessage message to set.
- * @see #setAddingLicenses(boolean)
+ * @see #isAddingLicenses()
*/
public void setCopyrightMessage(String copyrightMessage) {
this.copyrightMessage = copyrightMessage;
}
/**
- * @return If Rat is adding license headers: Returns, whether adding
- * license headers is enforced. This value is ignored, if no
- * license headers are added.
+ * This value is ignored if RAT is not adding licenses.
+ *
+ * @return {@code true} if RAT is forcing the adding license headers.
* @see #isAddingLicenses()
*/
public boolean isAddingLicensesForced() {
@@ -128,19 +479,7 @@ public boolean isAddingLicensesForced() {
}
/**
- * If Rat is adding license headers: Sets, whether adding
- * license headers is enforced. This value is ignored, if no
- * license headers are added.
- *
- * @param addingLicensesForced enable/disable forcibly adding licenses.
- * @see #isAddingLicenses()
- */
- public void setAddingLicensesForced(boolean addingLicensesForced) {
- this.addingLicensesForced = addingLicensesForced;
- }
-
- /**
- * @return Returns, whether Rat should add missing license headers.
+ * @return whether RAT should add missing license headers.
* @see #isAddingLicensesForced()
* @see #getCopyrightMessage()
*/
@@ -149,14 +488,137 @@ public boolean isAddingLicenses() {
}
/**
- * Returns, whether Rat should add missing license headers.
- *
- * @param addingLicenses enables/disables adding of licenses.
- * @see #setAddingLicensesForced(boolean)
+ * Sets whether RAT should enable, disable, or force the adding of license
+ * headers.
+ *
+ * @param addLicenseHeaders enables/disables or forces adding of licenses
+ * headers.
+ * @see #isAddingLicenses()
* @see #setCopyrightMessage(String)
*/
- public void setAddingLicenses(boolean addingLicenses) {
- this.addingLicenses = addingLicenses;
+ public void setAddLicenseHeaders(AddLicenseHeaders addLicenseHeaders) {
+ addingLicenses = false;
+ addingLicensesForced = false;
+ switch (addLicenseHeaders) {
+ case FALSE:
+ // do nothing
+ break;
+ case FORCED:
+ addingLicensesForced = true;
+ // fall through
+ case TRUE:
+ addingLicenses = true;
+ break;
+ }
+ }
+
+ /**
+ * Gets a set Licenses of depending on the {@code filter} if filter is set:
+ *
+ * {@code all} - All licenses will be returned.
+ * {@code approved} - Only approved licenses will be returned
+ * {@code none} - No licenses will be returned
+ *
+ *
+ * @param filter The license filter.
+ * @return The set of defined licenses.
+ */
+ public SortedSet getLicenses(LicenseFilter filter) {
+ switch (filter) {
+ case all:
+ return Collections.unmodifiableSortedSet(licenses);
+ case approved:
+ return new LicenseSetFactory(licenses, getApprovedLicenseCategories()).getLicenses(filter);
+ case none:
+ default:
+ return LicenseSetFactory.emptyLicenseSet();
+ }
+ }
+
+ /**
+ * Gets a sorted set of ILicenseFamily objects based on {@code filter}. if
+ * filter is set:
+ *
+ * {@code all} - All licenses families will be returned.
+ * {@code approved} - Only approved license families will be returned
+ * {@code none} - No license families will be returned
+ *
+ *
+ * @param filter The license filter.
+ * @return The set of defined licenses.
+ */
+ public SortedSet getLicenseFamilies(LicenseFilter filter) {
+ return new LicenseFamilySetFactory(families, getApprovedLicenseCategories()).getFamilies(filter);
+ }
+
+ /**
+ * Validates that the configuration is valid.
+ *
+ * @param logger String consumer to log warning messages to.
+ */
+ public void validate(Consumer logger) {
+ if (reportable == null) {
+ throw new ConfigurationException("Reportable may not be null");
+ }
+ if (licenses.isEmpty()) {
+ throw new ConfigurationException("You must specify at least one license");
+ }
+ if (styleSheet != null && !isStyleReport()) {
+ logger.accept("Ignoring stylesheet because styling is not selected");
+ }
+ if (styleSheet == null && isStyleReport()) {
+ throw new ConfigurationException("Stylesheet must be specified if report styling is selected");
+ }
}
+ /**
+ * A wrapper around an output stream that does not close the output stream.
+ */
+ public static class NoCloseOutputStream extends OutputStream {
+ private final OutputStream delegate;
+
+ public NoCloseOutputStream(OutputStream delegate) {
+ this.delegate = delegate;
+ }
+
+ @Override
+ public void write(int arg0) throws IOException {
+ delegate.write(arg0);
+ }
+
+ @Override
+ public void close() throws IOException {
+ this.delegate.flush();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return delegate.equals(obj);
+ }
+
+ @Override
+ public void flush() throws IOException {
+ delegate.flush();
+ }
+
+ @Override
+ public int hashCode() {
+ return delegate.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return delegate.toString();
+ }
+
+ @Override
+ public void write(byte[] arg0, int arg1, int arg2) throws IOException {
+ delegate.write(arg0, arg1, arg2);
+ }
+
+ @Override
+ public void write(byte[] b) throws IOException {
+ delegate.write(b);
+ }
+ }
}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/Reporter.java b/apache-rat-core/src/main/java/org/apache/rat/Reporter.java
new file mode 100644
index 000000000..7a5feb038
--- /dev/null
+++ b/apache-rat-core/src/main/java/org/apache/rat/Reporter.java
@@ -0,0 +1,138 @@
+/*
+ * 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;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PipedReader;
+import java.io.PipedWriter;
+import java.io.PrintWriter;
+import java.io.Writer;
+
+import org.apache.rat.api.RatException;
+import org.apache.rat.license.LicenseSetFactory.LicenseFilter;
+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;
+
+/**
+ * Class that executes the report as defined in a ReportConfiguration.
+ */
+public class Reporter {
+
+ /*
+ * Format used for listing license families
+ */
+ private static final String LICENSE_FAMILY_FORMAT = "\t%s: %s\n";
+
+ /**
+ * Format used for listing licenses.
+ */
+ private static final String LICENSE_FORMAT = "%s:\t%s\n\t\t%s\n";
+
+ private Reporter() {
+ // Do not instantiate
+ }
+
+ /**
+ * Execute the report.
+ *
+ * @param configuration The report configuration.
+ * @return the currently collected numerical statistics.
+ * @throws Exception in case of errors.
+ */
+ public static ClaimStatistic report(ReportConfiguration configuration) throws Exception {
+ if (configuration.getReportable() != null) {
+ if (configuration.isStyleReport()) {
+ try (PipedReader reader = new PipedReader();
+ PipedWriter writer = new PipedWriter(reader);
+ InputStream style = configuration.getStyleSheet().get();
+ PrintWriter reportWriter = configuration.getWriter().get();) {
+ ReportTransformer transformer = new ReportTransformer(reportWriter, style, reader);
+ Thread transformerThread = new Thread(transformer);
+ transformerThread.start();
+ final ClaimStatistic statistic = report(writer, configuration);
+ writer.flush();
+ writer.close();
+ transformerThread.join();
+ return statistic;
+ }
+ }
+ try (Writer writer = configuration.getWriter().get()) {
+ return report(writer, configuration);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Execute the report.
+ * @param outputWriter the writer to send output to.
+ * @param configuration The report configuration.
+ * @return the currently collected numerical statistics.
+ * @throws IOException in case of I/O errors.
+ * @throws RatException in case of internal errors.
+ */
+ private static ClaimStatistic report(Writer outputWriter, ReportConfiguration configuration)
+ throws IOException, RatException {
+ try (IXmlWriter writer = new XmlWriter(outputWriter)) {
+ final ClaimStatistic statistic = new ClaimStatistic();
+ RatReport report = XmlReportFactory.createStandardReport(writer, statistic, configuration);
+ report.startReport();
+ configuration.getReportable().run(report);
+ report.endReport();
+
+ return statistic;
+ } catch (Exception e) {
+ throw new IOException(e);
+ }
+ }
+
+ /**
+ * lists the license families information on the configured output stream.
+ * @param configuration The configuration for the system
+ * @throws IOException if PrintWriter can not be retrieved from configuration.
+ */
+ public static void listLicenseFamilies(ReportConfiguration configuration, LicenseFilter filter) throws IOException {
+ try (PrintWriter pw = configuration.getWriter().get()) {
+ pw.format("Families (%s):%n", filter);
+ configuration.getLicenseFamilies(filter)
+ .forEach(x -> pw.format(LICENSE_FAMILY_FORMAT, x.getFamilyCategory(), x.getFamilyName()));
+ pw.println();
+ }
+ }
+
+ /**
+ * lists the licenses on the configured output stream.
+ * @param configuration The configuration for the system
+ * @throws IOException if PrintWriter can not be retrieved from configuration.
+ */
+ public static void listLicenses(ReportConfiguration configuration, LicenseFilter filter) throws IOException {
+ try (PrintWriter pw = configuration.getWriter().get()) {
+ pw.format("Licenses (%s):%n", filter);
+ configuration.getLicenses(filter)
+ .forEach(lic -> pw.format(LICENSE_FORMAT, lic.getLicenseFamily().getFamilyCategory(),
+ lic.getLicenseFamily().getFamilyName(), lic.getNotes()));
+ pw.println();
+ }
+ }
+
+}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/DefaultAnalyserFactory.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/DefaultAnalyserFactory.java
index c8d39ffc8..06cbe8d3a 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/analysis/DefaultAnalyserFactory.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/DefaultAnalyserFactory.java
@@ -15,9 +15,12 @@
* KIND, either express or implied. See the License for the *
* specific language governing permissions and limitations *
* under the License. *
- */
+ */
package org.apache.rat.analysis;
+import java.util.Collection;
+
+import org.apache.rat.ConfigurationException;
import org.apache.rat.api.Document;
import org.apache.rat.api.MetaData;
import org.apache.rat.document.IDocumentAnalyser;
@@ -25,41 +28,65 @@
import org.apache.rat.document.impl.guesser.ArchiveGuesser;
import org.apache.rat.document.impl.guesser.BinaryGuesser;
import org.apache.rat.document.impl.guesser.NoteGuesser;
+import org.apache.rat.license.ILicense;
+import org.apache.rat.utils.Log;
+import org.apache.rat.utils.Log.Level;
/**
* Creates default analysers.
- *
*/
public class DefaultAnalyserFactory {
-
- public static final IDocumentAnalyser createDefaultAnalyser(final IHeaderMatcher matcher) {
-
- return new DefaultAnalyser(matcher);
+
+ /**
+ * Creates a DocumentAnalyser from a collection of ILicenses.
+ * @param licenses The licenses to use in the Analyser.
+ * @return A document analyser that uses the provides licenses.
+ */
+ public static IDocumentAnalyser createDefaultAnalyser(Log log, Collection licenses) {
+ if (licenses.isEmpty()) {
+ throw new ConfigurationException("At least one license must be defined");
+ }
+ log.debug("Licenses in Test");
+ licenses.forEach(log::debug);
+ return new DefaultAnalyser(log, new LicenseCollection(licenses));
}
-
+
+ /**
+ * A DocumentAnalyser for the license
+ */
private final static class DefaultAnalyser implements IDocumentAnalyser {
- private final IHeaderMatcher matcher;
-
- public DefaultAnalyser(final IHeaderMatcher matcher) {
- super();
- this.matcher = matcher;
+ /**
+ * The license to analyze
+ */
+ private final ILicense license;
+ /** The log to use */
+ private final Log log;
+
+ /**
+ * Constructs a DocumentAnalyser for the specified license.
+ * @param license The license to analyse
+ */
+ public DefaultAnalyser(final Log log, final ILicense license) {
+ this.license = license;
+ this.log = log;
}
- public void analyse(Document subject) throws RatDocumentAnalysisException {
+ @Override
+ public void analyse(Document document) throws RatDocumentAnalysisException {
final MetaData.Datum documentCategory;
- if (NoteGuesser.isNote(subject)) {
+ if (NoteGuesser.isNote(document)) {
documentCategory = MetaData.RAT_DOCUMENT_CATEGORY_DATUM_NOTICE;
- } else if (ArchiveGuesser.isArchive(subject)) {
+ } else if (ArchiveGuesser.isArchive(document)) {
documentCategory = MetaData.RAT_DOCUMENT_CATEGORY_DATUM_ARCHIVE;
- } else if (BinaryGuesser.isBinary(subject)) {
+ } else if (BinaryGuesser.isBinary(document)) {
documentCategory = MetaData.RAT_DOCUMENT_CATEGORY_DATUM_BINARY;
} else {
documentCategory = MetaData.RAT_DOCUMENT_CATEGORY_DATUM_STANDARD;
- final DocumentHeaderAnalyser headerAnalyser = new DocumentHeaderAnalyser(matcher);
- headerAnalyser.analyse(subject);
+ final DocumentHeaderAnalyser headerAnalyser = new DocumentHeaderAnalyser(log, license);
+ headerAnalyser.analyse(document);
}
- subject.getMetaData().set(documentCategory);
- }
+ document.getMetaData().set(documentCategory);
+ }
}
}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/DocumentHeaderAnalyser.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/DocumentHeaderAnalyser.java
index e9f658c60..9534db9e7 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/analysis/DocumentHeaderAnalyser.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/DocumentHeaderAnalyser.java
@@ -15,40 +15,54 @@
* KIND, either express or implied. See the License for the *
* specific language governing permissions and limitations *
* under the License. *
- */
+ */
package org.apache.rat.analysis;
-import org.apache.commons.io.IOUtils;
+import java.io.IOException;
+import java.io.Reader;
+
import org.apache.rat.api.Document;
import org.apache.rat.document.IDocumentAnalyser;
import org.apache.rat.document.RatDocumentAnalysisException;
+import org.apache.rat.license.ILicense;
+import org.apache.rat.utils.Log;
-import java.io.IOException;
-import java.io.Reader;
+import static java.lang.String.format;
+
+/**
+ * A Document analyzer that analyses document headers for a license.
+ */
+class DocumentHeaderAnalyser implements IDocumentAnalyser {
-public class DocumentHeaderAnalyser implements IDocumentAnalyser {
+ /**
+ * The license to analyse
+ */
+ private final ILicense license;
+ /** the logger to use */
+ private final Log log;
- private final IHeaderMatcher matcher;
-
- public DocumentHeaderAnalyser(final IHeaderMatcher matcher) {
+ /**
+ * Constructs the HeaderAnalyser for the specific license.
+ *
+ * @param license The license to analyse
+ */
+ public DocumentHeaderAnalyser(final Log log, final ILicense license) {
super();
- this.matcher = matcher;
+ this.license = license;
+ this.log = log;
}
+ @Override
public void analyse(Document document) throws RatDocumentAnalysisException {
- Reader reader = null;
- try {
- reader = document.reader();
- // TODO: worker function should be moved into this class
- HeaderCheckWorker worker = new HeaderCheckWorker(reader, matcher, document);
+ try (Reader reader = document.reader()) {
+ log.debug(format("Processing: %s", document));
+ HeaderCheckWorker worker = new HeaderCheckWorker(reader, license, document);
worker.read();
} catch (IOException e) {
throw new RatDocumentAnalysisException("Cannot read header", e);
} catch (RatHeaderAnalysisException e) {
throw new RatDocumentAnalysisException("Cannot analyse header", e);
- } finally {
- IOUtils.closeQuietly(reader);
}
- }
+ }
}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/HeaderCheckWorker.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/HeaderCheckWorker.java
index b7b51f7ba..01ef13b71 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/analysis/HeaderCheckWorker.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/HeaderCheckWorker.java
@@ -18,84 +18,110 @@
* under the License. *
*/
-import org.apache.commons.io.IOUtils;
-import org.apache.rat.api.Document;
-import org.apache.rat.api.MetaData;
-
import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
+import java.util.Objects;
+
+import org.apache.rat.ConfigurationException;
+import org.apache.rat.api.Document;
+import org.apache.rat.api.MetaData;
+import org.apache.rat.license.ILicense;
/**
- * Reads from a stream to check license.
- * Note that this class is not thread safe.
+ * Reads from a stream to check license.
+ *
+ * Note that this class is not thread safe.
+ *
*/
class HeaderCheckWorker {
+ /* TODO revisit this class. It is only used in one place and can be moved inline as the DocumentHeaderAnalyser states.
+ * However, it may also be possible to make the entire set threadsafe so that multiple files can be checked simultaneously.
+ */
+ /**
+ * The default number of header lines to read while looking for the license
+ * information.
+ */
public static final int DEFAULT_NUMBER_OF_RETAINED_HEADER_LINES = 50;
private final int numberOfRetainedHeaderLines;
private final BufferedReader reader;
- private final IHeaderMatcher matcher;
- private final Document subject;
-
- private boolean match = false;
+ private final ILicense license;
+ private final Document document;
private int headerLinesToRead;
private boolean finished = false;
/**
- * Convenience constructor wraps given Reader
- * in a BufferedReader
.
- * @param reader a Reader
for the content, not null
- * @param name the name of the checked content, possibly null
+ * Convenience constructor wraps given Reader
in a
+ * BufferedReader
.
+ *
+ * @param reader The reader on the document. not null.
+ * @param license The license to check against. not null.
+ * @param name The document that is being checked. possibly null
*/
- public HeaderCheckWorker(Reader reader, final IHeaderMatcher matcher, final Document name) {
- this(new BufferedReader(reader), matcher, name);
- }
-
- public HeaderCheckWorker(BufferedReader reader, final IHeaderMatcher matcher,
- final Document name) {
- this(reader, DEFAULT_NUMBER_OF_RETAINED_HEADER_LINES, matcher, name);
+ public HeaderCheckWorker(Reader reader, final ILicense license, final Document name) {
+ this(reader, DEFAULT_NUMBER_OF_RETAINED_HEADER_LINES, license, name);
}
- public HeaderCheckWorker(BufferedReader reader, int numberOfRetainedHeaderLine, final IHeaderMatcher matcher,
+ /**
+ * Constructs a check worker for the license against the specified document.
+ *
+ * @param reader The reader on the document. not null.
+ * @param numberOfRetainedHeaderLine the maximum number of lines to read to find
+ * the license information.
+ * @param license The license to check against. not null.
+ * @param name The document that is being checked. possibly null
+ */
+ public HeaderCheckWorker(Reader reader, int numberOfRetainedHeaderLine, final ILicense license,
final Document name) {
- this.reader = reader;
+ Objects.requireNonNull(reader, "Reader may not be null");
+ Objects.requireNonNull(license, "License may not be null");
+ if (numberOfRetainedHeaderLine < 0) {
+ throw new ConfigurationException("numberOfRetainedHeaderLine may not be less than zero");
+ }
+ this.reader = reader instanceof BufferedReader ? (BufferedReader) reader : new BufferedReader(reader);
this.numberOfRetainedHeaderLines = numberOfRetainedHeaderLine;
- this.matcher = matcher;
- this.subject = name;
+ this.license = license;
+ this.document = name;
}
+ /**
+ * @return {@code true} if the header check is complete.
+ */
public boolean isFinished() {
return finished;
}
+ /**
+ * Read the input and perform the header check.
+ *
+ * @throws RatHeaderAnalysisException on IO Exception.
+ */
public void read() throws RatHeaderAnalysisException {
if (!finished) {
final StringBuilder headers = new StringBuilder();
headerLinesToRead = numberOfRetainedHeaderLines;
try {
- while(readLine(headers)) {
+ while (readLine(headers)) {
// do nothing
}
- if (!match) {
- final String notes = headers.toString();
- final MetaData metaData = subject.getMetaData();
- metaData.set(new MetaData.Datum(MetaData.RAT_URL_HEADER_SAMPLE, notes));
- metaData.set(new MetaData.Datum(MetaData.RAT_URL_HEADER_CATEGORY, MetaData.RAT_LICENSE_FAMILY_CATEGORY_VALUE_UNKNOWN));
- metaData.set(MetaData.RAT_LICENSE_FAMILY_NAME_DATUM_UNKNOWN);
+ if (license.finalizeState().asBoolean()) {
+ document.getMetaData().reportOnLicense(license);
+ } else {
+ document.getMetaData().reportOnLicense(UnknownLicense.INSTANCE);
+ document.getMetaData().set(new MetaData.Datum(MetaData.RAT_URL_HEADER_SAMPLE, headers.toString()));
}
} catch (IOException e) {
- throw new RatHeaderAnalysisException("Cannot read header for " + subject, e);
+ throw new RatHeaderAnalysisException("Cannot read header for " + document, e);
}
- IOUtils.closeQuietly(reader);
- matcher.reset();
+ license.reset();
}
finished = true;
}
- boolean readLine(StringBuilder headers) throws IOException, RatHeaderAnalysisException {
+ boolean readLine(StringBuilder headers) throws IOException {
String line = reader.readLine();
boolean result = line != null;
if (result) {
@@ -103,8 +129,15 @@ boolean readLine(StringBuilder headers) throws IOException, RatHeaderAnalysisExc
headers.append(line);
headers.append('\n');
}
- match = matcher.match(subject, line);
- result = !match;
+ switch (license.matches(line)) {
+ case t:
+ result = false;
+ break;
+ case f:
+ case i:
+ result = true;
+ break;
+ }
}
return result;
}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/IHeaderMatcher.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/IHeaderMatcher.java
index 3ec499dcd..a4aacf8f6 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/analysis/IHeaderMatcher.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/IHeaderMatcher.java
@@ -15,31 +15,167 @@
* KIND, either express or implied. See the License for the *
* specific language governing permissions and limitations *
* under the License. *
- */
+ */
package org.apache.rat.analysis;
-import org.apache.rat.api.Document;
+import org.apache.rat.configuration.builders.AllBuilder;
+import org.apache.rat.configuration.builders.AnyBuilder;
+import org.apache.rat.configuration.builders.CopyrightBuilder;
+import org.apache.rat.configuration.builders.MatcherRefBuilder;
+import org.apache.rat.configuration.builders.NotBuilder;
+import org.apache.rat.configuration.builders.RegexBuilder;
+import org.apache.rat.configuration.builders.SpdxBuilder;
+import org.apache.rat.configuration.builders.TextBuilder;
/**
- * Matches text headers to known licenses.
+ * Performs explicit checks against a line from the header of a file.
+ * For implementations that need to check multiple lines the implementation must cache the earlier lines.
*/
public interface IHeaderMatcher {
+ /**
+ * The state of the matcher.
+ *
+ * {@code t} - The matcher has located a match.
+ * {@code f} - The matcher has determined that it will not match the
+ * document.
+ * {@code i} - The matcher can not yet determine if a matche is made or
+ * not.
+ *
+ */
+ enum State {
+ t("true"), f("false"), i("indeterminent");
+
+ private final String desc;
+
+ State(String desc) {
+ this.desc = desc;
+ }
+
+ public boolean asBoolean() {
+ switch (this) {
+ case t : return true;
+ case f : return false;
+ default:
+ case i : throw new IllegalStateException( "'asBoolean' should never be called on an indeterminate state");
+ }
+ }
+
+ @Override
+ public String toString() {
+ return super.toString()+" "+desc;
+ }
+ }
/**
- * Resets this matches.
- * Subsequent calls to {@link #match} will accumulate new text.
+ * Get the identifier for this matcher.
+ * All matchers must have unique identifiers
+ *
+ * @return the Identifier for this matcher.
+ */
+ String getId();
+
+ /**
+ * Resets this state {@code State.i}.
+ * If text is being cached this method should clear that cache.
*/
void reset();
/**
- * Matches the text accumulated to licenses.
- * TODO probably a poor design choice - hope to fix later
- * @param subject current document.
- * @param line next line of text, not null
+ * Attempts to match {@code line} and returns the State after
+ * the match is attempted.
*
- * @return whether the current line matched in the document.
+ * @param line next line of text, not null
+ * @return the new state after the matching was attempted.
+ */
+ State matches(String line);
+
+ /**
+ * Gets the final state for this matcher. This is called after the EOF on the
+ * input. At this point there should be no matchers in an {@code State.i} state.
+ */
+ State finalizeState();
+
+ /**
+ * Gets the the current state of the matcher. All matchers should be
+ * in {@code State.i} at the start.
*
- * @throws RatHeaderAnalysisException in case of internal RAT errors.
+ * @return the current state of the matcher.
*/
- boolean match(Document subject, String line) throws RatHeaderAnalysisException;
+ State currentState();
+
+ /**
+ * An IHeaderMatcher builder.
+ */
+ @FunctionalInterface
+ interface Builder {
+ /**
+ * Build the IHeaderMatcher.
+ * @return a new IHeaderMatcher.
+ */
+ IHeaderMatcher build();
+
+ /**
+ * @return an instance of the standard TextBuilder.
+ * @see TextBuilder
+ */
+ static TextBuilder text() {
+ return new TextBuilder();
+ }
+
+ /**
+ * @return an instance of the standard AnyBuilder.
+ * @see AnyBuilder
+ */
+ static AnyBuilder any() {
+ return new AnyBuilder();
+ }
+
+ /**
+ * @return an instance of the standard AllBuilder.
+ * @see AllBuilder
+ */
+ static AllBuilder all() {
+ return new AllBuilder();
+ }
+
+ /**
+ * @return an instance of the standard CopyrightBuilder.
+ * @see CopyrightBuilder
+ */
+ static CopyrightBuilder copyright() {
+ return new CopyrightBuilder();
+ }
+
+ /**
+ * @return an instance of the standard SpdxBuilder.
+ * @see SpdxBuilder
+ */
+ static SpdxBuilder spdx() {
+ return new SpdxBuilder();
+ }
+
+ /**
+ * @return an instance of the standard MatcherRefBuilder.
+ * @see MatcherRefBuilder
+ */
+ static MatcherRefBuilder matcherRef() {
+ return new MatcherRefBuilder();
+ }
+
+ /**
+ * @return an instance of the standard NotBuilder.
+ * @see NotBuilder
+ */
+ static NotBuilder not() {
+ return new NotBuilder();
+ }
+
+ /**
+ * @return an instance of the standard RegexBuilder.
+ * @see RegexBuilder
+ */
+ static RegexBuilder regex() {
+ return new RegexBuilder();
+ }
+ }
}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/LicenseCollection.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/LicenseCollection.java
new file mode 100644
index 000000000..57ee9de3d
--- /dev/null
+++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/LicenseCollection.java
@@ -0,0 +1,134 @@
+/*
+ * 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.analysis;
+
+import java.util.Collection;
+import java.util.Collections;
+
+import org.apache.rat.analysis.matchers.AbstractMatcherContainer;
+import org.apache.rat.license.ILicense;
+import org.apache.rat.license.ILicenseFamily;
+
+/**
+ * A collection of ILicenses that acts as a single License for purposes of Analysis.
+ *
+ * This class process each license in turn on each {@code matches(String)} call. When a match is found the
+ * ILicenseFamily for the matching license is captured and used as the family for this license. If no matching
+ * license has been found the default {@code dummy} license category is used.
+ */
+class LicenseCollection extends AbstractMatcherContainer implements ILicense {
+
+ private static final ILicenseFamily DEFAULT = ILicenseFamily.builder().setLicenseFamilyCategory("Dummy")
+ .setLicenseFamilyName("HeaderMatcherCollection default license family").build();
+ private final Collection enclosed;
+ private ILicense matchingLicense;
+ private State lastState;
+
+ /**
+ * Constructs the LicenseCollection from the provided ILicense collection.
+ * @param enclosed The collection of ILicenses to compose this License implementation from. May not be null.
+ */
+ public LicenseCollection(Collection enclosed) {
+ super(enclosed);
+ this.enclosed = Collections.unmodifiableCollection(enclosed);
+ this.matchingLicense = null;
+ this.lastState = State.i;
+ }
+
+ @Override
+ public String getId() {
+ return "Default License Collection";
+ }
+
+ @Override
+ public void reset() {
+ enclosed.forEach(ILicense::reset);
+ this.lastState = State.i;
+ this.matchingLicense = null;
+ }
+
+ @Override
+ public State matches(String line) {
+ State dflt = State.f;
+ for (ILicense license : enclosed) {
+ switch (license.matches(line)) {
+ case t:
+ this.matchingLicense = license;
+ lastState = State.t;
+ return State.t;
+ case i:
+ dflt = State.i;
+ break;
+ default:
+ // do nothing
+ break;
+ }
+ }
+ lastState = dflt;
+ return dflt;
+ }
+
+ @Override
+ public State currentState() {
+ if (lastState == State.t) {
+ return lastState;
+ }
+ for (ILicense license : enclosed) {
+ switch (license.currentState()) {
+ case t:
+ this.matchingLicense = license;
+ lastState = State.t;
+ return lastState;
+ case i:
+ lastState = State.i;
+ return lastState;
+ case f:
+ // do nothing;
+ break;
+ }
+ }
+ lastState = State.f;
+ return lastState;
+ }
+
+ @Override
+ public int compareTo(ILicense arg0) {
+ return getLicenseFamily().compareTo(arg0.getLicenseFamily());
+ }
+
+ @Override
+ public ILicenseFamily getLicenseFamily() {
+ return matchingLicense == null ? DEFAULT : matchingLicense.getLicenseFamily();
+ }
+
+ @Override
+ public String getNotes() {
+ return matchingLicense == null ? null : matchingLicense.getNotes();
+ }
+
+ @Override
+ public String derivedFrom() {
+ return matchingLicense == null ? null : matchingLicense.derivedFrom();
+ }
+
+ @Override
+ public String getName() {
+ return getLicenseFamily().getFamilyName();
+ }
+}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/UnknownLicense.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/UnknownLicense.java
new file mode 100644
index 000000000..113771b09
--- /dev/null
+++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/UnknownLicense.java
@@ -0,0 +1,97 @@
+/*
+ * 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.analysis;
+
+import org.apache.rat.license.ILicense;
+import org.apache.rat.license.ILicenseFamily;
+import org.apache.rat.license.ILicenseFamilyBuilder;
+
+/**
+ * An ILicense implementation that represents an unknown license.
+ *
+ * The UnknownLicense is used during processing to report that a document license can not be determined.
+ *
+ */
+public class UnknownLicense implements ILicense {
+
+ /**
+ * The single instance of this class.
+ */
+ static final UnknownLicense INSTANCE = new UnknownLicense();
+
+ private final ILicenseFamily family ;
+
+ /**
+ * Do not allow other constructions.
+ */
+ private UnknownLicense() {
+ family = new ILicenseFamilyBuilder().setLicenseFamilyCategory("?????")
+ .setLicenseFamilyName("Unknown license").build();
+ }
+
+ @Override
+ public String getId() {
+ return "?????";
+ }
+
+ @Override
+ public void reset() {
+ // do nothing
+ }
+
+ @Override
+ public State matches(String line) {
+ return State.f;
+ }
+
+ @Override
+ public State finalizeState() {
+ return State.f;
+ }
+
+ @Override
+ public State currentState() {
+ return State.f;
+ }
+
+ @Override
+ public int compareTo(ILicense arg0) {
+ return getLicenseFamily().compareTo(arg0.getLicenseFamily());
+ }
+
+ @Override
+ public ILicenseFamily getLicenseFamily() {
+ return family;
+ }
+
+ @Override
+ public String getNotes() {
+ return null;
+ }
+
+ @Override
+ public String getName() {
+ return family.getFamilyName();
+ }
+
+ @Override
+ public String derivedFrom() {
+ return null;
+ }
+}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/generation/GeneratedLicenseNotRequired.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/generation/GeneratedLicenseNotRequired.java
deleted file mode 100644
index 9003fbd0b..000000000
--- a/apache-rat-core/src/main/java/org/apache/rat/analysis/generation/GeneratedLicenseNotRequired.java
+++ /dev/null
@@ -1,106 +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.analysis.generation;
-
-import java.util.regex.Pattern;
-
-import org.apache.rat.analysis.IHeaderMatcher;
-import org.apache.rat.analysis.RatHeaderAnalysisException;
-import org.apache.rat.api.Document;
-import org.apache.rat.api.MetaData;
-
-public class GeneratedLicenseNotRequired implements IHeaderMatcher {
-
- private static final String[] EMPTY_STRING_ARRAY = new String[0];
-
- private static final Pattern[] EMPTY_PATTERN_ARRAY = new Pattern[0];
-
- private static final String[] DEFAULT_PHRASES = {
- "generated by Cayenne",
- "Generated By:JJTree",
- "Generated By:JavaCC",
- "THIS FILE IS AUTOMATICALLY GENERATED",
- "NOTE: this file is autogenerated by XBeans",
- "This file was automatically generated by ",
- "# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!",
- "# Microsoft Developer Studio Generated NMAKE File",
- "# Microsoft Developer Studio Generated Build File",
- "Generated from configure.ac by autoheader",
- "generated automatically by aclocal",
- "build.xml generated by maven from project.xml",
- "This file was generated by",
- "This file has been automatically generated.",
- "Automatically generated - do not modify!",
- "Javadoc style sheet",
- "SOURCE FILE GENERATATED",
- "Generated by the Batik",
- "this file is autogenerated",
- "This class was autogenerated",
- "Generated by Maven",
- "Autogenerated by Thrift",
- "DO NOT EDIT THIS FILE - it is machine generated",
- "This class was generated by"};
-
-
- // Uses either patterns or strings currently (not both)
- private final Pattern[] linePatterns;
- private final String[] phrases;
-
- public GeneratedLicenseNotRequired() {
- this(DEFAULT_PHRASES);
- }
-
- public GeneratedLicenseNotRequired(final Pattern[] linePatterns) {
- this.linePatterns = linePatterns;
- this.phrases = EMPTY_STRING_ARRAY;
- }
-
- public GeneratedLicenseNotRequired(final String[] lines) {
- this.linePatterns = EMPTY_PATTERN_ARRAY;
- this.phrases = lines;
- }
-
- public boolean match(Document subject, String line) throws RatHeaderAnalysisException {
- boolean result = false;
- for (Pattern pat : linePatterns) {
- if (pat.matcher(line).matches()) {
- result = true;
- reportOnLicense(subject);
- break;
- }
- }
- for(String phrase : phrases) {
- if (line.contains(phrase)) {
- result = true;
- reportOnLicense(subject);
- break;
- }
- }
- return result;
- }
-
- private void reportOnLicense(Document subject) {
- subject.getMetaData().set(MetaData.RAT_LICENSE_FAMILY_CATEGORY_DATUM_GEN);
- }
-
- public void reset() {
- // stateless
- }
-
-}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/license/ApacheSoftwareLicense20.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/license/ApacheSoftwareLicense20.java
deleted file mode 100644
index 34b6ab934..000000000
--- a/apache-rat-core/src/main/java/org/apache/rat/analysis/license/ApacheSoftwareLicense20.java
+++ /dev/null
@@ -1,47 +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.analysis.license;
-
-import org.apache.rat.api.MetaData;
-
-/**
- * Matches Apache License, Version 2.0
- *
- */
-public final class ApacheSoftwareLicense20 extends SimplePatternBasedLicense {
- public static final String FIRST_LICENSE_LINE = "Licensed under the Apache License, Version 2.0 (the \"License\")";
- public static final String FIRST_LICENSE_LINE_SHORT = "Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements; and to You under the Apache License, Version 2.0.";
- public static final String LICENSE_REFERENCE_LINE = "http://www.apache.org/licenses/LICENSE-2.0";
-
- // These are all allowed variants as mentioned in https://issues.apache.org/jira/browse/LEGAL-265
- public static final String LICENSE_URL_HTTP = LICENSE_REFERENCE_LINE;
- public static final String LICENSE_URL_HTTPS = "https://www.apache.org/licenses/LICENSE-2.0";
- public static final String LICENSE_URL_HTTP_HTML = "http://www.apache.org/licenses/LICENSE-2.0.html";
- public static final String LICENSE_URL_HTTPS_HTML = "https://www.apache.org/licenses/LICENSE-2.0.html";
- public static final String LICENSE_URL_HTTP_TXT = "http://www.apache.org/licenses/LICENSE-2.0.txt";
- public static final String LICENSE_URL_HTTPS_TXT = "https://www.apache.org/licenses/LICENSE-2.0.txt";
- public ApacheSoftwareLicense20() {
- super(MetaData.RAT_LICENSE_FAMILY_CATEGORY_DATUM_ASL, MetaData.RAT_LICENSE_FAMILY_NAME_DATUM_APACHE_LICENSE_VERSION_2_0,
- "", new String[]{FIRST_LICENSE_LINE, FIRST_LICENSE_LINE_SHORT,
- LICENSE_URL_HTTP, LICENSE_URL_HTTPS,
- LICENSE_URL_HTTP_HTML, LICENSE_URL_HTTPS_HTML,
- LICENSE_URL_HTTP_TXT, LICENSE_URL_HTTPS_TXT,});
- }
-}
-
diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/license/AppliedApacheSoftwareLicense20.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/license/AppliedApacheSoftwareLicense20.java
deleted file mode 100644
index 65da0f92f..000000000
--- a/apache-rat-core/src/main/java/org/apache/rat/analysis/license/AppliedApacheSoftwareLicense20.java
+++ /dev/null
@@ -1,73 +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.analysis.license;
-
-import org.apache.rat.analysis.RatHeaderAnalysisException;
-import org.apache.rat.api.Document;
-import org.apache.rat.api.MetaData;
-
-/**
- * Matches an applied AL 2.0 License header, including a required
- * initial copyright header line, conforming the template
- * from the AL 2.0 license itself.
- *
- * @since Rat 0.9
- */
-public class AppliedApacheSoftwareLicense20 extends CopyrightHeader {
-
- public static final String ASL20_LICENSE_DEFN
- = "Licensed under the Apache License, Version 2.0 (the \"License\");\n"
- + "you may not use this file except in compliance with the License.\n"
- + "You may obtain a copy of the License at\n"
- + "http://www.apache.org/licenses/LICENSE-2.0\n"
- + "Unless required by applicable law or agreed to in writing, software\n"
- + "distributed under the License is distributed on an \"AS IS\" BASIS,\n"
- + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n"
- + "See the License for the specific language governing permissions and\n"
- + "limitations under the License.\n";
-
- private final FullTextMatchingLicense textMatcher;
-
- public AppliedApacheSoftwareLicense20() {
- super(MetaData.RAT_LICENSE_FAMILY_CATEGORY_DATUM_ASL, MetaData.RAT_LICENSE_FAMILY_NAME_DATUM_APACHE_LICENSE_VERSION_2_0,"");
- textMatcher = new FullTextMatchingLicense(MetaData.RAT_LICENSE_FAMILY_CATEGORY_DATUM_ASL, MetaData.RAT_LICENSE_FAMILY_NAME_DATUM_APACHE_LICENSE_VERSION_2_0,"",ASL20_LICENSE_DEFN);
- }
-
- public AppliedApacheSoftwareLicense20(String copyrightOwner) {
- this();
- setCopyrightOwner(copyrightOwner);
- }
-
- @Override
- public boolean match(Document subject, String s) throws RatHeaderAnalysisException {
- if (isCopyrightMatch()) {
- return textMatcher.match(subject, s); // will report the match if it has occurred
- }
- else {
- matchCopyright(s);
- }
- return false;
- }
-
- @Override
- public void reset() {
- super.reset();
- textMatcher.reset();
- }
-}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/license/BaseLicense.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/license/BaseLicense.java
index fe55b9663..3149c0c0b 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/analysis/license/BaseLicense.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/license/BaseLicense.java
@@ -18,10 +18,10 @@
*/
package org.apache.rat.analysis.license;
-import org.apache.rat.api.Document;
-import org.apache.rat.api.MetaData;
+import org.apache.rat.license.ILicenseFamily;
-public class BaseLicense {
+@Deprecated // remove in v1.0
+public abstract class BaseLicense implements DeprecatedConfig {
private String licenseFamilyCategory;
private String licenseFamilyName;
private String notes;
@@ -29,21 +29,6 @@ public class BaseLicense {
public BaseLicense() {
}
- public BaseLicense(final MetaData.Datum licenseFamilyCategory, final MetaData.Datum licenseFamilyName, final String notes)
- {
- if (!MetaData.RAT_URL_LICENSE_FAMILY_CATEGORY.equals(licenseFamilyCategory.getName())) {
- throw new IllegalStateException("Expected " + MetaData.RAT_URL_LICENSE_FAMILY_CATEGORY
- + ", got " + licenseFamilyCategory.getName());
- }
- setLicenseFamilyCategory(licenseFamilyCategory.getValue());
- if (!MetaData.RAT_URL_LICENSE_FAMILY_NAME.equals(licenseFamilyName.getName())) {
- throw new IllegalStateException("Expected " + MetaData.RAT_URL_LICENSE_FAMILY_NAME
- + ", got " + licenseFamilyName.getName());
- }
- setLicenseFamilyName(licenseFamilyName.getValue());
- setNotes(notes);
- }
-
public String getLicenseFamilyCategory() {
return licenseFamilyCategory;
}
@@ -67,26 +52,12 @@ public String getNotes() {
public void setNotes(String pNotes) {
notes = pNotes;
}
-
- public final void reportOnLicense(Document subject) {
- final MetaData metaData = subject.getMetaData();
- metaData.set(new MetaData.Datum(MetaData.RAT_URL_HEADER_SAMPLE, notes));
- final String licFamilyCategory = getLicenseFamilyCategory();
- metaData.set(new MetaData.Datum(MetaData.RAT_URL_HEADER_CATEGORY, licFamilyCategory));
- metaData.set(new MetaData.Datum(MetaData.RAT_URL_LICENSE_FAMILY_CATEGORY, licFamilyCategory));
- metaData.set(new MetaData.Datum(MetaData.RAT_URL_LICENSE_FAMILY_NAME, getLicenseFamilyName()));
- }
-
- protected static final String prune(String text) {
- final int length = text.length();
- final StringBuilder buffer = new StringBuilder(length);
- for (int i = 0; i < length; i++) {
- char at = text.charAt(i);
- if (Character.isLetterOrDigit(at)) {
- buffer.append(at);
- }
- }
- return buffer.toString();
+
+ @Override
+ final public ILicenseFamily getLicenseFamily() {
+ return ILicenseFamily.builder()
+ .setLicenseFamilyCategory(licenseFamilyCategory)
+ .setLicenseFamilyName(licenseFamilyName)
+ .build();
}
-
-}
+}
\ No newline at end of file
diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/license/CDDL1License.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/license/CDDL1License.java
deleted file mode 100644
index d731ef5cc..000000000
--- a/apache-rat-core/src/main/java/org/apache/rat/analysis/license/CDDL1License.java
+++ /dev/null
@@ -1,67 +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.analysis.license;
-
-import org.apache.rat.analysis.IHeaderMatcher;
-import org.apache.rat.analysis.RatHeaderAnalysisException;
-import org.apache.rat.api.Document;
-import org.apache.rat.api.MetaData;
-
-/**
- * Base CDDL 1.0 license.
- */
-public class CDDL1License extends BaseLicense implements IHeaderMatcher {
-
- public static final String CDDL1_LICENSE_DEFN
- = "The contents of this file are subject to the terms of the Common Development\n"
- + "and Distribution License(\"CDDL\") (the \"License\"). You may not use this file\n"
- + "except in compliance with the License.\n\n";
-
- public static final String CDDL1_LICENSE_DEFN_ILLUMOS_STYLE
- = "The contents of this file are subject to the terms of the\n"
- + "Common Development and Distribution License (the \"License\")\n"
- + "You may not use this file except in compliance with the License.\n";
-
- private final FullTextMatchingLicense textMatcherBase;
- private final FullTextMatchingLicense textMatcherIllumosStyle;
-
-
- public CDDL1License() {
- super(MetaData.RAT_LICENSE_FAMILY_CATEGORY_DATUM_CDLL1,
- MetaData.RAT_LICENSE_FAMILY_NAME_DATUM_CDDL1,
- "");
- textMatcherBase = new FullTextMatchingLicense(MetaData.RAT_LICENSE_FAMILY_CATEGORY_DATUM_CDLL1,
- MetaData.RAT_LICENSE_FAMILY_NAME_DATUM_CDDL1,
- "", CDDL1_LICENSE_DEFN);
- textMatcherIllumosStyle = new FullTextMatchingLicense(MetaData.RAT_LICENSE_FAMILY_CATEGORY_DATUM_CDLL1,
- MetaData.RAT_LICENSE_FAMILY_NAME_DATUM_CDDL1,
- "", CDDL1_LICENSE_DEFN_ILLUMOS_STYLE);
- }
-
- public boolean match(Document subject, String s) throws RatHeaderAnalysisException {
- return textMatcherBase.match(subject, s) ||
- textMatcherIllumosStyle.match(subject, s);
- }
-
- public void reset() {
- textMatcherBase.reset();
- textMatcherIllumosStyle.reset();
- }
-
-}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/license/CopyrightHeader.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/license/CopyrightHeader.java
deleted file mode 100644
index 88037d73d..000000000
--- a/apache-rat-core/src/main/java/org/apache/rat/analysis/license/CopyrightHeader.java
+++ /dev/null
@@ -1,102 +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.analysis.license;
-
-import org.apache.rat.analysis.IHeaderMatcher;
-import org.apache.rat.analysis.RatHeaderAnalysisException;
-import org.apache.rat.api.Document;
-import org.apache.rat.api.MetaData.Datum;
-
-import java.util.regex.Pattern;
-
-/**
- * Matches a typical Copyright header line only based on a regex pattern
- * which allows for one (starting) year or year range, and a
- * configurable copyright owner.
- *
- * The matching is done case insensitive
- *
- * Example supported Copyright header lines, using copyright owner "FooBar"
- *
- * * Copyright 2010 FooBar. *
- * * Copyright 2010-2012 FooBar. *
- * *copyright 2012 foobar*
- *
- * Note also that the copyright owner is appended to the regex pattern, so
- * can support additional regex but also requires escaping where needed,
- * e.g. use "FooBar \(www\.foobar\.com\)" for matching "FooBar (www.foobar.com)"
- *
- * @since Rat 0.9
- */
-public class CopyrightHeader extends BaseLicense implements IHeaderMatcher {
-
- public static final String COPYRIGHT_PREFIX_PATTERN_DEFN = ".*Copyright [0-9]{4}(\\-[0-9]{4})? ";
-
- private Pattern copyrightPattern;
- private String copyrightOwner;
- private boolean copyrightMatch = false;
-
- public CopyrightHeader() {
- }
-
- protected CopyrightHeader(Datum licenseFamilyCategory, Datum licenseFamilyName, String notes) {
- super(licenseFamilyCategory, licenseFamilyName, notes);
- }
-
- protected CopyrightHeader(Datum licenseFamilyCategory, Datum licenseFamilyName, String notes, String copyrightOwner) {
- this(licenseFamilyCategory, licenseFamilyName, notes);
- setCopyrightOwner(copyrightOwner);
- }
-
- // Called by ctor, so must not be overridden
- public final void setCopyrightOwner(String copyrightOwner) {
- this.copyrightOwner = copyrightOwner;
- this.copyrightPattern = Pattern.compile(COPYRIGHT_PREFIX_PATTERN_DEFN + copyrightOwner + ".*", Pattern.CASE_INSENSITIVE);
- }
-
- public String getCopyRightOwner() {
- return copyrightOwner;
- }
-
- public boolean hasCopyrightPattern() {
- return copyrightPattern != null;
- }
-
- protected boolean isCopyrightMatch() {
- return copyrightMatch;
- }
-
- protected boolean matchCopyright(String s) {
- if (!copyrightMatch) {
- copyrightMatch = copyrightPattern.matcher(s).matches();
- }
- return copyrightMatch;
- }
-
- public boolean match(Document subject, String s) throws RatHeaderAnalysisException {
- if (!copyrightMatch && matchCopyright(s)) {
- reportOnLicense(subject);
- }
- return copyrightMatch;
- }
-
- public void reset() {
- copyrightMatch = false;
- }
-}
diff --git a/apache-rat-core/src/test/java/org/apache/rat/analysis/license/MockStandardLicense.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/license/DeprecatedConfig.java
similarity index 76%
rename from apache-rat-core/src/test/java/org/apache/rat/analysis/license/MockStandardLicense.java
rename to apache-rat-core/src/main/java/org/apache/rat/analysis/license/DeprecatedConfig.java
index 537f69e7d..fc8de831c 100644
--- a/apache-rat-core/src/test/java/org/apache/rat/analysis/license/MockStandardLicense.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/license/DeprecatedConfig.java
@@ -18,15 +18,20 @@
*/
package org.apache.rat.analysis.license;
-import org.apache.rat.api.MetaData;
+import org.apache.rat.license.ILicense;
+import org.apache.rat.license.ILicenseFamily;
-
-public class MockStandardLicense extends BaseLicense {
-
-// public List visitors = new ArrayList();
-
- public MockStandardLicense() {
- super(new MetaData.Datum(MetaData.RAT_URL_LICENSE_FAMILY_CATEGORY, ""),
- new MetaData.Datum(MetaData.RAT_URL_LICENSE_FAMILY_NAME, ""), "");
- }
+/**
+ * A temporary interface for deprecated configuration options.
+ */
+@Deprecated // remove in v1.0
+public interface DeprecatedConfig {
+ /**
+ * @return the license definition.
+ */
+ ILicense.Builder getLicense();
+ /**
+ * @return the license family definition.
+ */
+ ILicenseFamily getLicenseFamily();
}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/license/DojoLicenseHeader.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/license/DojoLicenseHeader.java
deleted file mode 100644
index a5c00d5ba..000000000
--- a/apache-rat-core/src/main/java/org/apache/rat/analysis/license/DojoLicenseHeader.java
+++ /dev/null
@@ -1,41 +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.analysis.license;
-
-import org.apache.rat.api.MetaData;
-
-
-public class DojoLicenseHeader extends SimplePatternBasedLicense {
- private static final String LICENSE_URL = "http://dojotoolkit.org/community/licensing.shtml";
-
- // Copyright (c) 2004-2006, The Dojo Foundation
- // All Rights Reserved.
- //
- // Licensed under the Academic Free License version 2.1 or above OR the
- // modified BSD license. For more information on Dojo licensing, see:
- //
- // http://dojotoolkit.org/community/licensing.shtml
-
- public DojoLicenseHeader() {
- // TODO: support for dual licensing
- // TODO: support for or higher clauses
- super(MetaData.RAT_LICENSE_FAMILY_CATEGORY_DATUM_DOJO, MetaData.RAT_LICENSE_FAMILY_NAME_DATUM_MODIFIED_BSD_LICENSE, "Dual license AFL/BSD",
- new String[]{LICENSE_URL});
- }
-}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/license/FullTextMatchingLicense.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/license/FullTextMatchingLicense.java
index 87b4aa7b6..6ce7ef7b3 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/analysis/license/FullTextMatchingLicense.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/license/FullTextMatchingLicense.java
@@ -18,12 +18,8 @@
*/
package org.apache.rat.analysis.license;
-import java.util.Locale;
-
-import org.apache.rat.analysis.IHeaderMatcher;
-import org.apache.rat.analysis.RatHeaderAnalysisException;
-import org.apache.rat.api.Document;
-import org.apache.rat.api.MetaData.Datum;
+import org.apache.rat.configuration.builders.TextBuilder;
+import org.apache.rat.license.ILicense;
/**
* Accumulates all letters and numbers contained inside the header and
@@ -33,88 +29,26 @@
* The text comparison is case insensitive but assumes only
* characters in the US-ASCII charset are being matched.
*
- * @since Rat 0.9
+ * @deprecated Use new configuration options
*/
-public class FullTextMatchingLicense extends BaseLicense
- implements IHeaderMatcher {
-
- // Number of match characters assumed to be present on first line
- private static final int DEFAULT_INITIAL_LINE_LENGTH = 20;
-
- private String fullText;
-
- private String firstLine;
+@Deprecated // Since 0.16
+public class FullTextMatchingLicense extends BaseLicense {
- private boolean seenFirstLine = false;
-
- private final StringBuilder buffer = new StringBuilder();
+ private String text;
public FullTextMatchingLicense() {
}
- protected FullTextMatchingLicense(Datum licenseFamilyCategory,
- Datum licenseFamilyName,
- String notes,
- String fullText) {
- super(licenseFamilyCategory, licenseFamilyName, notes);
- setFullText(fullText);
- }
-
public final void setFullText(String text) {
- int offset = text.indexOf('\n');
- if (offset == -1) {
- offset = Math.min(DEFAULT_INITIAL_LINE_LENGTH, text.length());
- }
- firstLine = prune(text.substring(0, offset)).toLowerCase(Locale.ENGLISH);
- fullText = prune(text).toLowerCase(Locale.ENGLISH);
- init();
- }
-
- public final boolean hasFullText() {
- return fullText != null;
- }
-
- public boolean match(Document subject, String line) throws RatHeaderAnalysisException {
- final String inputToMatch = prune(line).toLowerCase(Locale.ENGLISH);
- if (seenFirstLine) { // Accumulate more input
- buffer.append(inputToMatch);
- } else {
- int offset = inputToMatch.indexOf(firstLine);
- if (offset >= 0) {
- // we have a match, save the text starting with the match
- buffer.append(inputToMatch.substring(offset));
- seenFirstLine = true;
- // Drop out to check whether full text is matched
- } else {
- // we assume that the first line must appear in a single line
- return false; // no more to do here
- }
- }
-
- if (buffer.length() >= fullText.length()) { // we have enough data to match
- if (buffer.toString().contains(fullText)) {
- reportOnLicense(subject);
- return true; // we found a match
- } else { // buffer contains first line but does not contain full text
- // It's possible that the buffer contains the first line again
- int offset = buffer.substring(1).indexOf(firstLine);
- if (offset >= 0) { // first line found again
- buffer.delete(0,offset); // reset buffer to the new start
- } else { // buffer does not even contain first line, so cannot be used to match full text
- init();
- }
- }
- }
- return false;
- }
-
- public void reset() {
- init();
+ this.text = text;
}
- // This is called indirectly from a ctor so must be final or private
- private void init() {
- buffer.setLength(0);
- seenFirstLine = false;
+ @Override
+ public ILicense.Builder getLicense() {
+ return ILicense.builder()
+ .setLicenseFamilyCategory(getLicenseFamilyCategory())
+ .setName(getLicenseFamilyName())
+ .setMatcher( new TextBuilder().setText(text) )
+ .setNotes(getNotes());
}
-}
\ No newline at end of file
+}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/license/MITLicense.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/license/MITLicense.java
deleted file mode 100644
index d622470b9..000000000
--- a/apache-rat-core/src/main/java/org/apache/rat/analysis/license/MITLicense.java
+++ /dev/null
@@ -1,36 +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.analysis.license;
-
-import org.apache.rat.api.MetaData;
-
-/**
- * Base MIT license (all 3 parts).
- */
-public class MITLicense extends FullTextMatchingLicense {
- public static final String FIRST_LICENSE_LINE = "Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:";
- public static final String MIDDLE_LICENSE_LINE = "The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.";
- public static final String AS_IS_LICENSE_LINE = "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.";
-
- public MITLicense() {
- super(MetaData.RAT_LICENSE_FAMILY_CATEGORY_DATUM_MIT,
- MetaData.RAT_LICENSE_FAMILY_NAME_DATUM_MIT,
- "", FIRST_LICENSE_LINE + MIDDLE_LICENSE_LINE + AS_IS_LICENSE_LINE);
- }
-}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/license/OASISLicense.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/license/OASISLicense.java
deleted file mode 100644
index 234dfefc8..000000000
--- a/apache-rat-core/src/main/java/org/apache/rat/analysis/license/OASISLicense.java
+++ /dev/null
@@ -1,66 +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.analysis.license;
-
-import java.util.regex.Pattern;
-
-import org.apache.rat.analysis.RatHeaderAnalysisException;
-import org.apache.rat.api.Document;
-import org.apache.rat.api.MetaData;
-
-/**
- * Looks for documents contain the OASIS copyright claim plus derivative work clause.
- * Perhaps need to match more.
- */
-public class OASISLicense extends FullTextMatchingLicense {
-
- private static final String COPYRIGHT_PATTERN_DEFN = ".*Copyright\\s.*OASIS Open.*";
- private static final String CLAUSE_DEFN
- = "This document and translations of it may be copied and furnished to others and derivative works" +
- "that comment on or otherwise explain it or assist in its implementation may be prepared" +
- "copied published and distributed";
-
- private static final Pattern COPYRIGHT_PATTERN = Pattern.compile(COPYRIGHT_PATTERN_DEFN);
-
- boolean copyrightMatch = false;
-
- public OASISLicense() {
- super(MetaData.RAT_LICENSE_FAMILY_CATEGORY_DATUM_OASIS,
- MetaData.RAT_LICENSE_FAMILY_NAME_DATUM_OASIS_OPEN_LICENSE,
- "No modifications allowed",
- CLAUSE_DEFN);
- }
-
- @Override
- public boolean match(Document subject, String line) throws RatHeaderAnalysisException {
- boolean result = false;
- if (copyrightMatch) {
- result = super.match(subject, line);
- } else {
- copyrightMatch = COPYRIGHT_PATTERN.matcher(line).matches();
- }
- return result;
- }
-
- @Override
- public void reset() {
- copyrightMatch = false;
- super.reset();
- }
-}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/license/SimplePatternBasedLicense.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/license/SimplePatternBasedLicense.java
index 6844d7a1d..36363e698 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/analysis/license/SimplePatternBasedLicense.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/license/SimplePatternBasedLicense.java
@@ -18,26 +18,27 @@
*/
package org.apache.rat.analysis.license;
-import org.apache.rat.analysis.IHeaderMatcher;
-import org.apache.rat.analysis.RatHeaderAnalysisException;
-import org.apache.rat.api.Document;
-import org.apache.rat.api.MetaData.Datum;
+import java.util.Arrays;
+
+import org.apache.rat.configuration.builders.AbstractBuilder;
+import org.apache.rat.configuration.builders.AnyBuilder;
+import org.apache.rat.configuration.builders.TextBuilder;
+import org.apache.rat.license.ILicense;
/**
* @since Rat 0.8
+ * @deprecated Use new configuration options
*/
-public class SimplePatternBasedLicense extends BaseLicense implements IHeaderMatcher {
+@Deprecated // Since 0.16
+public class SimplePatternBasedLicense extends BaseLicense {
private String[] patterns;
+
public SimplePatternBasedLicense() {
+
}
- protected SimplePatternBasedLicense(Datum pLicenseFamilyCategory, Datum pLicenseFamilyName,
- String pNotes, String[] pPatterns) {
- super(pLicenseFamilyCategory, pLicenseFamilyName, pNotes);
- setPatterns(pPatterns);
- }
public String[] getPatterns() {
return patterns;
@@ -47,29 +48,22 @@ public void setPatterns(String[] pPatterns) {
patterns = pPatterns;
}
- protected boolean matches(String pLine) {
- if (pLine != null) {
- final String[] pttrns = getPatterns();
- if (pttrns != null) {
- for (String pttrn : pttrns) {
- if (pLine.contains(pttrn)) {
- return true;
- }
- }
- }
+ private AbstractBuilder getMatcher() {
+ if (patterns.length == 1) {
+ return new TextBuilder().setText(patterns[0]);
+ } else {
+ AnyBuilder any = new AnyBuilder();
+ Arrays.stream(patterns).map(s -> new TextBuilder().setText(s)).forEach(b-> any.add(b));
+ return any;
}
- return false;
- }
-
- public void reset() {
- // Nothing to do
}
- public boolean match(Document pSubject, String pLine) throws RatHeaderAnalysisException {
- final boolean result = matches(pLine);
- if (result) {
- reportOnLicense(pSubject);
- }
- return result;
+ @Override
+ public ILicense.Builder getLicense() {
+ return ILicense.builder()
+ .setLicenseFamilyCategory(getLicenseFamilyCategory())
+ .setName(getLicenseFamilyName())
+ .setMatcher( getMatcher() )
+ .setNotes(getNotes());
}
}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AbstractHeaderMatcher.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AbstractHeaderMatcher.java
new file mode 100644
index 000000000..64e2cc696
--- /dev/null
+++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AbstractHeaderMatcher.java
@@ -0,0 +1,50 @@
+/*
+ * 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.analysis.matchers;
+
+import java.util.UUID;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.rat.analysis.IHeaderMatcher;
+
+/**
+ * An abstract class to simplify IHeaderMatcher creation. This class ensures that the id is set.
+ */
+public abstract class AbstractHeaderMatcher implements IHeaderMatcher {
+
+ private final String id;
+
+ /**
+ * Constructs the IHeaderMatcher with an id value. If {@code id} is null then a unique random id is created.
+ * @param id the Id to use.
+ */
+ protected AbstractHeaderMatcher(String id) {
+ this.id = StringUtils.isBlank(id) ? UUID.randomUUID().toString() : id;
+ }
+
+ @Override
+ public String getId() {
+ return id;
+ }
+
+ @Override
+ public String toString() {
+ return getId();
+ }
+}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AbstractMatcherContainer.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AbstractMatcherContainer.java
new file mode 100644
index 000000000..d15dd4258
--- /dev/null
+++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AbstractMatcherContainer.java
@@ -0,0 +1,68 @@
+/*
+ * 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.analysis.matchers;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Objects;
+
+import org.apache.rat.analysis.IHeaderMatcher;
+
+/**
+ * A class that implements IHeaderMatcher as a collection of other IHeaderMatchers.
+ */
+public abstract class AbstractMatcherContainer extends AbstractHeaderMatcher {
+
+ protected final Collection enclosed;
+
+ /**
+ * Constructs the abstract matcher container.
+ * If the {@code id} is not set then a unique random identifier is created.
+ * The {@code enclosed} collection is preserved in a new collection that retains the order of
+ * of the original collection.
+ * @param id The id for the matcher.
+ * @param enclosed the collection of enclosed matchers.
+ */
+ public AbstractMatcherContainer(String id, Collection extends IHeaderMatcher> enclosed) {
+ super(id);
+ Objects.requireNonNull(enclosed, "The collection of IHeaderMatcher may not be null");
+ this.enclosed = new ArrayList<>(enclosed);
+ }
+
+ /**
+ * Constructs the abstract matcher container with a unique random id.
+ * The {@code enclosed} collection is preserved in a new collection that retains the order of
+ * of the original collection.
+ * @param enclosed the collection of enclosed matchers.
+ */
+ public AbstractMatcherContainer(Collection extends IHeaderMatcher> enclosed) {
+ this(null, enclosed);
+ }
+
+ @Override
+ public void reset() {
+ enclosed.forEach(IHeaderMatcher::reset);
+ }
+
+ @Override
+ public State finalizeState() {
+ enclosed.forEach(IHeaderMatcher::finalizeState);
+ return currentState();
+ }
+}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AbstractSimpleMatcher.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AbstractSimpleMatcher.java
new file mode 100644
index 000000000..71852c075
--- /dev/null
+++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AbstractSimpleMatcher.java
@@ -0,0 +1,74 @@
+/*
+ * 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.analysis.matchers;
+
+/**
+ * An abstract IHeaderMatcher that does simple matching. Implementations need to implement the {@code doMatch(String)}
+ * method to perform the actual matching. All handling of the {@code State} is managed by this class. By default the
+ * {@code finalizeState()} method will convert {@code State.i} to {@code State.f}.
+ */
+public abstract class AbstractSimpleMatcher extends AbstractHeaderMatcher {
+ private State lastState;
+
+ /**
+ * Constructs the AbstractSimpleMatcher with the specified id.
+ * If the id is null or an empty string a unique random id will be generated.
+ * @param id the Id to use. May be null.
+ */
+ protected AbstractSimpleMatcher(String id) {
+ super(id);
+ this.lastState = State.i;
+ }
+
+ /**
+ * Performs the actual match test.
+ * @param line the line to check.
+ * @return {@code true} if the line matches, {@code false} otherwise.
+ */
+ abstract protected boolean doMatch(String line);
+
+ @Override
+ public final State matches(String line) {
+ if (lastState == State.t) {
+ return lastState;
+ }
+ if (line != null && doMatch(line)) {
+ lastState = State.t;
+ }
+ return lastState;
+ }
+
+ @Override
+ public void reset() {
+ lastState = State.i;
+ }
+
+ @Override
+ public State finalizeState() {
+ if (lastState == State.i) {
+ lastState = State.f;
+ }
+ return lastState;
+ }
+
+ @Override
+ public final State currentState() {
+ return lastState;
+ }
+}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AndMatcher.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AndMatcher.java
new file mode 100644
index 000000000..fc64f6e43
--- /dev/null
+++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AndMatcher.java
@@ -0,0 +1,76 @@
+/*
+ * 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.analysis.matchers;
+
+import java.util.Collection;
+
+import org.apache.rat.analysis.IHeaderMatcher;
+
+/**
+ * A matcher that performs a logical {@code AND} across all the contained matchers.
+ */
+public class AndMatcher extends AbstractMatcherContainer {
+
+ /**
+ * Constructs the AndMatcher with the specified id and enclosed collection.
+ * @param id the to use. If null or an empty string a unique random id will be created.
+ * @param enclosed the enclosed collection.
+ */
+ public AndMatcher(String id, Collection extends IHeaderMatcher> enclosed) {
+ super(id, enclosed);
+ }
+
+ /**
+ * Constructs the AndMatcher with the a unique random id and the enclosed collection.
+ * @param enclosed the enclosed collection.
+ */
+ public AndMatcher(Collection extends IHeaderMatcher> enclosed) {
+ this(null, enclosed);
+ }
+
+ @Override
+ public State currentState() {
+ State dflt = State.t;
+ for (IHeaderMatcher matcher : enclosed) {
+ switch (matcher.currentState()) {
+ case f:
+ return State.f;
+ case i:
+ dflt = State.i;
+ break;
+ default:
+ // do nothing
+ break;
+ }
+ }
+ return dflt;
+ }
+
+ @Override
+ public State matches(String line) {
+ enclosed.stream().filter(x -> x.currentState() == State.i).forEach(x -> x.matches(line));
+ return currentState();
+ }
+
+ @Override
+ public State finalizeState() {
+ enclosed.forEach(IHeaderMatcher::finalizeState);
+ return currentState();
+ }
+}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/CopyrightMatcher.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/CopyrightMatcher.java
new file mode 100644
index 000000000..a03798b4d
--- /dev/null
+++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/CopyrightMatcher.java
@@ -0,0 +1,126 @@
+/*
+ * 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.analysis.matchers;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * Matches a typical Copyright header line only based on a regex pattern which
+ * allows for one (starting) year or year range, and a configurable copyright
+ * owner.
+ *
+ * The matching is done case insensitive
+ *
+ * Example supported Copyright header lines, using copyright owner
+ * "FooBar"
+ *
+ * Copyright 2010 FooBar.
+ * Copyright 2010-2012 FooBar.
+ * copyright 2012 foobar
+ *
+ *
+ * Note also that the copyright owner is appended to the regex pattern and so can
+ * support additional regex but also requires escaping where needed,
+ * e.g. use "FooBar \\(www\\.foobar\\.com\\)" or
+ * "FooBar \\Q(www.foobar.com)\\E" to match "FooBar
+ * (www.foobar.com)"
+ *
+ * The matcher also accepts "(C)", "(c)", and "©" in place of (or in addition to) the "Copyright" or "copyright"
+ * keyword
+ */
+public class CopyrightMatcher extends AbstractSimpleMatcher {
+
+ private static final String COPYRIGHT_SYMBOL_DEFN = "\\([Cc]\\)|©";
+ private static final String COPYRIGHT_PATTERN_DEFN = "(\\b)?" + COPYRIGHT_SYMBOL_DEFN + "|Copyright\\b";
+ private static final Pattern COPYRIGHT_PATTERN = Pattern.compile(COPYRIGHT_PATTERN_DEFN);
+ private static final String ONE_PART = "\\s+((" + COPYRIGHT_SYMBOL_DEFN + ")\\s+)?%s";
+ private static final String TWO_PART = "\\s+((" + COPYRIGHT_SYMBOL_DEFN + ")\\s+)?%s,?\\s+%s";
+
+ private final Pattern dateOwnerPattern;
+ private final Pattern ownerDatePattern;
+
+ /**
+ * Constructs the CopyrightMatcher with the specified start, stop and owner strings and a unique random id..
+ * @param start the start date for the copyright may be null.
+ * @param stop the stop date for the copyright, may be null. May not be specified if start is not specified.
+ * @param owner the owner of the copyright. may be null.
+ */
+ public CopyrightMatcher(String start, String stop, String owner) {
+ this(null, start, stop, owner);
+ }
+
+ /**
+ * Constructs the CopyrightMatcher with the specified start, stop and owner strings.
+ * @param id the id for the matcher.
+ * @param start the start date for the copyright may be null.
+ * @param stop the stop date for the copyright, may be null. May not be specified if start is not specified.
+ * @param owner the owner of the copyright. may be null.
+ */
+ public CopyrightMatcher(String id, String start, String stop, String owner) {
+ super(id);
+ String dateDefn = "";
+ if (StringUtils.isNotEmpty(start)) {
+ if (StringUtils.isNotEmpty(stop)) {
+ dateDefn = String.format("%s\\s*-\\s*%s", start.trim(), stop.trim());
+ } else {
+ dateDefn = start.trim();
+ }
+ }
+ if (StringUtils.isEmpty(owner)) {
+ // no owner
+ if (StringUtils.isEmpty(dateDefn)) {
+ dateDefn = "[0-9]{4}";
+ }
+ dateOwnerPattern = Pattern.compile(String.format(ONE_PART, dateDefn));
+ ownerDatePattern = null;
+ } else {
+ if (StringUtils.isEmpty(dateDefn)) {
+ // no date
+ dateOwnerPattern = Pattern.compile(String.format(ONE_PART, owner));
+ ownerDatePattern = null;
+ } else {
+ dateOwnerPattern = Pattern.compile(String.format(TWO_PART, dateDefn, owner));
+ ownerDatePattern = Pattern.compile(String.format(TWO_PART, owner, dateDefn));
+ }
+ }
+ }
+
+ @Override
+ protected boolean doMatch(String line) {
+ String lowerLine = line.toLowerCase();
+ if (lowerLine.contains("copyright") || lowerLine.contains("(c)") || line.contains("©")) {
+ Matcher matcher = COPYRIGHT_PATTERN.matcher(line);
+ if (matcher.find()) {
+ String buffer = line.substring(matcher.end());
+ matcher = dateOwnerPattern.matcher(buffer);
+ if (matcher.find() && matcher.start() == 0) {
+ return true;
+ }
+ if (ownerDatePattern != null) {
+ matcher = ownerDatePattern.matcher(buffer);
+ return matcher.find() && matcher.start() == 0;
+ }
+ }
+ }
+ return false;
+ }
+}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/FullTextMatcher.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/FullTextMatcher.java
new file mode 100644
index 000000000..ece1118f1
--- /dev/null
+++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/FullTextMatcher.java
@@ -0,0 +1,132 @@
+/*
+ * 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.analysis.matchers;
+
+import java.util.Locale;
+import java.util.Objects;
+
+/**
+ * Accumulates all letters and numbers contained inside the header and compares
+ * it to the full text of a given license (after reducing it to letters and
+ * numbers as well).
+ *
+ *
+ * The text comparison is case insensitive but assumes only characters in the
+ * US-ASCII charset are being matched.
+ *
+ */
+public class FullTextMatcher extends AbstractSimpleMatcher {
+
+ // Number of match characters assumed to be present on first line
+ private static final int DEFAULT_INITIAL_LINE_LENGTH = 20;
+
+ private final String fullText;
+
+ private final String firstLine;
+
+ private boolean seenFirstLine;
+
+ private final StringBuilder buffer = new StringBuilder();
+
+ /**
+ * Constructs the full text matcher with a unique random id and the specified text to match.
+ * @param fullText the text to match
+ */
+ public FullTextMatcher(String fullText) {
+ this(null, fullText);
+ }
+
+ /**
+ * Constructs the full text matcher for the specified text.
+ * @param id the id for the matcher
+ * @param fullText the text to match
+ */
+ public FullTextMatcher(String id, String fullText) {
+ super(id);
+ Objects.requireNonNull(fullText, "fullText may not be null");
+ int offset = fullText.indexOf('\n');
+ if (offset == -1) {
+ offset = Math.min(DEFAULT_INITIAL_LINE_LENGTH, fullText.length());
+ }
+ firstLine = prune(fullText.substring(0, offset)).toLowerCase(Locale.ENGLISH);
+ this.fullText = prune(fullText).toLowerCase(Locale.ENGLISH);
+ buffer.setLength(0);
+ seenFirstLine = false;
+ }
+
+ /**
+ * Removes everything except letter or digit from text.
+ *
+ * @param text The text to remove extra chars from.
+ * @return the pruned text.
+ */
+ public static String prune(String text) {
+ final int length = text.length();
+ final StringBuilder buffer = new StringBuilder(length);
+ for (int i = 0; i < length; i++) {
+ char at = text.charAt(i);
+ if (Character.isLetterOrDigit(at)) {
+ buffer.append(at);
+ }
+ }
+ return buffer.toString();
+ }
+
+ @Override
+ public boolean doMatch(String line) {
+ final String inputToMatch = prune(line).toLowerCase(Locale.ENGLISH);
+ if (seenFirstLine) { // Accumulate more input
+ buffer.append(inputToMatch);
+ } else {
+ int offset = inputToMatch.indexOf(firstLine);
+ if (offset >= 0) {
+ // we have a match, save the text starting with the match
+ buffer.append(inputToMatch.substring(offset));
+ seenFirstLine = true;
+ // Drop out to check whether full text is matched
+ } else {
+ // we assume that the first line must appear in a single line
+ return false; // no more to do here
+ }
+ }
+
+ if (buffer.length() >= fullText.length()) { // we have enough data to match
+ if (buffer.toString().contains(fullText)) {
+ return true;
+ }
+ // buffer contains first line but does not contain full text
+ // It's possible that the buffer contains the first line again
+ int offset = buffer.substring(1).indexOf(firstLine);
+ if (offset >= 0) { // first line found again
+ buffer.delete(0, offset); // reset buffer to the new start
+ } else { // buffer does not even contain first line, so cannot be used to match full text
+ reset();
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public void reset() {
+ super.reset();
+ buffer.setLength(0);
+ seenFirstLine = false;
+ }
+
+}
\ No newline at end of file
diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/NotMatcher.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/NotMatcher.java
new file mode 100644
index 000000000..8678f9257
--- /dev/null
+++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/NotMatcher.java
@@ -0,0 +1,79 @@
+/*
+ * 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.analysis.matchers;
+
+import java.util.Objects;
+
+import org.apache.rat.analysis.IHeaderMatcher;
+/**
+ * An IHeaderMatcher that reverses the result of an enclosed matcher.
+ */
+public class NotMatcher extends AbstractHeaderMatcher {
+
+ private final IHeaderMatcher enclosed;
+
+ /**
+ * Create the matcher with the enclosed matcher.
+ * @param enclosed the enclosed matcher
+ */
+ public NotMatcher(IHeaderMatcher enclosed) {
+ this(null, enclosed);
+ }
+
+ /**
+ * Create the matcher with the enclosed matcher and id.
+ * @param id the id for this matcher.
+ * @param enclosed the enclosed matcher
+ */
+ public NotMatcher(String id, IHeaderMatcher enclosed) {
+ super(id);
+ Objects.requireNonNull(enclosed, "enclosed matcher may not be null");
+ this.enclosed = enclosed;
+ }
+
+ @Override
+ public State matches(String line) {
+ enclosed.matches(line);
+ return currentState();
+ }
+
+ @Override
+ public void reset() {
+ enclosed.reset();
+ }
+
+ @Override
+ public State finalizeState() {
+ enclosed.finalizeState();
+ return currentState();
+ }
+
+ @Override
+ public State currentState() {
+ switch (enclosed.currentState()) {
+ case t:
+ return State.f;
+ case f:
+ return State.t;
+ default:
+ case i:
+ return State.i;
+ }
+ }
+}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/OrMatcher.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/OrMatcher.java
new file mode 100644
index 000000000..9b7bbae8a
--- /dev/null
+++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/OrMatcher.java
@@ -0,0 +1,95 @@
+/*
+ * 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.analysis.matchers;
+
+import java.util.Collection;
+
+import org.apache.rat.analysis.IHeaderMatcher;
+
+/**
+ * A matcher that performs a logical {@code OR} across all the contained matchers.
+ */
+public class OrMatcher extends AbstractMatcherContainer {
+
+ private State lastState;
+
+ /**
+ * Constructs the matcher from the enclosed matchers.
+ * @param enclosed the enclosed matchers.
+ */
+ public OrMatcher(Collection extends IHeaderMatcher> enclosed) {
+ this(null, enclosed);
+ }
+
+ /**
+ * Constructs the matcher with the specified id from the enclosed matchers.
+ * @param id the id to use.
+ * @param enclosed the enclosed matchers.
+ */
+ public OrMatcher(String id, Collection extends IHeaderMatcher> enclosed) {
+ super(id, enclosed);
+ lastState = State.i;
+ }
+
+ @Override
+ public State matches(String line) {
+ if (lastState == State.t) {
+ return State.t;
+ }
+ for (IHeaderMatcher matcher : enclosed) {
+ switch (matcher.matches(line)) {
+ case t:
+ lastState = State.t;
+ return lastState;
+ case f:
+ case i:
+ lastState = State.i;
+ }
+ }
+ return lastState;
+ }
+
+ @Override
+ public State currentState() {
+ if (lastState == State.t) {
+ return lastState;
+ }
+ for (IHeaderMatcher matcher : enclosed) {
+ switch (matcher.currentState()) {
+ case t:
+ lastState = State.t;
+ return lastState;
+ case i:
+ lastState = State.i;
+ return lastState;
+ case f:
+ // do nothing;
+ break;
+ }
+ }
+ lastState = State.f;
+ return lastState;
+ }
+
+ @Override
+ public void reset() {
+ super.reset();
+ lastState = State.i;
+ }
+}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SPDXMatcherFactory.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SPDXMatcherFactory.java
new file mode 100644
index 000000000..5766b5257
--- /dev/null
+++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SPDXMatcherFactory.java
@@ -0,0 +1,138 @@
+/*
+ * 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.analysis.matchers;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.rat.ConfigurationException;
+import org.apache.rat.analysis.IHeaderMatcher;
+
+/**
+ * Defines a factory to produce matchers for an SPDX tag. SPDX tag is of the format
+ * {@code SPDX-License-Identifier: short-name} where {@code short-name} matches
+ * the regex pattern [A-Za-z0-9\.\-]+
+ *
+ * SPDX identifiers are specified by the Software Package Data Exchange(R) also
+ * known as SPDX(R) project from the Linux foundation.
+ *
+ *
+ * @see List of Ids at spdx.dev
+ */
+public class SPDXMatcherFactory {
+
+ /**
+ * The collection of all matchers produced by this factory.
+ */
+ private static final Map matchers = new HashMap<>();
+
+ /**
+ * The instance of this factory.
+ */
+ public static final SPDXMatcherFactory INSTANCE = new SPDXMatcherFactory();
+
+ /**
+ * The regular expression to locate the SPDX license identifier in the text stream
+ */
+ private static Pattern groupSelector = Pattern.compile(".*SPDX-License-Identifier:\\s([A-Za-z0-9\\.\\-]+)");
+
+ /**
+ * the last line that this factory scanned.
+ */
+ private String lastLine;
+ /**
+ * The last matcer to match the line.
+ */
+ private Match lastMatch;
+
+ private SPDXMatcherFactory() {
+ lastLine = null;
+ };
+
+ /**
+ * Creates the spdx matcher.
+ * @param spdxId the spdx name to match.
+ * @return a spdx matcher.
+ */
+ public IHeaderMatcher create(String spdxId) {
+ if (StringUtils.isBlank(spdxId)) {
+ throw new ConfigurationException("'spdx' type matcher requires a name");
+ }
+ Match matcher = matchers.get(spdxId);
+ if (matcher == null) {
+ matcher = new Match(spdxId);
+ matchers.put(spdxId, matcher);
+ }
+ return matcher;
+ }
+
+ /**
+ * Each matcher calls this method to present the line it is working on.
+ * @param line The line the caller is looking at.
+ * @param caller the Match that is calling this method.
+ * @return true if the caller matches the text.
+ */
+ private boolean check(String line, Match caller) {
+ // if the line has not been seen yet see if we can extract the SPDX id from the line.
+ // if so then see if that name has been registered. If so then we have a match and set
+ // lastMatch.
+ if ((lastLine == null || !lastLine.equals(line)) && line.contains("SPDX-License-Identifier")) {
+ Matcher matcher = groupSelector.matcher(line);
+ if (matcher.find()) {
+ lastMatch = matchers.get(matcher.group(1));
+ } else {
+ lastMatch = null;
+ }
+ }
+ // see if the caller matches lastMatch.
+ return (lastMatch != null) && caller.spdxId.equals(lastMatch.spdxId);
+ }
+
+ public class Match extends AbstractSimpleMatcher {
+
+ String spdxId;
+ /**
+ * Constructor.
+ *
+ * @param spdxId A regular expression that matches the @{short-name} of the SPDX
+ * Identifier.
+ */
+ Match(final String spdxId) {
+ super("SPDX:" + spdxId);
+ Objects.requireNonNull(spdxId, "SpdxId is required");
+ this.spdxId = spdxId;
+ }
+
+ @Override
+ protected boolean doMatch(String line) {
+ return SPDXMatcherFactory.this.check(line, this);
+ }
+
+ @Override
+ public void reset() {
+ super.reset();
+ SPDXMatcherFactory.this.lastMatch = null;
+
+ }
+ }
+}
diff --git a/apache-rat-core/src/test/java/org/apache/rat/analysis/generation/GeneratedLicenseNotRequiredTest.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleRegexMatcher.java
similarity index 52%
rename from apache-rat-core/src/test/java/org/apache/rat/analysis/generation/GeneratedLicenseNotRequiredTest.java
rename to apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleRegexMatcher.java
index d9fc72f3a..641f7ab43 100644
--- a/apache-rat-core/src/test/java/org/apache/rat/analysis/generation/GeneratedLicenseNotRequiredTest.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleRegexMatcher.java
@@ -15,36 +15,37 @@
* KIND, either express or implied. See the License for the *
* specific language governing permissions and limitations *
* under the License. *
- */
-package org.apache.rat.analysis.generation;
-
-import org.apache.rat.api.Document;
-import org.apache.rat.document.MockLocation;
-import org.apache.rat.report.claim.impl.xml.MockClaimReporter;
-import org.junit.Before;
-import org.junit.Test;
+ */
+package org.apache.rat.analysis.matchers;
import java.util.regex.Pattern;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
+/**
+ * A simple regular expression matching IHeaderMatcher
+ */
+public class SimpleRegexMatcher extends AbstractSimpleMatcher {
+ private final Pattern pattern;
-public class GeneratedLicenseNotRequiredTest {
+ /**
+ * Constructs a regex pattern matcher with a unique random id and the specified Regex pattern.
+ * @param pattern the pattern to match. Pattern will only match a single line from the input stream.
+ */
+ public SimpleRegexMatcher(Pattern pattern) {
+ this(null, pattern);
+ }
- private GeneratedLicenseNotRequired license;
- private MockClaimReporter reporter;
-
- @Before
- public void setUp() throws Exception {
- Pattern[] patterns = {Pattern.compile(".*Generated")};
- license = new GeneratedLicenseNotRequired(patterns);
- reporter = new MockClaimReporter();
+ /**
+ * Constructs a regex pattern matcher with a unique random id and the specified Regex pattern.
+ * @param id the id for this matcher
+ * @param pattern the pattern to match. Pattern will only match a single line from the input stream.
+ */
+ public SimpleRegexMatcher(String id, Pattern pattern) {
+ super(id);
+ this.pattern = pattern;
}
- @Test
- public void match() throws Exception {
- final Document subject = new MockLocation("subject");
- assertFalse("Does not match regex", license.match(subject, "Not at all"));
- assertTrue("Matches regex", license.match(subject, "This is Generated"));
+ @Override
+ public boolean doMatch(String line) {
+ return pattern.matcher(line).find();
}
}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleTextMatcher.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleTextMatcher.java
new file mode 100644
index 000000000..f7ae6ef90
--- /dev/null
+++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleTextMatcher.java
@@ -0,0 +1,54 @@
+/*
+ * 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.analysis.matchers;
+
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * A simple text matching IHeaderMatcher implementation.
+ */
+public class SimpleTextMatcher extends AbstractSimpleMatcher {
+ private final String pattern;
+
+ /**
+ * Constructs the simple text matcher for the simple string.
+ * @param pattern The pattern to match. Will only match a single line from the input stream.
+ */
+ public SimpleTextMatcher(String pattern) {
+ this(null, pattern);
+ }
+
+ /**
+ * Constructs the simple text matcher for the simple string.
+ * @param id The id for this matcher.
+ * @param pattern The pattern to match. Will only match a single line from the input stream.
+ */
+ public SimpleTextMatcher(String id, String pattern) {
+ super(id);
+ if (StringUtils.isBlank(pattern)) {
+ throw new IllegalArgumentException("Pattern may not be null, empty or blank");
+ }
+ this.pattern = pattern;
+ }
+
+ @Override
+ public boolean doMatch(String line) {
+ return line.contains(pattern);
+ }
+}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/annotation/AbstractLicenseAppender.java b/apache-rat-core/src/main/java/org/apache/rat/annotation/AbstractLicenseAppender.java
index 17d6cd385..6870bcace 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/annotation/AbstractLicenseAppender.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/annotation/AbstractLicenseAppender.java
@@ -19,6 +19,7 @@
package org.apache.rat.annotation;
import org.apache.commons.io.IOUtils;
+import org.apache.rat.utils.Log;
import java.io.BufferedReader;
import java.io.File;
@@ -68,12 +69,16 @@ public abstract class AbstractLicenseAppender {
private static final int TYPE_JSP = 24;
private static final int TYPE_FML = 25;
private static final int TYPE_GO = 26;
- private static final int TYPE_PM = 27;
+ private static final int TYPE_PM = 27;
+ private static final int TYPE_MD = 28;
+ private static final int TYPE_YAML = 29;
+
+
/**
* the line separator for this OS
*/
- private static final String LINE_SEP = System.getProperty("line.separator");
+ private static final String LINE_SEP = System.lineSeparator();
private static final int[] FAMILY_C = new int[]{
TYPE_JAVA, TYPE_JAVASCRIPT, TYPE_C, TYPE_H, TYPE_SCALA,
@@ -81,11 +86,11 @@ public abstract class AbstractLicenseAppender {
TYPE_BEANSHELL, TYPE_GO,
};
private static final int[] FAMILY_SGML = new int[]{
- TYPE_XML, TYPE_HTML, TYPE_JSP, TYPE_FML,
+ TYPE_XML, TYPE_HTML, TYPE_JSP, TYPE_FML, TYPE_MD,
};
private static final int[] FAMILY_SH = new int[]{
TYPE_PROPERTIES, TYPE_PYTHON, TYPE_SH, TYPE_RUBY, TYPE_PERL,
- TYPE_TCL, TYPE_VISUAL_STUDIO_SOLUTION, TYPE_PM,
+ TYPE_TCL, TYPE_VISUAL_STUDIO_SOLUTION, TYPE_PM, TYPE_YAML,
};
private static final int[] FAMILY_BAT = new int[]{
TYPE_BAT,
@@ -160,6 +165,7 @@ public abstract class AbstractLicenseAppender {
EXT2TYPE.put("java", TYPE_JAVA);
EXT2TYPE.put("js", TYPE_JAVASCRIPT);
EXT2TYPE.put("jsp", TYPE_JSP);
+ EXT2TYPE.put("md", TYPE_MD);
EXT2TYPE.put("ndoc", TYPE_XML);
EXT2TYPE.put("nunit", TYPE_XML);
EXT2TYPE.put("php", TYPE_PHP);
@@ -186,12 +192,21 @@ public abstract class AbstractLicenseAppender {
EXT2TYPE.put("xml", TYPE_XML);
EXT2TYPE.put("xproj", TYPE_XML);
EXT2TYPE.put("xsl", TYPE_XML);
+ EXT2TYPE.put("yaml", TYPE_YAML);
+ EXT2TYPE.put("yml", TYPE_YAML);
}
private boolean isForced;
+ /** The log to use */
+ private final Log log;
- public AbstractLicenseAppender() {
+ /**
+ * Constructor
+ * @param log The log to use.
+ */
+ public AbstractLicenseAppender(final Log log) {
super();
+ this.log = log;
}
/**
@@ -240,11 +255,11 @@ public void append(File document) throws IOException {
if (isForced) {
boolean deleted = document.delete();
if (!deleted) {
- System.err.println("Could not delete original file to prepare renaming.");
+ log.error("Could not delete original file to prepare renaming.");
}
boolean renamed = newDocument.renameTo(document.getAbsoluteFile());
if (!renamed) {
- System.err.println("Failed to rename new file, original file remains unchanged.");
+ log.error("Failed to rename new file, original file remains unchanged.");
}
}
}
@@ -292,7 +307,7 @@ private boolean attachLicense(Writer writer, File document,
doFirstLine(document, writer, line, "@echo");
} else if (first && expectsMSVSSF) {
written = true;
- if ("".equals(line)) {
+ if (line.isEmpty()) {
line = passThroughReadNext(writer, line, br);
}
if (line.startsWith("Microsoft Visual Studio Solution"
diff --git a/apache-rat-core/src/main/java/org/apache/rat/annotation/ApacheV2LicenseAppender.java b/apache-rat-core/src/main/java/org/apache/rat/annotation/ApacheV2LicenseAppender.java
index 64509ccf2..8c4ccf7d0 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/annotation/ApacheV2LicenseAppender.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/annotation/ApacheV2LicenseAppender.java
@@ -20,6 +20,8 @@
import java.io.File;
+import org.apache.rat.utils.Log;
+
/**
* Add an Apache License V2 license header to a
@@ -35,8 +37,8 @@ public class ApacheV2LicenseAppender extends AbstractLicenseAppender {
/**
* Create a license appender with the standard ASF license header.
*/
- public ApacheV2LicenseAppender() {
- super();
+ public ApacheV2LicenseAppender(final Log log) {
+ super(log);
}
/**
@@ -45,8 +47,8 @@ public ApacheV2LicenseAppender() {
*
* @param copyright copyright line.
*/
- public ApacheV2LicenseAppender(String copyright) {
- super();
+ public ApacheV2LicenseAppender(final Log log, String copyright) {
+ super(log);
this.copyright = copyright;
}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/api/ContentType.java b/apache-rat-core/src/main/java/org/apache/rat/api/ContentType.java
index 84b4ee3b5..d5a2a0ccb 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/api/ContentType.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/api/ContentType.java
@@ -32,7 +32,7 @@ public class ContentType {
/**
* Constructs content types,
- * performing an necessary conversions.
+ * performing any necessary conversions.
* @param mediaType not null
* @param subType not null
* @param parameters not null
diff --git a/apache-rat-core/src/main/java/org/apache/rat/api/Document.java b/apache-rat-core/src/main/java/org/apache/rat/api/Document.java
index b0818d08b..9cf8d1413 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/api/Document.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/api/Document.java
@@ -26,10 +26,13 @@
public interface Document {
- String getName();
+ /**
+ * @return the name of the current document.
+ */
+ String getName();
/**
- * Reads the content of this document.
+ * Reads the contents of this document.
* @return Reader
not null
* @throws IOException if this document cannot be read
* @throws CompositeDocumentException if this document can only be read as
diff --git a/apache-rat-core/src/main/java/org/apache/rat/api/MetaData.java b/apache-rat-core/src/main/java/org/apache/rat/api/MetaData.java
index 556912e72..201f7f783 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/api/MetaData.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/api/MetaData.java
@@ -24,8 +24,11 @@
import java.util.Iterator;
import java.util.List;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.rat.license.ILicense;
+
/**
- * Data about the subject.
+ * Data about the document under test..
*/
public class MetaData {
@@ -54,73 +57,119 @@ public class MetaData {
// Shortcuts used in report output, must be exactly 5 characters
public static final String RAT_LICENSE_FAMILY_CATEGORY_VALUE_GEN = "GEN ";
public static final String RAT_LICENSE_FAMILY_CATEGORY_VALUE_UNKNOWN = "?????";
+ @Deprecated
public static final String RAT_LICENSE_FAMILY_CATEGORY_VALUE_ASL = "AL ";
+ @Deprecated
public static final String RAT_LICENSE_FAMILY_CATEGORY_VALUE_OASIS = "OASIS";
+ @Deprecated
public static final String RAT_LICENSE_FAMILY_CATEGORY_VALUE_W3CD = "W3CD ";
+ @Deprecated
public static final String RAT_LICENSE_FAMILY_CATEGORY_VALUE_W3C = "W3C ";
+ @Deprecated
public static final String RAT_LICENSE_FAMILY_CATEGORY_VALUE_DOJO = "DOJO ";
+ @Deprecated
public static final String RAT_LICENSE_FAMILY_CATEGORY_VALUE_TMF = "TMF ";
+ @Deprecated
public static final String RAT_LICENSE_FAMILY_CATEGORY_VALUE_GPL1 ="GPL1 ";
+ @Deprecated
public static final String RAT_LICENSE_FAMILY_CATEGORY_VALUE_GPL2 ="GPL2 ";
+ @Deprecated
public static final String RAT_LICENSE_FAMILY_CATEGORY_VALUE_GPL3 = "GPL3 ";
+ @Deprecated
public static final String RAT_LICENSE_FAMILY_CATEGORY_VALUE_MIT = "MIT ";
+ @Deprecated
public static final String RAT_LICENSE_FAMILY_CATEGORY_VALUE_CDDL1 = "CDDL1";
public static final Datum RAT_LICENSE_FAMILY_CATEGORY_DATUM_GEN = new Datum(RAT_URL_LICENSE_FAMILY_CATEGORY, RAT_LICENSE_FAMILY_CATEGORY_VALUE_GEN);
public static final Datum RAT_LICENSE_FAMILY_CATEGORY_DATUM_UNKNOWN = new Datum(RAT_URL_LICENSE_FAMILY_CATEGORY, RAT_LICENSE_FAMILY_CATEGORY_VALUE_UNKNOWN);
+ @Deprecated
public static final Datum RAT_LICENSE_FAMILY_CATEGORY_DATUM_ASL = new Datum(RAT_URL_LICENSE_FAMILY_CATEGORY, RAT_LICENSE_FAMILY_CATEGORY_VALUE_ASL);
+ @Deprecated
public static final Datum RAT_LICENSE_FAMILY_CATEGORY_DATUM_OASIS = new Datum(RAT_URL_LICENSE_FAMILY_CATEGORY, RAT_LICENSE_FAMILY_CATEGORY_VALUE_OASIS);
+ @Deprecated
public static final Datum RAT_LICENSE_FAMILY_CATEGORY_DATUM_W3CD = new Datum(RAT_URL_LICENSE_FAMILY_CATEGORY, RAT_LICENSE_FAMILY_CATEGORY_VALUE_W3CD);
+ @Deprecated
public static final Datum RAT_LICENSE_FAMILY_CATEGORY_DATUM_W3C = new Datum(RAT_URL_LICENSE_FAMILY_CATEGORY, RAT_LICENSE_FAMILY_CATEGORY_VALUE_W3C);
+ @Deprecated
public static final Datum RAT_LICENSE_FAMILY_CATEGORY_DATUM_DOJO = new Datum(RAT_URL_LICENSE_FAMILY_CATEGORY, RAT_LICENSE_FAMILY_CATEGORY_VALUE_DOJO);
+ @Deprecated
public static final Datum RAT_LICENSE_FAMILY_CATEGORY_DATUM_TMF = new Datum(RAT_URL_LICENSE_FAMILY_CATEGORY, RAT_LICENSE_FAMILY_CATEGORY_VALUE_TMF);
+ @Deprecated
public static final Datum RAT_LICENSE_FAMILY_CATEGORY_DATUM_GPL1 = new Datum(RAT_URL_LICENSE_FAMILY_CATEGORY,RAT_LICENSE_FAMILY_CATEGORY_VALUE_GPL1);
+ @Deprecated
public static final Datum RAT_LICENSE_FAMILY_CATEGORY_DATUM_GPL2 = new Datum(RAT_URL_LICENSE_FAMILY_CATEGORY,RAT_LICENSE_FAMILY_CATEGORY_VALUE_GPL2);
+ @Deprecated
public static final Datum RAT_LICENSE_FAMILY_CATEGORY_DATUM_GPL3 = new Datum(RAT_URL_LICENSE_FAMILY_CATEGORY,RAT_LICENSE_FAMILY_CATEGORY_VALUE_GPL3);
+ @Deprecated
public static final Datum RAT_LICENSE_FAMILY_CATEGORY_DATUM_MIT = new Datum(RAT_URL_LICENSE_FAMILY_CATEGORY,RAT_LICENSE_FAMILY_CATEGORY_VALUE_MIT);
+ @Deprecated
public static final Datum RAT_LICENSE_FAMILY_CATEGORY_DATUM_CDLL1 = new Datum(RAT_URL_LICENSE_FAMILY_CATEGORY,RAT_LICENSE_FAMILY_CATEGORY_VALUE_CDDL1);
// License Family Standard Names
public static final String RAT_URL_LICENSE_FAMILY_NAME= RAT_BASE_URL + "#LicenseFamilyName";
+ @Deprecated
public static final String RAT_LICENSE_FAMILY_NAME_VALUE_W3C_SOFTWARE_COPYRIGHT = "W3C Software Copyright";
+ @Deprecated
public static final String RAT_LICENSE_FAMILY_NAME_VALUE_W3C_DOCUMENT_COPYRIGHT = "W3C Document Copyright";
+ @Deprecated
public static final String RAT_LICENSE_FAMILY_NAME_VALUE_OASIS_OPEN_LICENSE = "OASIS Open License";
+ @Deprecated
public static final String RAT_LICENSE_FAMILY_NAME_VALUE_MODIFIED_BSD_LICENSE = "Modified BSD License";
+ @Deprecated
public static final String RAT_LICENSE_FAMILY_NAME_VALUE_APACHE_LICENSE_VERSION_2_0 = "Apache License Version 2.0";
+ @Deprecated
public static final String RAT_LICENSE_FAMILY_NAME_VALUE_GPL_VERSION_1 =
"GNU General Public License, version 1";
+ @Deprecated
public static final String RAT_LICENSE_FAMILY_NAME_VALUE_GPL_VERSION_2 =
"GNU General Public License, version 2";
+ @Deprecated
public static final String RAT_LICENSE_FAMILY_NAME_VALUE_GPL_VERSION_3 =
"GNU General Public License, version 3";
+ @Deprecated
public static final String RAT_LICENSE_FAMILY_NAME_VALUE_MIT =
"The MIT License";
+ @Deprecated
public static final String RAT_LICENSE_FAMILY_NAME_VALUE_CDDL1 =
"COMMON DEVELOPMENT AND DISTRIBUTION LICENSE Version 1.0";
+ @Deprecated
public static final String RAT_LICENSE_FAMILY_NAME_VALUE_ACADEMIC_FREE_LICENSE_VERSION_2_1 = "Academic Free License, Version 2.1";
+
public static final String RAT_LICENSE_FAMILY_NAME_VALUE_UNKNOWN = "?????";
+ @Deprecated
public static final Datum RAT_LICENSE_FAMILY_NAME_DATUM_W3C_SOFTWARE_COPYRIGHT
= new Datum(RAT_URL_LICENSE_FAMILY_NAME, RAT_LICENSE_FAMILY_NAME_VALUE_W3C_SOFTWARE_COPYRIGHT);
+ @Deprecated
public static final Datum RAT_LICENSE_FAMILY_NAME_DATUM_W3C_DOCUMENT_COPYRIGHT
= new Datum(RAT_URL_LICENSE_FAMILY_NAME, RAT_LICENSE_FAMILY_NAME_VALUE_W3C_DOCUMENT_COPYRIGHT);
+ @Deprecated
public static final Datum RAT_LICENSE_FAMILY_NAME_DATUM_OASIS_OPEN_LICENSE
= new Datum(RAT_URL_LICENSE_FAMILY_NAME, RAT_LICENSE_FAMILY_NAME_VALUE_OASIS_OPEN_LICENSE);
+ @Deprecated
public static final Datum RAT_LICENSE_FAMILY_NAME_DATUM_MODIFIED_BSD_LICENSE
= new Datum(RAT_URL_LICENSE_FAMILY_NAME, RAT_LICENSE_FAMILY_NAME_VALUE_MODIFIED_BSD_LICENSE);
+ @Deprecated
public static final Datum RAT_LICENSE_FAMILY_NAME_DATUM_APACHE_LICENSE_VERSION_2_0
= new Datum(RAT_URL_LICENSE_FAMILY_NAME, RAT_LICENSE_FAMILY_NAME_VALUE_APACHE_LICENSE_VERSION_2_0);
+ @Deprecated
public static final Datum
- RAT_LICENSE_FAMILY_NAME_DATUM_GPL_VERSION_1 = new Datum(RAT_URL_LICENSE_FAMILY_NAME, RAT_LICENSE_FAMILY_CATEGORY_VALUE_GPL1);
+ RAT_LICENSE_FAMILY_NAME_DATUM_GPL_VERSION_1 = new Datum(RAT_URL_LICENSE_FAMILY_NAME, RAT_LICENSE_FAMILY_NAME_VALUE_GPL_VERSION_1);
+ @Deprecated
public static final Datum
- RAT_LICENSE_FAMILY_NAME_DATUM_GPL_VERSION_2 = new Datum(RAT_URL_LICENSE_FAMILY_NAME, RAT_LICENSE_FAMILY_CATEGORY_VALUE_GPL2);
+ RAT_LICENSE_FAMILY_NAME_DATUM_GPL_VERSION_2 = new Datum(RAT_URL_LICENSE_FAMILY_NAME, RAT_LICENSE_FAMILY_NAME_VALUE_GPL_VERSION_2);
+ @Deprecated
public static final Datum
RAT_LICENSE_FAMILY_NAME_DATUM_GPL_VERSION_3 = new Datum(RAT_URL_LICENSE_FAMILY_NAME, RAT_LICENSE_FAMILY_NAME_VALUE_GPL_VERSION_3);
+ @Deprecated
public static final Datum
RAT_LICENSE_FAMILY_NAME_DATUM_MIT = new Datum(RAT_URL_LICENSE_FAMILY_NAME, RAT_LICENSE_FAMILY_NAME_VALUE_MIT);
+ @Deprecated
public static final Datum
RAT_LICENSE_FAMILY_NAME_DATUM_CDDL1 = new Datum(RAT_URL_LICENSE_FAMILY_NAME, RAT_LICENSE_FAMILY_NAME_VALUE_CDDL1);
+ @Deprecated
public static final Datum RAT_LICENSE_FAMILY_NAME_DATUM_ACADEMIC_FREE_LICENSE_VERSION_2_1
= new Datum(RAT_URL_LICENSE_FAMILY_NAME, RAT_LICENSE_FAMILY_NAME_VALUE_ACADEMIC_FREE_LICENSE_VERSION_2_1);
+
public static final Datum RAT_LICENSE_FAMILY_NAME_DATUM_UNKNOWN
= new Datum(RAT_URL_LICENSE_FAMILY_NAME, RAT_LICENSE_FAMILY_NAME_VALUE_UNKNOWN);
@@ -131,41 +180,40 @@ public class MetaData {
public static final String RAT_URL_APPROVED_LICENSE = RAT_BASE_URL + "#ApprovedLicense";
public static final String RAT_APPROVED_LICENSE_VALUE_TRUE = Boolean.TRUE.toString();
public static final String RAT_APPROVED_LICENSE_VALUE_FALSE = Boolean.FALSE.toString();
- public static final Datum RAT_APPROVED_LICENSE_DATIM_TRUE = new Datum(RAT_URL_APPROVED_LICENSE, RAT_APPROVED_LICENSE_VALUE_TRUE);
- public static final Datum RAT_APPROVED_LICENSE_DATIM_FALSE = new Datum(RAT_URL_APPROVED_LICENSE, RAT_APPROVED_LICENSE_VALUE_FALSE);
-
- private ContentType contentType;
+ public static final Datum RAT_APPROVED_LICENSE_DATUM_TRUE = new Datum(RAT_URL_APPROVED_LICENSE, RAT_APPROVED_LICENSE_VALUE_TRUE);
+ public static final Datum RAT_APPROVED_LICENSE_DATUM_FALSE = new Datum(RAT_URL_APPROVED_LICENSE, RAT_APPROVED_LICENSE_VALUE_FALSE);
+ @Deprecated
+ public static final Datum RAT_APPROVED_LICENSE_DATIM_TRUE = RAT_APPROVED_LICENSE_DATUM_TRUE;
+ @Deprecated
+ public static final Datum RAT_APPROVED_LICENSE_DATIM_FALSE = RAT_APPROVED_LICENSE_DATUM_FALSE;
+
/**
* Only likely to be a small quantity of data
* so trade some performance for simplicity.
*/
private final List data;
- public MetaData() {
- this(null);
- }
-
- public MetaData(final ContentType contentType) {
- this.contentType = contentType;
- this.data = new ArrayList<>(16);
- }
-
/**
- * Gets the content type for the subject.
- * @return or null when the type is unknown
+ * Create metadata without a content type.
*/
- public ContentType getContentType() {
- return contentType;
+ public MetaData() {
+ this.data = new ArrayList<>(16);
}
/**
- * Sets the content type for this subject.
- * @param contentType ContentType
,
- * or null when the content type is unknown
+ * Add the license information to the metadata.
+ * @param license the license to add metadata for.
*/
- public void setContentType(final ContentType contentType) {
- this.contentType = contentType;
+ public void reportOnLicense(ILicense license) {
+
+ if (StringUtils.isNotBlank(license.getNotes())) {
+ set(new MetaData.Datum(MetaData.RAT_URL_HEADER_SAMPLE, license.getNotes()));
+ }
+ set(new MetaData.Datum(MetaData.RAT_URL_HEADER_CATEGORY, license.getLicenseFamily().getFamilyCategory()));
+ set(new MetaData.Datum(MetaData.RAT_URL_LICENSE_FAMILY_CATEGORY, license.getLicenseFamily().getFamilyCategory()));
+ set(new MetaData.Datum(MetaData.RAT_URL_LICENSE_FAMILY_NAME, license.getLicenseFamily().getFamilyName()));
}
+
/**
* Gets all data.
@@ -252,7 +300,6 @@ public boolean clear(final String name) {
*/
public void clear() {
data.clear();
- this.contentType = null;
}
/**
diff --git a/apache-rat-core/src/main/java/org/apache/rat/config/ReportFormat.java b/apache-rat-core/src/main/java/org/apache/rat/config/ReportFormat.java
index 6215585db..cd915be8f 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/config/ReportFormat.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/config/ReportFormat.java
@@ -25,6 +25,6 @@ public enum ReportFormat {
XML;
public boolean is(String optionGiven) {
- return optionGiven != null && optionGiven.length() != 0 && name().equalsIgnoreCase(optionGiven);
+ return optionGiven != null && !optionGiven.isEmpty() && name().equalsIgnoreCase(optionGiven);
}
}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/config/SourceCodeManagementSystems.java b/apache-rat-core/src/main/java/org/apache/rat/config/SourceCodeManagementSystems.java
index 908ec8291..71973d3b1 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/config/SourceCodeManagementSystems.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/config/SourceCodeManagementSystems.java
@@ -74,7 +74,7 @@ public List getExclusions() {
}
public boolean hasIgnoreFile() {
- return ignoreFile != null && ignoreFile.length() != 0;
+ return ignoreFile != null && !ignoreFile.isEmpty();
}
/**
diff --git a/apache-rat-core/src/main/java/org/apache/rat/configuration/Format.java b/apache-rat-core/src/main/java/org/apache/rat/configuration/Format.java
new file mode 100644
index 000000000..f995773ca
--- /dev/null
+++ b/apache-rat-core/src/main/java/org/apache/rat/configuration/Format.java
@@ -0,0 +1,120 @@
+/*
+ * 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.configuration;
+
+import java.io.File;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Arrays;
+
+import org.apache.rat.ConfigurationException;
+
+/**
+ * An enumeration of the types of files that can contain the configuration
+ * information.
+ */
+public enum Format {
+ /** an XML file */
+ XML(XMLConfigurationReader.class, "xml"),
+ /** A plain text file */
+ TXT(null, "txt", "text");
+
+ private final String[] suffix;
+
+ private Constructor matcherReader;
+ private Constructor licenseReader;
+
+ @SuppressWarnings("unchecked")
+ Format(Class> reader, String... suffix) {
+ if (reader != null) {
+ try {
+ matcherReader = MatcherReader.class.isAssignableFrom(reader)
+ ? (Constructor) reader.getConstructor()
+ : null;
+ licenseReader = LicenseReader.class.isAssignableFrom(reader)
+ ? (Constructor) reader.getConstructor()
+ : null;
+ } catch (NoSuchMethodException | SecurityException e) {
+ throw new ConfigurationException("Error retrieving no argument constructor for " + reader.getName(), e);
+ }
+ }
+ this.suffix = suffix;
+ }
+
+ /**
+ * @return a new instance of MatcherReader for this format.
+ */
+ public MatcherReader matcherReader() {
+ try {
+ return matcherReader == null ? null : matcherReader.newInstance();
+ } catch (InstantiationException | IllegalAccessException | IllegalArgumentException
+ | InvocationTargetException e) {
+ throw new ConfigurationException("Can not instantiate MatcherReader for " + this.name(), e);
+ }
+ }
+
+ /**
+ * @return a new instance of the LicenseReader for this format.
+ */
+ public LicenseReader licenseReader() {
+ try {
+ return licenseReader == null ? null : licenseReader.newInstance();
+ } catch (InstantiationException | IllegalAccessException | IllegalArgumentException
+ | InvocationTargetException e) {
+ throw new ConfigurationException("Can not instantiate LicenseReader for " + this.name(), e);
+ }
+ }
+
+ /**
+ * Determine the {@code Format} from the file name.
+ * @param name the file name to check.
+ * @return the Format
+ */
+ public static Format fromName(String name) {
+ String[] parts = name.split("\\.");
+ String suffix = parts[parts.length - 1];
+ for (Format f : Format.values()) {
+ if (Arrays.asList(f.suffix).contains(suffix)) {
+ return f;
+ }
+ }
+ throw new IllegalArgumentException(String.format("No such suffix: %s", suffix));
+ }
+
+ /**
+ * Determine the {@code Format} from a URL.
+ * @param url the URL to check.
+ * @return the Format
+ */
+ public static Format fromURL(URL url) {
+ return Format.fromName(url.getFile());
+ }
+
+ /**
+ * Determine the {@code Format} from a File.
+ * @param file the File to check.
+ * @return the Format
+ * @throws MalformedURLException in case the file cannot be found.
+ */
+ public static Format fromFile(File file) throws MalformedURLException {
+ return Format.fromURL(file.toURI().toURL());
+ }
+}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/configuration/LicenseReader.java b/apache-rat-core/src/main/java/org/apache/rat/configuration/LicenseReader.java
new file mode 100644
index 000000000..428137072
--- /dev/null
+++ b/apache-rat-core/src/main/java/org/apache/rat/configuration/LicenseReader.java
@@ -0,0 +1,59 @@
+/*
+ * 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.configuration;
+
+import java.net.URL;
+import java.util.SortedSet;
+
+import org.apache.rat.license.ILicense;
+import org.apache.rat.license.ILicenseFamily;
+
+/**
+ * An interface describing the methods of a LicenseReader.
+ */
+public interface LicenseReader {
+ /**
+ * Adds a URL to the set of files to be read.
+ *
+ * @param url the URL to read.
+ */
+ void addLicenses(URL url);
+
+ /**
+ * Reads the configuration and extracts instances of ILicense.
+ *
+ * @return A collection of ILicense.
+ */
+ SortedSet readLicenses();
+
+ /**
+ * Reads the configuration and extracts instances of ILicenseFamily.
+ *
+ * @return A collection of ILicenseFamily.
+ */
+ SortedSet readFamilies();
+
+ /**
+ * Reads the configuration and extracts the list of approved licenses.
+ *
+ * @return The list of approved licenses specified in the configuration or an
+ * empty list if none specified.
+ */
+ SortedSet approvedLicenseId();
+}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/configuration/MatcherBuilderTracker.java b/apache-rat-core/src/main/java/org/apache/rat/configuration/MatcherBuilderTracker.java
new file mode 100644
index 000000000..447ad82e3
--- /dev/null
+++ b/apache-rat-core/src/main/java/org/apache/rat/configuration/MatcherBuilderTracker.java
@@ -0,0 +1,115 @@
+/*
+ * 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.configuration;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.rat.ConfigurationException;
+import org.apache.rat.Defaults;
+import org.apache.rat.configuration.builders.AbstractBuilder;
+
+/**
+ * A class to track the Matcher Builders as they are defined. Matchers may be defined in multiple configuration files
+ * this method tracks them so that they can be referenced across the configuration files.
+ */
+public class MatcherBuilderTracker {
+
+ private static MatcherBuilderTracker INSTANCE;
+
+ private final Map> matcherBuilders;
+
+ private static synchronized MatcherBuilderTracker instance() {
+ if (INSTANCE == null) {
+ INSTANCE = new MatcherBuilderTracker();
+ Defaults.init();
+ }
+ return INSTANCE;
+ }
+
+ /**
+ * Adds a builder to the tracker.
+ * If the {@code name} is null then the builder class name simple is used with the "Builder" suffix removed.
+ * @param className the Class name for the builder.
+ * @param name the short name for the builder.
+ */
+ public static void addBuilder(String className, String name) {
+ instance().addBuilderImpl(className, name);
+ }
+
+ /**
+ * Get the matching builder for the name.
+ * @param name The name of the builder.
+ * @return the builder for that name.
+ */
+ public static AbstractBuilder getMatcherBuilder(String name) {
+ Class extends AbstractBuilder> clazz = instance().matcherBuilders.get(name);
+ if (clazz == null) {
+ StringBuilder sb = new StringBuilder("\nValid builders\n");
+ instance().matcherBuilders.keySet().forEach(x -> sb.append(x).append("\n"));
+ sb.append("ERROR MSG\n");
+ throw new ConfigurationException(sb.append("No matcher builder named ").append(name).toString());
+ }
+ try {
+ return clazz.getConstructor().newInstance();
+ } catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException
+ | IllegalArgumentException | InvocationTargetException e) {
+ throw new ConfigurationException(
+ String.format("Can not instantiate matcher builder named %s (%s)", name, clazz.getName()), e);
+ }
+ }
+
+ private MatcherBuilderTracker() {
+ matcherBuilders = new HashMap<>();
+ }
+
+ private void addBuilderImpl(String className, String name) {
+ Objects.requireNonNull(className, "className may not be null");
+ Class> clazz;
+ try {
+ clazz = getClass().getClassLoader().loadClass(className);
+ } catch (ClassNotFoundException e) {
+ throw new ConfigurationException(e);
+ }
+ if (AbstractBuilder.class.isAssignableFrom(clazz)) {
+ @SuppressWarnings("unchecked")
+ Class extends AbstractBuilder> candidate = (Class extends AbstractBuilder>) clazz;
+ // String name = attributes.get(AttributeName.name);
+ if (StringUtils.isBlank(name)) {
+ name = candidate.getSimpleName();
+ if (!name.endsWith("Builder")) {
+ throw new ConfigurationException(
+ "name is required, or " + candidate.getName() + " must end with 'Builder'");
+ }
+ name = name.substring(0, name.lastIndexOf("Builder"));
+ if (StringUtils.isBlank(name)) {
+ throw new ConfigurationException("Last segment of " + candidate.getName()
+ + " may not be 'Builder', but must end in 'Builder'");
+ }
+ name = name.replaceFirst(".", StringUtils.lowerCase(name.substring(0, 1)));
+ }
+ matcherBuilders.put(name, candidate);
+ } else {
+ throw new ConfigurationException("Class " + clazz.getName() + " does not extend " + AbstractBuilder.class);
+ }
+ }
+}
diff --git a/apache-rat-plugin/src/main/java/org/apache/rat/mp/LicenseFamilySpecification.java b/apache-rat-core/src/main/java/org/apache/rat/configuration/MatcherReader.java
similarity index 54%
rename from apache-rat-plugin/src/main/java/org/apache/rat/mp/LicenseFamilySpecification.java
rename to apache-rat-core/src/main/java/org/apache/rat/configuration/MatcherReader.java
index 5bd4941ea..d6e42253d 100644
--- a/apache-rat-plugin/src/main/java/org/apache/rat/mp/LicenseFamilySpecification.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/configuration/MatcherReader.java
@@ -1,5 +1,3 @@
-package org.apache.rat.mp;
-
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
@@ -18,36 +16,23 @@
* specific language governing permissions and limitations
* under the License.
*/
+package org.apache.rat.configuration;
+
+import java.net.URL;
/**
- * Used to specify additional license families. A license family is basically a class, which implements
- * {@link org.apache.rat.license.ILicenseFamily}.
+ * An interface that describes the methods of a Matcher reader.
*/
-public class LicenseFamilySpecification
-{
- /**
- * The license family's class name.
- */
- private String className;
-
+public interface MatcherReader {
/**
- * Returns the license familys class name.
+ * Adds a URL to the set of files to be read.
*
- * @return Class name of the license family.
+ * @param url the URL to read.
*/
- public String getClassName()
- {
- return className;
- }
+ void addMatchers(URL url);
/**
- * Sets the license family's class name. Required.
- *
- * @param pClassName
- * Class name of the license family.
+ * Reads the configuration and MatcherBuilder classes and adds them to Readers.
*/
- public void setClassName( String pClassName )
- {
- className = pClassName;
- }
+ void readMatcherBuilders();
}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/configuration/XMLConfigurationReader.java b/apache-rat-core/src/main/java/org/apache/rat/configuration/XMLConfigurationReader.java
new file mode 100644
index 000000000..b05711b07
--- /dev/null
+++ b/apache-rat-core/src/main/java/org/apache/rat/configuration/XMLConfigurationReader.java
@@ -0,0 +1,394 @@
+/*
+ * 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.configuration;
+
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.net.URL;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import java.util.function.Consumer;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.commons.beanutils.MethodUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.rat.ConfigurationException;
+import org.apache.rat.analysis.IHeaderMatcher;
+import org.apache.rat.analysis.matchers.FullTextMatcher;
+import org.apache.rat.analysis.matchers.SimpleTextMatcher;
+import org.apache.rat.configuration.builders.AbstractBuilder;
+import org.apache.rat.configuration.builders.ChildContainerBuilder;
+import org.apache.rat.configuration.builders.MatcherRefBuilder;
+import org.apache.rat.configuration.builders.TextCaptureBuilder;
+import org.apache.rat.license.ILicense;
+import org.apache.rat.license.ILicenseFamily;
+import org.apache.rat.license.LicenseFamilySetFactory;
+import org.apache.rat.license.LicenseSetFactory;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
+
+/**
+ * A class that reads the XML configuration file format.
+ *
+ * {@code }
+ * {@code }
+ * {@code }
+ * {@code }
+ * {@code }
+ * {@code }
+ * {@code }
+ * {@code ... }
+ * {@code ... }
+ * {@code }
+ * {@code }
+ * {@code }
+ * {@code }
+ * {@code }
+ * {@code }
+ * {@code }
+ * {@code }
+ * {@code }
+ * {@code }
+ * {@code }
+ * {@code }
+ *
+ */
+
+public class XMLConfigurationReader implements LicenseReader, MatcherReader {
+
+ private final static String ATT_ID = "id";
+ private final static String ATT_NAME = "name";
+ private final static String ATT_DERIVED_FROM = "derived_from";
+ private final static String ATT_LICENSE_REF = "license_ref";
+ private final static String ATT_CLASS_NAME = "class";
+
+ private final static String ROOT = "rat-config";
+ private final static String FAMILIES = "families";
+ private final static String LICENSES = "licenses";
+ private final static String LICENSE = "license";
+ private final static String APPROVED = "approved";
+ private final static String FAMILY = "family";
+ private final static String NOTE = "note";
+ private final static String MATCHERS = "matchers";
+ private final static String MATCHER = "matcher";
+
+ private Document document;
+ private final Element rootElement;
+ private final Element familiesElement;
+ private final Element licensesElement;
+ private final Element approvedElement;
+ private final Element matchersElement;
+
+ private final SortedSet licenses;
+ private final Map matchers;
+ private final SortedSet licenseFamilies;
+ private final SortedSet approvedFamilies;
+
+ /**
+ * Constructs the XML configuration reader.
+ */
+ public XMLConfigurationReader() {
+ try {
+ document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
+ } catch (ParserConfigurationException e) {
+ throw new IllegalStateException("No XML parser defined", e);
+ }
+ rootElement = document.createElement(ROOT);
+ document.appendChild(rootElement);
+ familiesElement = document.createElement(FAMILIES);
+ rootElement.appendChild(familiesElement);
+ licensesElement = document.createElement(LICENSES);
+ rootElement.appendChild(licensesElement);
+ approvedElement = document.createElement(APPROVED);
+ rootElement.appendChild(approvedElement);
+ matchersElement = document.createElement(MATCHERS);
+ rootElement.appendChild(matchersElement);
+ licenses = LicenseSetFactory.emptyLicenseSet();
+ licenseFamilies = LicenseFamilySetFactory.emptyLicenseFamilySet();
+ approvedFamilies = new TreeSet<>();
+ matchers = new HashMap<>();
+ }
+
+ @Override
+ public void addLicenses(URL url) {
+ read(url);
+ }
+
+ /**
+ * Read the urls and create a single document to process.
+ *
+ * @param urls The URLs to read.
+ */
+ public void read(URL... urls) {
+ DocumentBuilder builder;
+ try {
+ builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+ } catch (ParserConfigurationException e) {
+ throw new ConfigurationException("Unable to create DOM builder", e);
+ }
+ for (URL url : urls) {
+ try {
+ add(builder.parse(url.openStream()));
+ } catch (SAXException | IOException e) {
+ throw new ConfigurationException("Unable to read url: " + url, e);
+ }
+ }
+ }
+
+ /**
+ * Applies the {@code consumer} to each node in the {@code list}
+ *
+ * @param list the NodeList to process
+ * @param consumer the consumer to apply to each node in the list.
+ */
+ private void nodeListConsumer(NodeList list, Consumer consumer) {
+ for (int i = 0; i < list.getLength(); i++) {
+ consumer.accept(list.item(i));
+ }
+ }
+
+ /**
+ * Merge the new document into the document that this reader processes.
+ *
+ * @param newDoc the Document to merge.
+ */
+ public void add(Document newDoc) {
+ nodeListConsumer(newDoc.getElementsByTagName(FAMILIES),
+ nl -> nodeListConsumer( nl.getChildNodes(),
+ n -> familiesElement.appendChild(rootElement.getOwnerDocument().adoptNode(n.cloneNode(true)))));
+ nodeListConsumer(newDoc.getElementsByTagName(LICENSE),
+ n -> licensesElement.appendChild(rootElement.getOwnerDocument().adoptNode(n.cloneNode(true))));
+ nodeListConsumer(newDoc.getElementsByTagName(APPROVED),
+ nl -> nodeListConsumer( nl.getChildNodes(),
+ n -> approvedElement.appendChild(rootElement.getOwnerDocument().adoptNode(n.cloneNode(true)))));
+ nodeListConsumer(newDoc.getElementsByTagName(MATCHERS),
+ n -> matchersElement.appendChild(rootElement.getOwnerDocument().adoptNode(n.cloneNode(true))));
+ }
+
+ /**
+ * Get a map of Node attribute names to values.
+ *
+ * @param node The node to process
+ * @return the map of attributes on the node
+ */
+ private Map attributes(Node node) {
+ NamedNodeMap nnm = node.getAttributes();
+ Map result = new HashMap<>();
+ for (int i = 0; i < nnm.getLength(); i++) {
+ Node n = nnm.item(i);
+ result.put(n.getNodeName(), n.getNodeValue());
+ }
+ return result;
+ }
+
+ /**
+ * Create a text matcher. Will construct a FullTextMatcher or a
+ * SimpleTextMatcher depending on the complexity of the text.
+ *
+ * @param id the id for the Matcher.
+ * @param txt the text to match
+ * @return the IHeaderMatcher that matches the text.
+ */
+ public static IHeaderMatcher createTextMatcher(String id, String txt) {
+ boolean complex = txt.contains(" ") | txt.contains("\\t") | txt.contains("\\n") | txt.contains("\\r")
+ | txt.contains("\\f") | txt.contains("\\v");
+ return complex ? new FullTextMatcher(id, txt) : new SimpleTextMatcher(id, txt);
+ }
+
+ private AbstractBuilder parseMatcher(Node matcherNode) {
+ AbstractBuilder builder = MatcherBuilderTracker.getMatcherBuilder(matcherNode.getNodeName());
+
+ NamedNodeMap nnm = matcherNode.getAttributes();
+ for (int i = 0; i < nnm.getLength(); i++) {
+ Node n = nnm.item(i);
+ String methodName = "set" + StringUtils.capitalize(n.getNodeName());
+ try {
+ MethodUtils.invokeExactMethod(builder, methodName, n.getNodeValue());
+ } catch (NoSuchMethodException e) {
+ throw new ConfigurationException(
+ String.format("'%s' does not have a setter '%s' that takes a String argument",
+ matcherNode.getNodeName(), methodName));
+ } catch (IllegalAccessException | InvocationTargetException | DOMException e) {
+ throw new ConfigurationException(e);
+ }
+ }
+ if (builder instanceof ChildContainerBuilder) {
+ ChildContainerBuilder ccb = (ChildContainerBuilder) builder;
+ nodeListConsumer(matcherNode.getChildNodes(), x -> {
+ if (x.getNodeType() == Node.ELEMENT_NODE) {
+ ccb.add(parseMatcher(x));
+ }
+ });
+ }
+ if (builder instanceof TextCaptureBuilder) {
+ ((TextCaptureBuilder) builder).setText(matcherNode.getTextContent().trim());
+ }
+
+ if (builder instanceof MatcherRefBuilder) {
+ ((MatcherRefBuilder) builder).setMatchers(matchers);
+ }
+
+ if (builder.hasId()) {
+ builder = new DelegatingBuilder(builder) {
+ @Override
+ public IHeaderMatcher build() {
+ IHeaderMatcher result = delegate.build();
+ matchers.put(result.getId(), result);
+ return result;
+ }
+ };
+ }
+ return builder;
+ }
+
+ private ILicense parseLicense(Node licenseNode) {
+ Map attributes = attributes(licenseNode);
+ ILicense.Builder builder = ILicense.builder();
+
+ builder.setLicenseFamilyCategory(attributes.get(FAMILY));
+ builder.setName(attributes.get(ATT_NAME));
+ builder.setId(attributes.get(ATT_ID));
+
+ StringBuilder notesBuilder = new StringBuilder();
+ nodeListConsumer(licenseNode.getChildNodes(), x -> {
+ if (x.getNodeType() == Node.ELEMENT_NODE) {
+ if (x.getNodeName().equals(NOTE)) {
+ notesBuilder.append(x.getTextContent()).append("\n");
+ } else {
+ builder.setMatcher(parseMatcher(x));
+ }
+ }
+ });
+ builder.setDerivedFrom(StringUtils.defaultIfBlank(attributes.get(ATT_DERIVED_FROM), null));
+ builder.setNotes(StringUtils.defaultIfBlank(notesBuilder.toString().trim(), null));
+ return builder.build(licenseFamilies);
+ }
+
+ @Override
+ public SortedSet readLicenses() {
+ readFamilies();
+ readMatcherBuilders();
+ if (licenses.isEmpty()) {
+ nodeListConsumer(document.getElementsByTagName(LICENSE), x -> licenses.add(parseLicense(x)));
+ document = null;
+ }
+ return Collections.unmodifiableSortedSet(licenses);
+ }
+
+
+ @Override
+ public SortedSet readFamilies() {
+ if (licenseFamilies.isEmpty()) {
+ nodeListConsumer(document.getElementsByTagName(FAMILIES),
+ x -> nodeListConsumer(x.getChildNodes(), this::parseFamily));
+ nodeListConsumer(document.getElementsByTagName(APPROVED),
+ x -> nodeListConsumer(x.getChildNodes(), this::parseApproved));
+ }
+ return Collections.unmodifiableSortedSet(licenseFamilies);
+ }
+
+ private ILicenseFamily parseFamily(Map attributes) {
+ if (attributes.containsKey(ATT_ID)) {
+ ILicenseFamily.Builder builder = ILicenseFamily.builder();
+ builder.setLicenseFamilyCategory(attributes.get(ATT_ID));
+ builder.setLicenseFamilyName(StringUtils.defaultIfBlank(attributes.get(ATT_NAME), attributes.get(ATT_ID)));
+ return builder.build();
+ }
+ return null;
+ }
+
+ private void parseFamily(Node familyNode) {
+ if (FAMILY.equals(familyNode.getNodeName())) {
+ ILicenseFamily result = parseFamily(attributes(familyNode));
+ if (result == null) {
+ throw new ConfigurationException(String.format("families/family tag requires %s attribute", ATT_ID));
+ }
+ licenseFamilies.add(result);
+ }
+ }
+
+ private void parseApproved(Node approvedNode) {
+ if (FAMILY.equals(approvedNode.getNodeName())) {
+ Map attributes = attributes(approvedNode);
+ if (attributes.containsKey(ATT_LICENSE_REF)) {
+ approvedFamilies.add(attributes.get(ATT_LICENSE_REF));
+ } else if (attributes.containsKey(ATT_ID)) {
+ ILicenseFamily target = parseFamily(attributes);
+ licenseFamilies.add(target);
+ approvedFamilies.add(target.getFamilyCategory());
+ } else {
+ throw new ConfigurationException(
+ String.format("family tag requires %s or %s attribute", ATT_LICENSE_REF, ATT_ID));
+ }
+ }
+ }
+
+ @Override
+ public SortedSet approvedLicenseId() {
+ if (licenses.isEmpty()) {
+ this.readLicenses();
+ }
+ if (approvedFamilies.isEmpty()) {
+ SortedSet result = new TreeSet<>();
+ licenses.stream().map(x -> x.getLicenseFamily().getFamilyCategory()).forEach(result::add);
+ return result;
+ }
+ return Collections.unmodifiableSortedSet(approvedFamilies);
+ }
+
+ private void parseMatcherBuilder(Node classNode) {
+ Map attributes = attributes(classNode);
+ if (attributes.get(ATT_CLASS_NAME) == null) {
+ throw new ConfigurationException("matcher must have a " + ATT_CLASS_NAME + " attribute");
+ }
+ MatcherBuilderTracker.addBuilder(attributes.get(ATT_CLASS_NAME), attributes.get(ATT_NAME));
+ }
+
+ @Override
+ public void readMatcherBuilders() {
+ nodeListConsumer(document.getElementsByTagName(MATCHER), this::parseMatcherBuilder);
+ }
+
+ @Override
+ public void addMatchers(URL url) {
+ read(url);
+ }
+
+ /**
+ * An abstract builder that delegates to another abstract builder.
+ */
+ abstract static class DelegatingBuilder extends AbstractBuilder {
+ protected final AbstractBuilder delegate;
+
+ DelegatingBuilder(AbstractBuilder delegate) {
+ this.delegate = delegate;
+ }
+ }
+}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/generation/JavaDocLicenseNotRequired.java b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/AbstractBuilder.java
similarity index 56%
rename from apache-rat-core/src/main/java/org/apache/rat/analysis/generation/JavaDocLicenseNotRequired.java
rename to apache-rat-core/src/main/java/org/apache/rat/configuration/builders/AbstractBuilder.java
index d165b8ea4..7d546a03a 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/analysis/generation/JavaDocLicenseNotRequired.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/AbstractBuilder.java
@@ -15,35 +15,52 @@
* KIND, either express or implied. See the License for the *
* specific language governing permissions and limitations *
* under the License. *
- */
-package org.apache.rat.analysis.generation;
+ */
+package org.apache.rat.configuration.builders;
+import org.apache.commons.lang3.StringUtils;
import org.apache.rat.analysis.IHeaderMatcher;
-import org.apache.rat.analysis.RatHeaderAnalysisException;
-import org.apache.rat.api.Document;
-import org.apache.rat.api.MetaData;
/**
- * JavaDocs are generated and so no license is required.
- * It is useful to note these separately.
+ * An abstract IHeaderMatcher.Builder.
*/
-public class JavaDocLicenseNotRequired implements IHeaderMatcher {
+public abstract class AbstractBuilder implements IHeaderMatcher.Builder {
- private static final String JAVADOC_REGEX_DEFN = "Generated by javadoc";
-
- public boolean match(Document subject, String line) throws RatHeaderAnalysisException {
- boolean result = line.contains(JAVADOC_REGEX_DEFN);
- if (result) {
- reportOnLicense(subject);
- }
- return result;
+ private String id;
+
+ /**
+ * Protected empty constructor.
+ */
+ protected AbstractBuilder() {
+ }
+
+ /**
+ * Set the id for the matcher.
+ * @param id the id to use.
+ * @return this builder for chaining.
+ */
+ public final AbstractBuilder setId(String id) {
+ this.id = id;
+ return this;
}
- private void reportOnLicense(Document subject) {
- subject.getMetaData().set(MetaData.RAT_LICENSE_FAMILY_CATEGORY_DATUM_GEN);
+ /**
+ * @return {@code true} if the id is not null and not blank.
+ */
+ public final boolean hasId() {
+ return !StringUtils.isBlank(id);
+ }
+
+ /**
+ * @return the id as specified in the builder.
+ */
+ protected String getId() {
+ return id;
}
- public void reset() {
- // stateless
+ @Override
+ public String toString() {
+ return String.format( "%s with id %s", this.getClass(), id);
}
-}
+
+}
\ No newline at end of file
diff --git a/apache-rat-core/src/main/java/org/apache/rat/license/GPL2LicenseFamily.java b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/AllBuilder.java
similarity index 76%
rename from apache-rat-core/src/main/java/org/apache/rat/license/GPL2LicenseFamily.java
rename to apache-rat-core/src/main/java/org/apache/rat/configuration/builders/AllBuilder.java
index e2d252201..9c0980e5f 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/license/GPL2LicenseFamily.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/AllBuilder.java
@@ -15,17 +15,19 @@
* KIND, either express or implied. See the License for the *
* specific language governing permissions and limitations *
* under the License. *
- */
-package org.apache.rat.license;
+ */
+package org.apache.rat.configuration.builders;
-import org.apache.rat.api.MetaData;
+import org.apache.rat.analysis.IHeaderMatcher;
+import org.apache.rat.analysis.matchers.AndMatcher;
/**
- * Base implementation for GPLv2 or later.
+ * Constructs a All matcher.
*/
-public class GPL2LicenseFamily extends SimpleLicenseFamily {
- public GPL2LicenseFamily() {
- super(MetaData.RAT_LICENSE_FAMILY_NAME_VALUE_GPL_VERSION_2);
- }
+public class AllBuilder extends ChildContainerBuilder {
+ @Override
+ public IHeaderMatcher build() {
+ return new AndMatcher(getId(), getChildren());
+ }
}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/license/CDDL1LicenseFamily.java b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/AnyBuilder.java
similarity index 76%
rename from apache-rat-core/src/main/java/org/apache/rat/license/CDDL1LicenseFamily.java
rename to apache-rat-core/src/main/java/org/apache/rat/configuration/builders/AnyBuilder.java
index 6bf01c0bd..6ecb73e97 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/license/CDDL1LicenseFamily.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/AnyBuilder.java
@@ -16,16 +16,18 @@
* specific language governing permissions and limitations *
* under the License. *
*/
-package org.apache.rat.license;
+package org.apache.rat.configuration.builders;
-import org.apache.rat.api.MetaData;
+import org.apache.rat.analysis.IHeaderMatcher;
+import org.apache.rat.analysis.matchers.OrMatcher;
/**
- * Base implementation for CDDL 1.0 licenses.
+ * Constructs an Any matcher.
*/
-public class CDDL1LicenseFamily extends SimpleLicenseFamily {
+public class AnyBuilder extends ChildContainerBuilder {
- public CDDL1LicenseFamily() {
- super(MetaData.RAT_LICENSE_FAMILY_NAME_VALUE_CDDL1);
+ @Override
+ public IHeaderMatcher build() {
+ return new OrMatcher(getId(), getChildren());
}
}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/ChildContainerBuilder.java b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/ChildContainerBuilder.java
new file mode 100644
index 000000000..d67264b42
--- /dev/null
+++ b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/ChildContainerBuilder.java
@@ -0,0 +1,110 @@
+/*
+ * 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.configuration.builders;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.rat.ConfigurationException;
+import org.apache.rat.analysis.IHeaderMatcher;
+import org.apache.rat.analysis.IHeaderMatcher.Builder;
+
+/**
+ * Constructs a builder that contains other builders.
+ */
+public abstract class ChildContainerBuilder extends AbstractBuilder {
+
+ /**
+ * The list of builders that will build the enclosed matchers.
+ */
+ protected final List children = new ArrayList<>();
+
+ /**
+ * Empty default constructor.
+ */
+ protected ChildContainerBuilder() {
+ }
+
+ /**
+ * Reads a text file. Each line becomes a text matcher in the resulting list.
+ *
+ * @param resourceName the name of the resource to read.
+ * @return a List of Matchers, one for each non-empty line in the input file.
+ */
+ public AbstractBuilder setResource(String resourceName) {
+ URL url = this.getClass().getResource(resourceName);
+ try (final InputStream in = url.openStream()) {
+ BufferedReader buffer = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8));
+ String txt;
+ while (null != (txt = buffer.readLine())) {
+ txt = txt.trim();
+ if (StringUtils.isNotBlank(txt)) {
+ children.add(Builder.text().setText(txt));
+ }
+ }
+ return this;
+ } catch (IOException e) {
+ throw new ConfigurationException("Unable to read matching text file: " + resourceName, e);
+ }
+ }
+
+ /**
+ * Adds a builder to the list of builders.
+ * @param child the child builder to add.
+ * @return this for chaining.
+ */
+ public AbstractBuilder add(IHeaderMatcher.Builder child) {
+ children.add(child);
+ return this;
+ }
+
+ /**
+ * Adds a collection of builders to the list of child builders.
+ * @param children the children to add.
+ * @return this for chaining.
+ */
+ public AbstractBuilder add(Collection children) {
+ this.children.addAll(children);
+ return this;
+ }
+
+ /**
+ * @return the list of child builders for this builder.
+ */
+ public List getChildren() {
+ return children.stream().map(IHeaderMatcher.Builder::build).collect(Collectors.toList());
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder(this.getClass().getSimpleName()).append( ":");
+ children.stream().map(Object::toString).forEach( x -> sb.append("\n").append(x));
+ return sb.toString();
+ }
+
+}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/CopyrightBuilder.java b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/CopyrightBuilder.java
new file mode 100644
index 000000000..f38220ade
--- /dev/null
+++ b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/CopyrightBuilder.java
@@ -0,0 +1,71 @@
+/*
+ * 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.configuration.builders;
+
+import org.apache.rat.analysis.IHeaderMatcher;
+import org.apache.rat.analysis.matchers.CopyrightMatcher;
+
+/**
+ * A copyright builder.
+ */
+public class CopyrightBuilder extends AbstractBuilder {
+ private String start;
+ private String end;
+ private String owner;
+
+ /**
+ * Sets the start date.
+ * @param start the start date for the copyright
+ * @return this for chaining
+ */
+ public CopyrightBuilder setStart(String start) {
+ this.start = start;
+ return this;
+ }
+
+ /**
+ * Sets the end date.
+ * @param end the End data for the copyright.
+ * @return this for chaining.
+ */
+ public CopyrightBuilder setEnd(String end) {
+ this.end = end;
+ return this;
+ }
+
+ /**
+ * Sets the owner.
+ * @param owner the owner for the copyright
+ * @return this for chaining.
+ */
+ public CopyrightBuilder setOwner(String owner) {
+ this.owner = owner;
+ return this;
+ }
+
+ @Override
+ public IHeaderMatcher build() {
+ return new CopyrightMatcher(getId(), start, end, owner);
+ }
+
+ @Override
+ public String toString() {
+ return String.format("Copyright Builder: s:%s e:%s o:%s", start, end, owner);
+ }
+}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/MatcherRefBuilder.java b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/MatcherRefBuilder.java
new file mode 100644
index 000000000..17918096a
--- /dev/null
+++ b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/MatcherRefBuilder.java
@@ -0,0 +1,125 @@
+/*
+ * 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.configuration.builders;
+
+import java.util.Map;
+
+import org.apache.rat.analysis.IHeaderMatcher;
+
+/**
+ * A reference matching Matcher builder.
+ *
+ * This class stores a matcher id as a reference to the matcher. It also has a map of matcher ids to the matcher
+ * instances. When build is called the matcher reference is looked up in the map. If it is found then it is returned
+ * value from the {@code build()} call. If the reference is not located then a IHeaderMatcherProxy is returned.
+ * the IHeaderMatcherProxy is resolved in a later configuration construction phase.
+ */
+public class MatcherRefBuilder extends AbstractBuilder {
+ private String referenceId;
+ private Map matchers;
+
+ /**
+ * Constructs the MatcherReferenceBuilder using the provided reference id.
+ * @param refId the reverence to the matcher id.
+ * @return this builder for chaining.
+ */
+ public MatcherRefBuilder setRefId(String refId) {
+ this.referenceId = refId;
+ return this;
+ }
+
+ /**
+ * Set the Map of matcher ids to matcher instances.
+ * @param matchers the Map of ids to instances.
+ * @return this builder for chaining.
+ */
+ public MatcherRefBuilder setMatchers(Map matchers) {
+ this.matchers = matchers;
+ return this;
+ }
+
+ @Override
+ public IHeaderMatcher build() {
+ IHeaderMatcher result = matchers.get(referenceId);
+ return result != null ? result : new IHeaderMatcherProxy(referenceId, matchers);
+ }
+
+ @Override
+ public String toString() {
+ return "MathcerRefBuilder: "+referenceId;
+ }
+
+ /**
+ * A class that is a proxy to the actual matcher. It retrieves the actual matcher from the map of
+ * matcher ids to matcher instances one the first use of the matcher. This allows earlier read matchers
+ * to reference later constructed matchers as long as all the matchers are constructed before the earlier one is
+ * used.
+ */
+ private class IHeaderMatcherProxy implements IHeaderMatcher {
+ private final String proxyId;
+ private IHeaderMatcher wrapped;
+ private Map matchers;
+
+ private IHeaderMatcherProxy(String proxyId, Map matchers) {
+ this.proxyId = proxyId;
+ this.matchers = matchers;
+ }
+
+ private void checkProxy() {
+ if (wrapped == null) {
+ wrapped = matchers.get(proxyId);
+ if (wrapped == null) {
+ throw new IllegalStateException(String.format("%s is not a valid matcher id", proxyId));
+ }
+ matchers = null;
+ }
+ }
+
+ @Override
+ public String getId() {
+ checkProxy();
+ return wrapped.getId();
+ }
+
+ @Override
+ public void reset() {
+ checkProxy();
+ wrapped.reset();
+ }
+
+ @Override
+ public State matches(String line) {
+ checkProxy();
+ return wrapped.matches(line);
+ }
+
+ @Override
+ public State currentState() {
+ checkProxy();
+ return wrapped.currentState();
+ }
+
+ @Override
+ public State finalizeState() {
+ checkProxy();
+ return wrapped.finalizeState();
+ }
+ }
+
+}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/license/GPL1License.java b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/NotBuilder.java
similarity index 60%
rename from apache-rat-core/src/main/java/org/apache/rat/analysis/license/GPL1License.java
rename to apache-rat-core/src/main/java/org/apache/rat/configuration/builders/NotBuilder.java
index 5c9409292..61e264b8b 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/analysis/license/GPL1License.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/NotBuilder.java
@@ -16,22 +16,27 @@
* specific language governing permissions and limitations *
* under the License. *
*/
-package org.apache.rat.analysis.license;
+package org.apache.rat.configuration.builders;
-import org.apache.rat.api.MetaData;
+import org.apache.rat.ConfigurationException;
+import org.apache.rat.analysis.IHeaderMatcher;
+import org.apache.rat.analysis.matchers.NotMatcher;
/**
- * License matches GPL1 or later.
+ * A builder for the NotMatcher.
*/
-public class GPL1License extends FullTextMatchingLicense {
- public static final String FIRST_LICENSE_LINE = "This program is free software; you can redistribute it and/or modify\n" +
- " it under the terms of the GNU General Public License as published by\n" +
- " the Free Software Foundation; either version 1, or (at your option)\n" +
- " any later version.";
-
- public GPL1License() {
- super(MetaData.RAT_LICENSE_FAMILY_CATEGORY_DATUM_GPL1,
- MetaData.RAT_LICENSE_FAMILY_NAME_DATUM_GPL_VERSION_1,
- "", FIRST_LICENSE_LINE);
+public class NotBuilder extends ChildContainerBuilder {
+
+ @Override
+ public IHeaderMatcher build() {
+ if (children.size() != 1) {
+ throw new ConfigurationException("'not' type matcher requires one and only one enclosed matcher");
+ }
+ return new NotMatcher(getId(), children.get(0).build());
+ }
+
+ @Override
+ public String toString() {
+ return String.format( "NotBuilder: %s", !children.isEmpty() ? children.get(0) : null );
}
-}
\ No newline at end of file
+}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/RegexBuilder.java b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/RegexBuilder.java
new file mode 100644
index 000000000..a132ba6c6
--- /dev/null
+++ b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/RegexBuilder.java
@@ -0,0 +1,60 @@
+/*
+ * 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.configuration.builders;
+
+import java.util.regex.Pattern;
+
+import org.apache.rat.ConfigurationException;
+import org.apache.rat.analysis.IHeaderMatcher;
+import org.apache.rat.analysis.matchers.SimpleRegexMatcher;
+
+/**
+ * A builder for the regex matcher.
+ */
+public class RegexBuilder extends AbstractBuilder {
+
+ private Pattern pattern;
+
+ /**
+ * Sets the regex expression.
+ * This method compiles the string into a pattern and may throw any exception thrown by the
+ * {@code Pattern.compile(String)} method.
+ * @param exp the expression as a string.
+ * @return this builder for chaining.
+ * @see Pattern#compile(String)
+ */
+ public RegexBuilder setExpr(String exp) {
+ this.pattern = exp == null ? null : Pattern.compile(exp);
+ return this;
+ }
+
+ @Override
+ public IHeaderMatcher build() {
+ if (null == pattern) {
+ throw new ConfigurationException("'regex' type matcher requires an expression");
+ }
+ return new SimpleRegexMatcher(pattern);
+ }
+
+ @Override
+ public String toString() {
+ return String.format("RegexBuilder: %s", pattern==null? null: pattern.pattern());
+ }
+
+}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/license/GPL2License.java b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/SpdxBuilder.java
similarity index 59%
rename from apache-rat-core/src/main/java/org/apache/rat/analysis/license/GPL2License.java
rename to apache-rat-core/src/main/java/org/apache/rat/configuration/builders/SpdxBuilder.java
index ed9259235..42530147d 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/analysis/license/GPL2License.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/SpdxBuilder.java
@@ -16,22 +16,38 @@
* specific language governing permissions and limitations *
* under the License. *
*/
-package org.apache.rat.analysis.license;
+package org.apache.rat.configuration.builders;
-import org.apache.rat.api.MetaData;
+import java.util.Objects;
+
+import org.apache.rat.analysis.IHeaderMatcher;
+import org.apache.rat.analysis.matchers.SPDXMatcherFactory;
/**
- * License matches GPL2 or later.
+ * A build for SPDX matchers.
*/
-public class GPL2License extends FullTextMatchingLicense {
- public static final String FIRST_LICENSE_LINE = "This program is free software; you can redistribute it and/or\n" +
- " modify it under the terms of the GNU General Public License\n" +
- " as published by the Free Software Foundation; either version 2\n" +
- " of the License, or (at your option) any later version.";
+public class SpdxBuilder extends AbstractBuilder {
+
+ private String name;
- public GPL2License() {
- super(MetaData.RAT_LICENSE_FAMILY_CATEGORY_DATUM_GPL2,
- MetaData.RAT_LICENSE_FAMILY_NAME_DATUM_GPL_VERSION_2,
- "", FIRST_LICENSE_LINE);
+ /**
+ * sets the name for the SPDX matcher
+ * @param name
+ * @return
+ */
+ public SpdxBuilder setName(String name) {
+ Objects.requireNonNull(name, "name must not be null");
+ this.name = name;
+ return this;
+ }
+
+ @Override
+ public IHeaderMatcher build() {
+ return SPDXMatcherFactory.INSTANCE.create(name);
+ }
+
+ @Override
+ public String toString() {
+ return "SpdxBuilder: "+name;
}
}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/TextBuilder.java b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/TextBuilder.java
new file mode 100644
index 000000000..456afe03b
--- /dev/null
+++ b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/TextBuilder.java
@@ -0,0 +1,62 @@
+/*
+ * 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.configuration.builders;
+
+import java.util.Objects;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.rat.ConfigurationException;
+import org.apache.rat.analysis.IHeaderMatcher;
+import org.apache.rat.analysis.matchers.FullTextMatcher;
+import org.apache.rat.analysis.matchers.SimpleTextMatcher;
+
+/**
+ * Builds text based matcher based on the complexity of the text to match.
+ */
+public class TextBuilder extends AbstractBuilder implements TextCaptureBuilder {
+
+ private String text;
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public TextBuilder setText(String text) {
+ Objects.requireNonNull(text, "text may not be null");
+ this.text = text;
+ return this;
+ }
+
+ @Override
+ public IHeaderMatcher build() {
+ if (StringUtils.isBlank(text)) {
+ throw new ConfigurationException("text value is required");
+ }
+ boolean complex = text.contains(" ") | text.contains("\\t") | text.contains("\\n") | text.contains("\\r")
+ | text.contains("\\f") | text.contains("\\v");
+
+ return complex ? new FullTextMatcher(getId(), text) : new SimpleTextMatcher(getId(), text);
+ }
+
+ @Override
+ public String toString() {
+ if (text.length() > 20) {
+ return "TextBuilder: " + text.substring(0, 20) + "...";
+ }
+ return "TextBuilder: " + text;
+ }
+}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/TextCaptureBuilder.java b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/TextCaptureBuilder.java
new file mode 100644
index 000000000..8ad765974
--- /dev/null
+++ b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/TextCaptureBuilder.java
@@ -0,0 +1,26 @@
+/*
+ * 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.configuration.builders;
+
+/**
+ * A marker interface for builders that accept text plain text to match.
+ */
+public interface TextCaptureBuilder {
+ T setText(String text);
+}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/document/ToNameTransformer.java b/apache-rat-core/src/main/java/org/apache/rat/document/ToNameTransformer.java
index 0f8809599..860e8a914 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/document/ToNameTransformer.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/document/ToNameTransformer.java
@@ -21,11 +21,11 @@
import org.apache.commons.collections4.Transformer;
import org.apache.rat.api.Document;
-public class ToNameTransformer implements Transformer {
+public class ToNameTransformer implements Transformer {
- private static final Transformer TO_NAME_TRANSFORMER = new ToNameTransformer();
+ private static final Transformer TO_NAME_TRANSFORMER = new ToNameTransformer();
- public static final Transformer toNameTransformer() {
+ public static Transformer toNameTransformer() {
return TO_NAME_TRANSFORMER;
}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/document/impl/DocumentImplUtils.java b/apache-rat-core/src/main/java/org/apache/rat/document/impl/DocumentImplUtils.java
index f72160f75..5522e6705 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/document/impl/DocumentImplUtils.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/document/impl/DocumentImplUtils.java
@@ -22,7 +22,6 @@
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.util.zip.ZipException;
import java.util.zip.ZipInputStream;
import org.apache.commons.io.IOUtils;
diff --git a/apache-rat-core/src/main/java/org/apache/rat/document/impl/guesser/ArchiveGuesser.java b/apache-rat-core/src/main/java/org/apache/rat/document/impl/guesser/ArchiveGuesser.java
index d3d44e676..f213d6090 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/document/impl/guesser/ArchiveGuesser.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/document/impl/guesser/ArchiveGuesser.java
@@ -44,7 +44,7 @@ public class ArchiveGuesser {
* @param document the current document.
* @return whether the given document is an archive.
*/
- public static final boolean isArchive(final Document document) {
+ public static boolean isArchive(final Document document) {
return isArchive(document.getName());
}
@@ -52,7 +52,7 @@ public static final boolean isArchive(final Document document) {
* @return Is a file by that name an archive?
* @param name file name to check against.
*/
- public static final boolean isArchive(final String name) {
+ public static boolean isArchive(final String name) {
if (name == null) {return false;}
String nameToLower = name.toLowerCase(Locale.US);
for (int i = 0; i < ArchiveGuesser.ARCHIVE_EXTENSIONS.length; i++) {
diff --git a/apache-rat-core/src/main/java/org/apache/rat/document/impl/guesser/BinaryGuesser.java b/apache-rat-core/src/main/java/org/apache/rat/document/impl/guesser/BinaryGuesser.java
index 312140e6b..1a900f65b 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/document/impl/guesser/BinaryGuesser.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/document/impl/guesser/BinaryGuesser.java
@@ -26,11 +26,7 @@
import java.io.Reader;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
-import java.nio.charset.Charset;
-import java.nio.charset.CharsetDecoder;
-import java.nio.charset.CoderResult;
-import java.nio.charset.CodingErrorAction;
-import java.nio.charset.UnsupportedCharsetException;
+import java.nio.charset.*;
import java.util.Locale;
/**
@@ -41,10 +37,10 @@ public class BinaryGuesser {
private static final String DOT = ".";
static final String FILE_ENCODING = "file.encoding";
- private static Charset CHARSET_FROM_FILE_ENCODING_OR_UTF8 = getFileEncodingOrUTF8AsFallback();
+ private static final Charset CHARSET_FROM_FILE_ENCODING_OR_UTF8 = getFileEncodingOrUTF8AsFallback();
private static boolean isBinaryDocument(Document document) {
- boolean result = false;
+ boolean result;
InputStream stream = null;
try {
stream = document.inputStream();
@@ -141,7 +137,7 @@ static Charset getFileEncodingOrUTF8AsFallback() {
try {
return Charset.forName(System.getProperty(FILE_ENCODING));
} catch (UnsupportedCharsetException e) {
- return Charset.forName("UTF-8");
+ return StandardCharsets.UTF_8;
}
}
@@ -149,7 +145,7 @@ static Charset getFileEncodingOrUTF8AsFallback() {
* @param name current file name.
* @return whether given name is binary.
*/
- public static final boolean isBinaryData(final String name) {
+ public static boolean isBinaryData(final String name) {
return extensionMatches(name, DATA_EXTENSIONS);
}
@@ -157,7 +153,7 @@ public static final boolean isBinaryData(final String name) {
* @param name current file name.
* @return Is a file by that name a known non-binary file?
*/
- public static final boolean isNonBinary(final String name) {
+ public static boolean isNonBinary(final String name) {
return name != null && extensionMatches(name.toUpperCase(Locale.US), BinaryGuesser.NON_BINARY_EXTENSIONS);
}
@@ -165,7 +161,7 @@ public static final boolean isNonBinary(final String name) {
* @param name current file name.
* @return Is a file by that name an executable/binary file?
*/
- public static final boolean isExecutable(final String name) {
+ public static boolean isExecutable(final String name) {
return name.equals(BinaryGuesser.JAVA) || extensionMatches(name, EXE_EXTENSIONS)
|| containsExtension(name, EXE_EXTENSIONS);
}
@@ -194,15 +190,15 @@ public static boolean isBytecode(final String name) {
return BinaryGuesser.extensionMatches(name, BYTECODE_EXTENSIONS);
}
- public static final boolean isImage(final String name) {
+ public static boolean isImage(final String name) {
return BinaryGuesser.extensionMatches(name, IMAGE_EXTENSIONS);
}
- public static final boolean isKeystore(final String name) {
+ public static boolean isKeystore(final String name) {
return BinaryGuesser.extensionMatches(name, KEYSTORE_EXTENSIONS);
}
- public static final boolean isAudio(final String name) {
+ public static boolean isAudio(final String name) {
return BinaryGuesser.extensionMatches( name, AUDIO_EXTENSIONS );
}
@@ -210,7 +206,7 @@ public static final boolean isAudio(final String name) {
* @param name file name.
* @return Is a file by that name a known binary file?
*/
- public static final boolean isBinary(final String name) {
+ public static boolean isBinary(final String name) {
if (name == null) {
return false;
}
@@ -266,7 +262,7 @@ public static final boolean isBinary(final String name) {
};
/**
- * Based on https://www.apache.org/dev/svn-eol-style.txt
+ * Based on https://www.apache.org/dev/svn-eol-style.txt
*/
private static final String[] NON_BINARY_EXTENSIONS = {
"AART",
@@ -363,7 +359,7 @@ public static final boolean isBinary(final String name) {
public static final int NON_ASCII_THRESHOLD = 256;
public static final int ASCII_CHAR_THRESHOLD = 8;
- public static final boolean isBinary(final Document document) {
+ public static boolean isBinary(final Document document) {
// TODO: reimplement the binary test algorithm?
// TODO: more efficient to move into standard analysis
// TODO: then use binary as default
diff --git a/apache-rat-core/src/main/java/org/apache/rat/document/impl/guesser/GuessUtils.java b/apache-rat-core/src/main/java/org/apache/rat/document/impl/guesser/GuessUtils.java
index d6b7f4d5e..ec3368549 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/document/impl/guesser/GuessUtils.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/document/impl/guesser/GuessUtils.java
@@ -31,7 +31,7 @@ public class GuessUtils {
* @param name not null
* @return not null
*/
- public static final String normalise(final String name) {
+ public static String normalise(final String name) {
String result = name.toUpperCase(Locale.US);
final int lastSeparatorIndex = StringUtils.lastIndexOfAny(result, SEPARATORS);
final int length = result.length();
diff --git a/apache-rat-core/src/main/java/org/apache/rat/document/impl/guesser/NoteGuesser.java b/apache-rat-core/src/main/java/org/apache/rat/document/impl/guesser/NoteGuesser.java
index d0b9901f0..cbf636fd8 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/document/impl/guesser/NoteGuesser.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/document/impl/guesser/NoteGuesser.java
@@ -58,7 +58,7 @@ public class NoteGuesser {
* @return Is a file by that name a note file?
* @param name file name.
*/
- public static final boolean isNote(final String name) {
+ public static boolean isNote(final String name) {
if (name == null) {return false;}
List l = Arrays.asList(NoteGuesser.NOTE_FILE_NAMES);
@@ -77,7 +77,7 @@ public static final boolean isNote(final String name) {
return false;
}
- public static final boolean isNote(final Document document) {
+ public static boolean isNote(final Document document) {
return isNote(document.getName());
}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/license/AcademicFree21LicenseFamily.java b/apache-rat-core/src/main/java/org/apache/rat/license/AcademicFree21LicenseFamily.java
deleted file mode 100644
index bc870c306..000000000
--- a/apache-rat-core/src/main/java/org/apache/rat/license/AcademicFree21LicenseFamily.java
+++ /dev/null
@@ -1,27 +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.license;
-
-import org.apache.rat.api.MetaData;
-
-public class AcademicFree21LicenseFamily extends SimpleLicenseFamily {
- public AcademicFree21LicenseFamily() {
- super(MetaData.RAT_LICENSE_FAMILY_NAME_VALUE_ACADEMIC_FREE_LICENSE_VERSION_2_1);
- }
-}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/license/Apache20LicenseFamily.java b/apache-rat-core/src/main/java/org/apache/rat/license/Apache20LicenseFamily.java
deleted file mode 100644
index 17abbcdd0..000000000
--- a/apache-rat-core/src/main/java/org/apache/rat/license/Apache20LicenseFamily.java
+++ /dev/null
@@ -1,27 +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.license;
-
-import org.apache.rat.api.MetaData;
-
-public final class Apache20LicenseFamily extends SimpleLicenseFamily {
- public Apache20LicenseFamily() {
- super(MetaData.RAT_LICENSE_FAMILY_NAME_VALUE_APACHE_LICENSE_VERSION_2_0);
- }
-}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/license/GPL1LicenseFamily.java b/apache-rat-core/src/main/java/org/apache/rat/license/GPL1LicenseFamily.java
deleted file mode 100644
index bdfd86e7b..000000000
--- a/apache-rat-core/src/main/java/org/apache/rat/license/GPL1LicenseFamily.java
+++ /dev/null
@@ -1,31 +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.license;
-
-import org.apache.rat.api.MetaData;
-
-/**
- * Base implementation for GPLv1 or later.
- */
-public class GPL1LicenseFamily extends SimpleLicenseFamily {
- public GPL1LicenseFamily() {
- super(MetaData.RAT_LICENSE_FAMILY_NAME_VALUE_GPL_VERSION_1);
- }
-
-}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/license/GPL3LicenseFamily.java b/apache-rat-core/src/main/java/org/apache/rat/license/GPL3LicenseFamily.java
deleted file mode 100644
index 9d91466c1..000000000
--- a/apache-rat-core/src/main/java/org/apache/rat/license/GPL3LicenseFamily.java
+++ /dev/null
@@ -1,31 +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.license;
-
-import org.apache.rat.api.MetaData;
-
-/**
- * Base implementation for GPLv3 or later.
- */
-public class GPL3LicenseFamily extends SimpleLicenseFamily {
- public GPL3LicenseFamily() {
- super(MetaData.RAT_LICENSE_FAMILY_NAME_VALUE_GPL_VERSION_3);
- }
-
-}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/license/ILicense.java b/apache-rat-core/src/main/java/org/apache/rat/license/ILicense.java
new file mode 100644
index 000000000..4d30ff2d7
--- /dev/null
+++ b/apache-rat-core/src/main/java/org/apache/rat/license/ILicense.java
@@ -0,0 +1,171 @@
+/*
+ * 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.license;
+
+import java.util.Comparator;
+import java.util.Objects;
+import java.util.SortedSet;
+
+import org.apache.rat.analysis.IHeaderMatcher;
+
+/**
+ * The definition of a License.
+ */
+public interface ILicense extends IHeaderMatcher, Comparable {
+ /**
+ * @return the ILicenseFamily implementation for this license.
+ */
+ ILicenseFamily getLicenseFamily();
+
+ /**
+ * @return the notes associated with this license. May be null or empty.
+ */
+ String getNotes();
+
+ /**
+ * @return the id of a license that this license is derived from. May be null.
+ */
+ String derivedFrom();
+
+ /**
+ * Returns the name of this license. If no name was specified then the name of the family is returned.
+ * @return the name of this license.
+ */
+ String getName();
+
+ /**
+ * @return An ILicense.Builder instance.
+ */
+ static ILicense.Builder builder() {
+ return new Builder();
+ }
+
+ /**
+ * @return The comparator for used to sort Licenses.
+ */
+ static Comparator getComparator() {
+ return Comparator.comparing(IHeaderMatcher::getId);
+ }
+
+ /**
+ * A builder for ILicense instances.
+ */
+ class Builder {
+
+ private IHeaderMatcher.Builder matcher;
+
+ private String notes;
+
+ private String derivedFrom;
+
+ private String name;
+
+ private String id;
+
+ private final ILicenseFamily.Builder licenseFamily = ILicenseFamily.builder();
+
+ /**
+ * Sets the matcher from a builder.
+ * @param matcher the builder for the matcher for the license.
+ * @return this builder for chaining.
+ */
+ public Builder setMatcher(IHeaderMatcher.Builder matcher) {
+ this.matcher = matcher;
+ return this;
+ }
+
+ /**
+ * Sets the matcher.
+ * @param matcher the matcher for the license.
+ * @return this builder for chaining.
+ */
+ public Builder setMatcher(IHeaderMatcher matcher) {
+ this.matcher = ()->matcher;
+ return this;
+ }
+
+ /**
+ * Sets the notes for the license.
+ * If called multiple times the notes are concatenated to create a single note.
+ * @param notes the notes for the license.
+ * @return this builder for chaining.
+ */
+ public Builder setNotes(String notes) {
+ this.notes = notes;
+ return this;
+ }
+
+ /**
+ * Sets the ID of the license.
+ * If the ID is not set then the ID of the license family is used.
+ * @param id the ID for the license
+ * @return this builder for chaining.
+ */
+ public Builder setId(String id) {
+ this.id = id;
+ return this;
+ }
+
+ /**
+ * Sets the derived from fields in the license.
+ * @param derivedFrom the family category of the license this license was derived from.
+ * @return this builder for chaining.
+ */
+ public Builder setDerivedFrom(String derivedFrom) {
+ this.derivedFrom = derivedFrom;
+ return this;
+ }
+
+ /**
+ * Set the family category for this license.
+ * The category must be unique across all licenses and must be 5 characters. If more than
+ * 5 characters are provided then only the first 5 are taken. If fewer than 5 characters are provided
+ * the category is padded with spaces.
+ * @param licenseFamilyCategory the family category for the license.
+ * @return this builder for chaining.
+ */
+ public Builder setLicenseFamilyCategory(String licenseFamilyCategory) {
+ this.licenseFamily.setLicenseFamilyCategory(licenseFamilyCategory);
+ this.licenseFamily.setLicenseFamilyName("License Family for searching");
+ return this;
+ }
+
+ /**
+ * Sets the name of the license.
+ * If the name is not set then the name of the license family is used.
+ * @param name the name for the license
+ * @return this builder for chaining.
+ */
+ public Builder setName(String name) {
+ this.name = name;
+ return this;
+ }
+
+ /**
+ * @param licenseFamilies the set of defined license families.
+ * @return A new License implementation.
+ */
+ public ILicense build(SortedSet licenseFamilies) {
+ Objects.requireNonNull(matcher, "Matcher must not be null");
+ ILicenseFamily family = LicenseFamilySetFactory.search(licenseFamily.build(), licenseFamilies);
+ Objects.requireNonNull(family, "License family "+licenseFamily.getCategory()+" not found.");
+ return new SimpleLicense(family, matcher.build(), derivedFrom, notes, name, id);
+ }
+ }
+}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/license/ILicenseFamily.java b/apache-rat-core/src/main/java/org/apache/rat/license/ILicenseFamily.java
index 97ef9a954..501a59e89 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/license/ILicenseFamily.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/license/ILicenseFamily.java
@@ -15,10 +15,73 @@
* KIND, either express or implied. See the License for the *
* specific language governing permissions and limitations *
* under the License. *
- */
+ */
package org.apache.rat.license;
-
-public interface ILicenseFamily {
+/**
+ * The definition of the license family.
+ */
+public interface ILicenseFamily extends Comparable {
+ /**
+ * @return the license family name.
+ */
String getFamilyName();
+
+ /**
+ * @return the license family category.
+ */
+ String getFamilyCategory();
+
+ /**
+ * @return A builder for an ILicenseFamily.
+ */
+ static ILicenseFamily.Builder builder() {
+ return new ILicenseFamilyBuilder();
+ }
+
+ /**
+ * Convert a potential category string into a category string of exactly 5 characters either by truncating
+ * the string or appending spaces as necessary.
+ * @param cat the string to convert.
+ * @return a string of exactly 5 characters.
+ */
+ static String makeCategory(String cat) {
+ return cat == null ? " " : cat.concat(" ").substring(0, 5);
+ }
+
+ @Override
+ default int compareTo(ILicenseFamily other) {
+ return getFamilyCategory().compareTo(other.getFamilyCategory());
+ }
+
+ /**
+ * The definition of an ILicenseFamily builder.
+ */
+ interface Builder {
+ /**
+ * Sets the license family category. Will trim or extends the string with spaces to ensure that it is
+ * exactly 5 characters.
+ * @param licenseFamilyCategory the category string
+ * @return this builder for chaining.
+ */
+ Builder setLicenseFamilyCategory(String licenseFamilyCategory);
+
+ /**
+ * Sets the license family name.
+ * @param licenseFamilyName the name string
+ * @return this builder for chaining.
+ */
+ Builder setLicenseFamilyName(String licenseFamilyName);
+
+ /**
+ * Gets the category that this builder is building.
+ * @return the category that this builder is building.
+ */
+ String getCategory();
+
+ /**
+ * @return a new ILicenseFamily instance.
+ */
+ ILicenseFamily build();
+ }
}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/license/ILicenseFamilyBuilder.java b/apache-rat-core/src/main/java/org/apache/rat/license/ILicenseFamilyBuilder.java
new file mode 100644
index 000000000..84c27cc15
--- /dev/null
+++ b/apache-rat-core/src/main/java/org/apache/rat/license/ILicenseFamilyBuilder.java
@@ -0,0 +1,78 @@
+/*
+ * 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.license;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.rat.ConfigurationException;
+import org.apache.rat.license.ILicenseFamily.Builder;
+
+/**
+ * An instance of the ILicenseFamily Builder.
+ */
+public class ILicenseFamilyBuilder implements Builder {
+
+ private String licenseFamilyCategory;
+ private String licenseFamilyName;
+
+ @Override
+ public Builder setLicenseFamilyCategory(String licenseFamilyCategory) {
+ this.licenseFamilyCategory = licenseFamilyCategory;
+ return this;
+ }
+
+
+ @Override
+ public String getCategory() {
+ return licenseFamilyCategory;
+ }
+
+ @Override
+ public Builder setLicenseFamilyName(String licenseFamilyName) {
+ this.licenseFamilyName = licenseFamilyName;
+ return this;
+ }
+
+ @Override
+ public ILicenseFamily build() {
+ if (StringUtils.isBlank(licenseFamilyCategory)) {
+ throw new ConfigurationException("LicenseFamily Category must be specified");
+ }
+ if (StringUtils.isBlank(licenseFamilyName)) {
+ throw new ConfigurationException("LicenseFamily Name must be specified");
+ }
+ return new ILicenseFamily() {
+ private final String cat = ILicenseFamily.makeCategory(licenseFamilyCategory);
+ private final String name = licenseFamilyName;
+ @Override
+ public String toString() {
+ return String.format("%s %s", getFamilyCategory(), getFamilyName());
+ }
+
+ @Override
+ public final String getFamilyName() {
+ return name;
+ }
+
+ @Override
+ public String getFamilyCategory() {
+ return cat;
+ }
+ };
+ }
+}
\ No newline at end of file
diff --git a/apache-rat-core/src/main/java/org/apache/rat/license/LicenseFamilySetFactory.java b/apache-rat-core/src/main/java/org/apache/rat/license/LicenseFamilySetFactory.java
new file mode 100644
index 000000000..464987933
--- /dev/null
+++ b/apache-rat-core/src/main/java/org/apache/rat/license/LicenseFamilySetFactory.java
@@ -0,0 +1,121 @@
+/*
+ * 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.license;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import org.apache.rat.license.LicenseSetFactory.LicenseFilter;
+
+/**
+ * Class to take a set of ILicenses and collection of approved license categories and extract Subsets.
+ */
+public class LicenseFamilySetFactory {
+
+ private final SortedSet families;
+ private final Collection approvedLicenses;
+
+ /**
+ * Constructs a factory with the specified set of Licenses and the approved license collection.
+ * @param licenses the set of defined licenses.
+ * @param approvedLicenses the list of approved licenses.
+ */
+ public LicenseFamilySetFactory(SortedSet licenses, Collection approvedLicenses) {
+ this.families = licenses;
+ this.approvedLicenses = approvedLicenses;
+ }
+
+ /**
+ * Create an empty sorted Set with proper comparator.
+ * @return An empty sorted set of ILicenseFamily objects.
+ */
+ public static SortedSet emptyLicenseFamilySet() {
+ return new TreeSet<>();
+ }
+
+
+ /**
+ * Gets the License objects based on the filter.
+ * @param filter the types of LicenseFamily objects to return.
+ * @return a SortedSet of ILicense objects.
+ */
+ public SortedSet getFamilies(LicenseFilter filter) {
+ switch (filter) {
+ case all:
+ return Collections.unmodifiableSortedSet(families);
+ case approved:
+ SortedSet result = emptyLicenseFamilySet();
+ families.stream().filter(x -> approvedLicenses.contains(x.getFamilyCategory()))
+ .forEach(result::add);
+ return result;
+ case none:
+ default:
+ return Collections.emptySortedSet();
+ }
+ }
+
+
+ /**
+ * Gets the categories of LicenseFamily objects based on the filter.
+ * @param filter the types of LicenseFamily objects to return.
+ * @return a SortedSet of ILicenseFamily categories.
+ */
+ public SortedSet getFamilyIds(LicenseFilter filter) {
+ SortedSet result = new TreeSet<>();
+ switch (filter) {
+ case all:
+ families.stream().map(ILicenseFamily::getFamilyCategory)
+ .forEach(result::add);
+ break;
+ case approved:
+ result.addAll(approvedLicenses);
+ break;
+ case none:
+ default:
+ // do nothing
+ }
+ return result;
+ }
+
+
+ /**
+ * Search a SortedSet of ILicenseFamily instances looking for a matching instance.
+ * @param target The instance to search for.
+ * @param licenseFamilies the license families to search
+ * @return the matching instance of the target given.
+ */
+ public static ILicenseFamily search(String target, SortedSet licenseFamilies) {
+ ILicenseFamily family = ILicenseFamily.builder().setLicenseFamilyCategory(target).setLicenseFamilyName("Searching family")
+ .build();
+ return search( family, licenseFamilies);
+ }
+
+ /**
+ * Search a SortedSet of ILicenseFamily instances looking for a matching instance.
+ * @param target The instance to search for.
+ * @param licenseFamilies the license families to search
+ * @return the matching instance of the target given.
+ */
+ public static ILicenseFamily search(ILicenseFamily target, SortedSet licenseFamilies) {
+ SortedSet part = licenseFamilies.tailSet(target);
+ return (!part.isEmpty() && part.first().compareTo(target) == 0) ? part.first() : null;
+ }
+
+}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/license/LicenseSetFactory.java b/apache-rat-core/src/main/java/org/apache/rat/license/LicenseSetFactory.java
new file mode 100644
index 000000000..40bbe20ee
--- /dev/null
+++ b/apache-rat-core/src/main/java/org/apache/rat/license/LicenseSetFactory.java
@@ -0,0 +1,224 @@
+/*
+ * 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.license;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+/**
+ * Class to take a set of ILicenses and collection of approved license categories and extract Subsets.
+ */
+public class LicenseSetFactory {
+
+ /**
+ * An enum that defines the types of Licenses to extract.
+ */
+ public enum LicenseFilter {
+ /** All defined licenses are returned */
+ all,
+ /** Only approved licenses are returned */
+ approved,
+ /** No licenses are returned */
+ none;
+
+ /**
+ * Converts from a String to an enum value.
+ * @param s String representation.
+ * @return given licenseFilter for the given String representation.
+ */
+ static public LicenseFilter fromText(String s) {
+ return LicenseFilter.valueOf(s.toLowerCase());
+ }
+ }
+
+ private final SortedSet licenses;
+ private final Collection approvedLicenses;
+
+ /**
+ * Constructs a factory with the specified set of Licenses and the approved license collection.
+ * @param licenses the set of defined licenses.
+ * @param approvedLicenses the list of approved licenses.
+ */
+ public LicenseSetFactory(SortedSet licenses, Collection approvedLicenses) {
+ this.licenses = licenses;
+ this.approvedLicenses = approvedLicenses;
+ }
+
+ /**
+ * Create an empty sorted Set with proper comparator.
+ * @return An empty sorted set of ILicense objects.
+ */
+ public static SortedSet emptyLicenseSet() {
+ return new TreeSet<>(ILicense.getComparator());
+ }
+
+ /**
+ * Create a sorted set of licenses families from the collection.
+ * @param licenses the collection of all licenses.
+ * @return a SortedSet of license families from the collection.
+ */
+ private static SortedSet extractFamily(Collection licenses) {
+ SortedSet result = new TreeSet<>();
+ licenses.stream().map( ILicense::getLicenseFamily ).forEach(result::add);
+ return result;
+ }
+
+ /**
+ * Gets the License objects based on the filter.
+ * @param filter the types of LicenseFamily objects to return.
+ * @return a SortedSet of ILicense objects.
+ */
+ public SortedSet getLicenses(LicenseFilter filter) {
+ switch (filter) {
+ case all:
+ return Collections.unmodifiableSortedSet(licenses);
+ case approved:
+ SortedSet result = LicenseSetFactory.emptyLicenseSet();
+ licenses.stream().filter(x -> approvedLicenses.contains(x.getLicenseFamily().getFamilyCategory()))
+ .forEach(result::add);
+ return result;
+ case none:
+ default:
+ return Collections.emptySortedSet();
+ }
+ }
+
+ /**
+ * Gets the LicenseFamily objects based on the filter.
+ * @param filter the types of LicenseFamily objects to return.
+ * @return a SortedSet of ILicenseFamily objects.
+ */
+ public SortedSet getLicenseFamilies(LicenseFilter filter) {
+ switch (filter) {
+ case all:
+ return extractFamily(licenses);
+ case approved:
+ SortedSet result = LicenseFamilySetFactory.emptyLicenseFamilySet();
+ licenses.stream().map(ILicense::getLicenseFamily)
+ .filter(x -> approvedLicenses.contains(x.getFamilyCategory()))
+ .forEach(result::add);
+ return result;
+ case none:
+ default:
+ return Collections.emptySortedSet();
+ }
+ }
+
+ /**
+ * Gets the categories of LicenseFamily objects based on the filter.
+ * @param filter the types of LicenseFamily objects to return.
+ * @return a SortedSet of ILicenseFamily categories.
+ */
+ public SortedSet getLicenseFamilyIds(LicenseFilter filter) {
+ SortedSet result = new TreeSet<>();
+ switch (filter) {
+ case all:
+ licenses.stream().map(x -> x.getLicenseFamily().getFamilyCategory())
+ .forEach(result::add);
+ break;
+ case approved:
+ result.addAll(approvedLicenses);
+ break;
+ case none:
+ default:
+ // do nothing
+ }
+ return result;
+ }
+
+ /**
+ * Search a SortedSet of licenses for the matching license id.
+ *
+ * @param licenseId the id to search for.
+ * @param licenses the SortedSet of licenses to search.
+ * @return the matching license or {@code null} if not found.
+ */
+ public static ILicense search(String licenseId, SortedSet licenses) {
+ ILicenseFamily searchFamily = ILicenseFamily.builder().setLicenseFamilyCategory(licenseId)
+ .setLicenseFamilyName("searching proxy").build();
+ ILicense target = new ILicense() {
+
+ @Override
+ public String getId() {
+ return licenseId;
+ }
+
+ @Override
+ public void reset() {
+ // do nothing
+ }
+
+ @Override
+ public State matches(String line) {
+ return State.f;
+ }
+
+ @Override
+ public int compareTo(ILicense arg0) {
+ return searchFamily.compareTo(arg0.getLicenseFamily());
+ }
+
+ @Override
+ public ILicenseFamily getLicenseFamily() {
+ return searchFamily;
+ }
+
+ @Override
+ public String getNotes() {
+ return null;
+ }
+
+ @Override
+ public String derivedFrom() {
+ return null;
+ }
+
+ @Override
+ public String getName() {
+ return searchFamily.getFamilyName();
+ }
+
+ @Override
+ public State finalizeState() {
+ return State.f;
+ }
+
+ @Override
+ public State currentState() {
+ return State.f;
+ }
+
+ };
+ return search(target, licenses);
+ }
+
+ /**
+ * Search a SortedSet of licenses for the matching license.
+ *
+ * @param target the license to search for.
+ * @param licenses the SortedSet of licenses to search.
+ * @return the matching license or {@code null} if not found.
+ */
+ public static ILicense search(ILicense target, SortedSet licenses) {
+ SortedSet part = licenses.tailSet(target);
+ return (!part.isEmpty() && part.first().compareTo(target) == 0) ? part.first() : null;
+ }
+
+}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/license/MITLicenseFamily.java b/apache-rat-core/src/main/java/org/apache/rat/license/MITLicenseFamily.java
deleted file mode 100644
index c6453d01e..000000000
--- a/apache-rat-core/src/main/java/org/apache/rat/license/MITLicenseFamily.java
+++ /dev/null
@@ -1,31 +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.license;
-
-import org.apache.rat.api.MetaData;
-
-/**
- * Base implementation for MIT licenses.
- */
-public class MITLicenseFamily extends SimpleLicenseFamily {
- public MITLicenseFamily() {
- super(MetaData.RAT_LICENSE_FAMILY_NAME_VALUE_MIT);
- }
-
-}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/license/ModifiedBSDLicenseFamily.java b/apache-rat-core/src/main/java/org/apache/rat/license/ModifiedBSDLicenseFamily.java
deleted file mode 100644
index d94de9719..000000000
--- a/apache-rat-core/src/main/java/org/apache/rat/license/ModifiedBSDLicenseFamily.java
+++ /dev/null
@@ -1,27 +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.license;
-
-import org.apache.rat.api.MetaData;
-
-public class ModifiedBSDLicenseFamily extends SimpleLicenseFamily {
- public ModifiedBSDLicenseFamily() {
- super(MetaData.RAT_LICENSE_FAMILY_NAME_VALUE_MODIFIED_BSD_LICENSE);
- }
-}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/license/SimpleLicense.java b/apache-rat-core/src/main/java/org/apache/rat/license/SimpleLicense.java
new file mode 100644
index 000000000..18e4f7609
--- /dev/null
+++ b/apache-rat-core/src/main/java/org/apache/rat/license/SimpleLicense.java
@@ -0,0 +1,123 @@
+/*
+ * 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.license;
+
+import java.util.Objects;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.rat.analysis.IHeaderMatcher;
+
+/**
+ * A simple implementation of ILicense.
+ */
+class SimpleLicense implements ILicense {
+
+ private ILicenseFamily family;
+ private IHeaderMatcher matcher;
+ private String derivedFrom;
+ private String notes;
+ private String name;
+ private String id;
+
+ SimpleLicense(ILicenseFamily family, IHeaderMatcher matcher, String derivedFrom, String notes, String name, String id) {
+ Objects.requireNonNull(matcher, "Matcher must not be null");
+ Objects.requireNonNull(family, "Family must not be null");
+ this.family = family;
+ this.matcher = matcher;
+ this.derivedFrom = derivedFrom;
+ this.notes = notes;
+ this.name = StringUtils.defaultIfBlank(name, family.getFamilyName());
+ this.id = StringUtils.defaultIfBlank(id, family.getFamilyCategory().trim());
+ }
+
+ @Override
+ public String toString() {
+ return String.format( "%s:%s", getId(), getName());
+ }
+
+ public ILicenseFamily getFamily() {
+ return family;
+ }
+
+ public void setFamily(ILicenseFamily family) {
+ this.family = family;
+ }
+
+ public IHeaderMatcher getMatcher() {
+ return matcher;
+ }
+
+ public void setMatcher(IHeaderMatcher matcher) {
+ this.matcher = matcher;
+ }
+
+ public void setDerivedFrom(String derivedFrom) {
+ this.derivedFrom = derivedFrom;
+ }
+
+ @Override
+ public String getId() {
+ return id;
+ }
+
+ @Override
+ public void reset() {
+ matcher.reset();
+ }
+
+ @Override
+ public State matches(String line) {
+ return matcher.matches(line);
+ }
+
+ @Override
+ public State finalizeState() {
+ return matcher.finalizeState();
+ }
+
+ @Override
+ public State currentState() {
+ return matcher.currentState();
+ }
+
+ @Override
+ public ILicenseFamily getLicenseFamily() {
+ return family;
+ }
+
+ @Override
+ public int compareTo(ILicense other) {
+ return ILicense.getComparator().compare(this, other);
+ }
+
+ @Override
+ public String getNotes() {
+ return notes;
+ }
+
+ @Override
+ public String derivedFrom() {
+ return derivedFrom;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/license/SimpleLicenseFamily.java b/apache-rat-core/src/main/java/org/apache/rat/license/SimpleLicenseFamily.java
index 24231dd15..3e6cd4cf4 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/license/SimpleLicenseFamily.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/license/SimpleLicenseFamily.java
@@ -15,29 +15,39 @@
* KIND, either express or implied. See the License for the *
* specific language governing permissions and limitations *
* under the License. *
- */
+ */
package org.apache.rat.license;
/**
- * Trivial bean implementing ILicenseFamily
- * @since Rat 0.8
+ * An implementation of the ILicenseFamily.
*/
-public class SimpleLicenseFamily implements ILicenseFamily {
+@Deprecated // remove in v1.0
+public class SimpleLicenseFamily {
private String familyName;
+ private String familyCategory;
- public SimpleLicenseFamily(String familyName) {
- setFamilyName(familyName);
- }
+ public SimpleLicenseFamily() {}
- public SimpleLicenseFamily() {
- this(null);
- }
-
- public final void setFamilyName(String familyName) {
+ public void setFamilyName(String familyName) {
this.familyName = familyName;
}
+
+ public void setFamilyCategory(String familyCategory) {
+ this.familyCategory = familyCategory;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("%s %s", getFamilyCategory(), getFamilyName());
+ }
+
public final String getFamilyName() {
return familyName;
}
+
+
+ public String getFamilyCategory() {
+ return familyCategory;
+ }
}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/license/W3CDocumentLicenseFamily.java b/apache-rat-core/src/main/java/org/apache/rat/license/W3CDocumentLicenseFamily.java
deleted file mode 100644
index c3d2101be..000000000
--- a/apache-rat-core/src/main/java/org/apache/rat/license/W3CDocumentLicenseFamily.java
+++ /dev/null
@@ -1,27 +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.license;
-
-import org.apache.rat.api.MetaData;
-
-public class W3CDocumentLicenseFamily extends SimpleLicenseFamily {
- public W3CDocumentLicenseFamily() {
- super(MetaData.RAT_LICENSE_FAMILY_NAME_VALUE_W3C_DOCUMENT_COPYRIGHT);
- }
-}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/license/W3CSoftwareLicenseFamily.java b/apache-rat-core/src/main/java/org/apache/rat/license/W3CSoftwareLicenseFamily.java
deleted file mode 100644
index 42a6dc901..000000000
--- a/apache-rat-core/src/main/java/org/apache/rat/license/W3CSoftwareLicenseFamily.java
+++ /dev/null
@@ -1,27 +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.license;
-
-import org.apache.rat.api.MetaData;
-
-public class W3CSoftwareLicenseFamily extends SimpleLicenseFamily {
- public W3CSoftwareLicenseFamily() {
- super(MetaData.RAT_LICENSE_FAMILY_NAME_VALUE_W3C_SOFTWARE_COPYRIGHT);
- }
-}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/policy/DefaultPolicy.java b/apache-rat-core/src/main/java/org/apache/rat/policy/DefaultPolicy.java
index 6cbf7a327..bec67c468 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/policy/DefaultPolicy.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/policy/DefaultPolicy.java
@@ -18,70 +18,70 @@
*/
package org.apache.rat.policy;
-import org.apache.rat.Defaults;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.SortedSet;
+
import org.apache.rat.api.Document;
import org.apache.rat.api.MetaData;
-import org.apache.rat.config.ConfigurationUtil;
import org.apache.rat.document.IDocumentAnalyser;
-import org.apache.rat.document.RatDocumentAnalysisException;
import org.apache.rat.license.ILicenseFamily;
+import org.apache.rat.license.LicenseFamilySetFactory;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
+/**
+ * A default Document Analyser that determines if the matched license is in the set of approved licenses.
+ */
public class DefaultPolicy implements IDocumentAnalyser {
- private List approvedLicenseNames;
+ private final SortedSet approvedLicenseFamilies;
/**
- * Creates a policy that matches the default licenses.
- * Mainly used for testing purposes.
+ * Constructor with the list of approved license families.
+ * @param approvedLicenseFamilies the approved license families.
*/
- DefaultPolicy() {
- this(new ArrayList(0), true);
+ public DefaultPolicy(final Collection approvedLicenseFamilies) {
+ this.approvedLicenseFamilies = LicenseFamilySetFactory.emptyLicenseFamilySet();
+ this.approvedLicenseFamilies.addAll(approvedLicenseFamilies);
}
- public DefaultPolicy(final ILicenseFamily[] approvedLicenses, boolean mergeWithDefault) {
- this(ConfigurationUtil.toNames(approvedLicenses), mergeWithDefault);
- }
-
- public DefaultPolicy(final List approvedLicenseNames, boolean mergeWithDefault) {
- this.approvedLicenseNames = new ArrayList<>();
-
- if (approvedLicenseNames == null || approvedLicenseNames.isEmpty()) {
- // used in tests only, no additional licenses given but defaults requested
- if(mergeWithDefault) {
- this.approvedLicenseNames = new ArrayList<>(Defaults.DEFAULT_LICENSE_FAMILIES);
- }
- } else {
- // avoid duplicate entries and merge with defaults if requested
- Set mergedLicenses = new HashSet<>(approvedLicenseNames);
- if(mergeWithDefault) {
- mergedLicenses.addAll(Defaults.DEFAULT_LICENSE_FAMILIES);
- }
- this.approvedLicenseNames = new ArrayList<>(mergedLicenses);
- }
- Collections.sort(this.approvedLicenseNames);
+ /**
+ * adds an ILicenseFamily to the list of approved licenses.
+ * @param approvedLicense license to be approved.
+ */
+ public void add(ILicenseFamily approvedLicense) {
+ this.approvedLicenseFamilies.add(approvedLicense);
}
- public void analyse(final Document subject) throws RatDocumentAnalysisException {
- if (subject != null) {
- final String name = subject.getMetaData().value(MetaData.RAT_URL_LICENSE_FAMILY_NAME);
- if (name != null) {
- final boolean isApproved = Collections.binarySearch(approvedLicenseNames, name) >= 0;
- reportLicenseApprovalClaim(subject, isApproved);
+ @Override
+ public void analyse(final Document document) {
+ if (document != null) {
+ boolean approval;
+ if (document.getMetaData().value(MetaData.RAT_URL_HEADER_CATEGORY) != null) {
+ ILicenseFamily licenseFamily = ILicenseFamily.builder()
+ .setLicenseFamilyCategory(
+ document.getMetaData().value(MetaData.RAT_URL_HEADER_CATEGORY))
+ .setLicenseFamilyName(document.getMetaData().value(MetaData.RAT_URL_LICENSE_FAMILY_NAME))
+ .build();
+ approval = approvedLicenseFamilies.contains(licenseFamily);
+ reportLicenseApprovalClaim(document, approval);
}
}
}
- public void reportLicenseApprovalClaim(final Document subject, final boolean isAcceptable) {
- subject.getMetaData().set(//
- isAcceptable ? MetaData.RAT_APPROVED_LICENSE_DATIM_TRUE: MetaData.RAT_APPROVED_LICENSE_DATIM_FALSE);
+ /**
+ * Report if the document as either having approved license or not.
+ * @param document the document to approve.
+ * @param isAcceptable {@code true} if the license is an approved one, {@code false} otherwise.
+ */
+ public void reportLicenseApprovalClaim(final Document document, final boolean isAcceptable) {
+ document.getMetaData().set(
+ isAcceptable ? MetaData.RAT_APPROVED_LICENSE_DATUM_TRUE : MetaData.RAT_APPROVED_LICENSE_DATUM_FALSE);
}
- public List getApprovedLicenseNames() {
- return Collections.unmodifiableList(approvedLicenseNames);
+ /**
+ * Gets an unmodifiable reference to the SortedSet of approved licenses that this policy is holding.
+ * @return sorted set of license family definitions.
+ */
+ public SortedSet getApprovedLicenseNames() {
+ return Collections.unmodifiableSortedSet(approvedLicenseFamilies);
}
}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/report/AbstractReport.java b/apache-rat-core/src/main/java/org/apache/rat/report/AbstractReport.java
index 18bfd1fd5..d3d896e90 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/report/AbstractReport.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/report/AbstractReport.java
@@ -26,14 +26,24 @@
* Abstract base class for deriving implementations of {@link RatReport}.
*/
public abstract class AbstractReport implements RatReport {
+ /**
+ * Empty default implementation.
+ */
public void startReport() throws RatException {
// Does nothing
}
+ /**
+ * Empty default implementation.
+ * @param document the actual document
+ */
public void report(Document document) throws RatException {
// Does nothing
}
+ /**
+ * Empty default implementation.
+ */
public void endReport() throws RatException {
// Does nothing
}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/report/RatReport.java b/apache-rat-core/src/main/java/org/apache/rat/report/RatReport.java
index d178acf0f..6208f571e 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/report/RatReport.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/report/RatReport.java
@@ -21,11 +21,32 @@
import org.apache.rat.api.Document;
import org.apache.rat.api.RatException;
+/**
+ * Interface that defines a RatReport.
+ * A RatReport examines a document and may report issues or modify the underlying file.
+ */
public interface RatReport {
+ /**
+ * Signals the start of execution for the report. Will be called before the {@code report()} method
+ * to ensure proper setup.
+ * @throws RatException on error.
+ * @see #report(Document)
+ */
void startReport() throws RatException;
+ /**
+ * Performs the actual reporting on the given document.
+ * @param document write any reporting results into this document upon analysis.
+ * @throws RatException on error.
+ */
void report(Document document) throws RatException;
+ /**
+ * Signals the end of execution for the report. Will be called after the {@code report()} method
+ * to ensure proper cleanup.
+ * @throws RatException on error.
+ * @see #report(Document)
+ */
void endReport() throws RatException;
}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/report/claim/impl/AbstractClaimReporter.java b/apache-rat-core/src/main/java/org/apache/rat/report/claim/impl/AbstractClaimReporter.java
index 8904cfbb6..ee059b649 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/report/claim/impl/AbstractClaimReporter.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/report/claim/impl/AbstractClaimReporter.java
@@ -31,18 +31,34 @@
* this class.
*/
public abstract class AbstractClaimReporter extends AbstractReport {
+ /**
+ * Empty default implementation.
+ * @param documentCategoryName name of the category
+ */
protected void handleDocumentCategoryClaim(String documentCategoryName) {
// Does nothing
}
+ /**
+ * Empty default implementation.
+ * @param licenseApproved name of the approved license
+ */
protected void handleApprovedLicenseClaim(String licenseApproved) {
// Does nothing
}
+ /**
+ * Empty default implementation.
+ * @param licenseFamilyName name of the license family
+ */
protected void handleLicenseFamilyNameClaim(String licenseFamilyName) {
// Does Nothing
}
+ /**
+ * Empty default implementation.
+ * @param headerCategory name of the header category
+ */
protected void handleHeaderCategoryClaim(String headerCategory) {
// Does nothing
}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/report/claim/impl/xml/SimpleXmlClaimReporter.java b/apache-rat-core/src/main/java/org/apache/rat/report/claim/impl/xml/SimpleXmlClaimReporter.java
index e4da2ee98..43185931c 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/report/claim/impl/xml/SimpleXmlClaimReporter.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/report/claim/impl/xml/SimpleXmlClaimReporter.java
@@ -24,6 +24,7 @@
import org.apache.rat.api.RatException;
import org.apache.rat.report.AbstractReport;
import org.apache.rat.report.xml.writer.IXmlWriter;
+import org.apache.rat.report.xml.writer.impl.base.XmlWriter;
import java.io.IOException;
import java.util.Calendar;
diff --git a/apache-rat-core/src/main/java/org/apache/rat/report/claim/util/LicenseAddingReport.java b/apache-rat-core/src/main/java/org/apache/rat/report/claim/util/LicenseAddingReport.java
index 8570c692b..eb0dd83e6 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/report/claim/util/LicenseAddingReport.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/report/claim/util/LicenseAddingReport.java
@@ -27,13 +27,14 @@
import org.apache.rat.api.MetaData.Datum;
import org.apache.rat.api.RatException;
import org.apache.rat.report.AbstractReport;
+import org.apache.rat.utils.Log;
public class LicenseAddingReport extends AbstractReport {
private final AbstractLicenseAppender appender;
- public LicenseAddingReport(String pCopyrightMsg, boolean pForced) {
- appender = pCopyrightMsg == null ? new ApacheV2LicenseAppender() : new ApacheV2LicenseAppender(pCopyrightMsg);
+ public LicenseAddingReport(final Log log, String pCopyrightMsg, boolean pForced) {
+ appender = pCopyrightMsg == null ? new ApacheV2LicenseAppender(log) : new ApacheV2LicenseAppender(log,pCopyrightMsg);
appender.setForce(pForced);
}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/report/xml/XmlReportFactory.java b/apache-rat-core/src/main/java/org/apache/rat/report/xml/XmlReportFactory.java
index ae3c23b6b..b88dbff60 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/report/xml/XmlReportFactory.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/report/xml/XmlReportFactory.java
@@ -22,6 +22,7 @@
import org.apache.rat.analysis.DefaultAnalyserFactory;
import org.apache.rat.document.IDocumentAnalyser;
import org.apache.rat.document.impl.util.DocumentAnalyserMultiplexer;
+import org.apache.rat.license.LicenseSetFactory.LicenseFilter;
import org.apache.rat.policy.DefaultPolicy;
import org.apache.rat.report.RatReport;
import org.apache.rat.report.claim.ClaimStatistic;
@@ -35,24 +36,33 @@
import java.util.List;
/**
- * Creates reports.
+ * A factory to create reports from a writer and a configuration.
*
*/
public class XmlReportFactory {
- public static final RatReport createStandardReport(IXmlWriter writer,
- final ClaimStatistic pStatistic, ReportConfiguration pConfiguration) {
+ /**
+ * Creates a RatReport from the arguments.
+ * The {@code statistic} is used to create a ClaimAggregator.
+ * If the {@code configuration} indicates that licenses should be added a LicenseAddingReport is added.
+ * @param writer The XML writer to send output to.
+ * @param statistic the ClaimStatistics for the report. may be null.
+ * @param configuration The report configuration.
+ * @return a RatReport instance.
+ */
+ public static RatReport createStandardReport(IXmlWriter writer,
+ final ClaimStatistic statistic, ReportConfiguration configuration) {
final List reporters = new ArrayList<>();
- if (pStatistic != null) {
- reporters.add(new ClaimAggregator(pStatistic));
+ if (statistic != null) {
+ reporters.add(new ClaimAggregator(statistic));
}
- if (pConfiguration.isAddingLicenses()) {
- reporters.add(new LicenseAddingReport(pConfiguration.getCopyrightMessage(), pConfiguration.isAddingLicensesForced()));
+ if (configuration.isAddingLicenses()) {
+ reporters.add(new LicenseAddingReport(configuration.getLog(), configuration.getCopyrightMessage(), configuration.isAddingLicensesForced()));
}
reporters.add(new SimpleXmlClaimReporter(writer));
final IDocumentAnalyser analyser =
- DefaultAnalyserFactory.createDefaultAnalyser(pConfiguration.getHeaderMatcher());
- final DefaultPolicy policy = new DefaultPolicy(pConfiguration.getApprovedLicenseNames(), pConfiguration.isApproveDefaultLicenses());
+ DefaultAnalyserFactory.createDefaultAnalyser(configuration.getLog(), configuration.getLicenses(LicenseFilter.all));
+ final DefaultPolicy policy = new DefaultPolicy(configuration.getLicenseFamilies(LicenseFilter.approved));
final IDocumentAnalyser[] analysers = {analyser, policy};
DocumentAnalyserMultiplexer analysisMultiplexer = new DocumentAnalyserMultiplexer(analysers);
diff --git a/apache-rat-core/src/main/java/org/apache/rat/report/xml/writer/IXmlWriter.java b/apache-rat-core/src/main/java/org/apache/rat/report/xml/writer/IXmlWriter.java
index 9f7268f07..cad0768cc 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/report/xml/writer/IXmlWriter.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/report/xml/writer/IXmlWriter.java
@@ -21,11 +21,11 @@
import java.io.IOException;
/**
- * Simple interface for creating basic xml documents.
+ * Simple interface for creating basic XML documents.
* Performs basic validation and escaping.
- * Not namespace aware (may reconsider this later).
+ * Not namespace aware.
*/
-public interface IXmlWriter {
+public interface IXmlWriter extends AutoCloseable {
/**
* Starts a document by writing a prolog.
diff --git a/apache-rat-core/src/main/java/org/apache/rat/report/xml/writer/InvalidXmlException.java b/apache-rat-core/src/main/java/org/apache/rat/report/xml/writer/InvalidXmlException.java
index e01226fd7..ed0a0905e 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/report/xml/writer/InvalidXmlException.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/report/xml/writer/InvalidXmlException.java
@@ -21,15 +21,18 @@
import java.io.IOException;
/**
- * Indicates that the requested document would not be well formed.
- *
+ * Indicates that the requested document is not well formed.
*/
public class InvalidXmlException extends IOException {
private static final long serialVersionUID = 1L;
- public InvalidXmlException(String s) {
- super(s);
+ /**
+ * Instantiate exception with given message.
+ * @param message more context when this exception happens.
+ */
+ public InvalidXmlException(String message) {
+ super(message);
}
}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/report/xml/writer/XmlWriterUtils.java b/apache-rat-core/src/main/java/org/apache/rat/report/xml/writer/XmlWriterUtils.java
deleted file mode 100644
index 26f540cd9..000000000
--- a/apache-rat-core/src/main/java/org/apache/rat/report/xml/writer/XmlWriterUtils.java
+++ /dev/null
@@ -1,29 +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.report.xml.writer;
-
-import java.io.IOException;
-
-public class XmlWriterUtils {
-
- public static final void writeAttribute(final IXmlWriter writer, final String name, final boolean booleanValue) throws IOException {
- final String value = Boolean.toString(booleanValue);
- writer.attribute(name, value);
- }
-}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/report/xml/writer/impl/base/XmlWriter.java b/apache-rat-core/src/main/java/org/apache/rat/report/xml/writer/impl/base/XmlWriter.java
index d30475226..36365a024 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/report/xml/writer/impl/base/XmlWriter.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/report/xml/writer/impl/base/XmlWriter.java
@@ -18,10 +18,6 @@
*/
package org.apache.rat.report.xml.writer.impl.base;
-import org.apache.rat.report.xml.writer.IXmlWriter;
-import org.apache.rat.report.xml.writer.InvalidXmlException;
-import org.apache.rat.report.xml.writer.OperationNotAllowedException;
-
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayDeque;
@@ -29,13 +25,20 @@
import java.util.HashSet;
import java.util.Set;
+import org.apache.rat.report.xml.writer.IXmlWriter;
+import org.apache.rat.report.xml.writer.InvalidXmlException;
+import org.apache.rat.report.xml.writer.OperationNotAllowedException;
+
/**
- * Lightweight {@link IXmlWriter} implementation.
*
- * Requires a wrapper to be used safely in a multithreaded
- * environment.
+ * Lightweight {@link IXmlWriter} implementation.
+ *
+ *
+ * Requires a wrapper to be used safely in a multithreaded environment.
+ *
*
- * Not intended to be subclassed. Please copy and hack!
+ * Not intended to be subclassed. Please copy and hack!
+ *
*/
public final class XmlWriter implements IXmlWriter {
@@ -269,10 +272,11 @@ public final class XmlWriter implements IXmlWriter {
Arrays.fill(CHARACTER_CODES, 0x4E00, 0x9FA5, NAME_START_OR_BODY_CHAR);
CHARACTER_CODES[0x3007] = NAME_START_OR_BODY_CHAR;
Arrays.fill(CHARACTER_CODES, 0x3021, 0x3029, NAME_START_OR_BODY_CHAR);
- // NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' | CombiningChar | Extender
+ // NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' | CombiningChar |
+ // Extender
CHARACTER_CODES['.'] = NAME_BODY_CHAR;
CHARACTER_CODES['-'] = NAME_BODY_CHAR;
- // CombiningChar
+ // CombiningChar
Arrays.fill(CHARACTER_CODES, 0x0300, 0x0345, NAME_BODY_CHAR);
Arrays.fill(CHARACTER_CODES, 0x0360, 0x0361, NAME_BODY_CHAR);
Arrays.fill(CHARACTER_CODES, 0x0483, 0x0486, NAME_BODY_CHAR);
@@ -368,7 +372,7 @@ public final class XmlWriter implements IXmlWriter {
Arrays.fill(CHARACTER_CODES, 0x302A, 0x302F, NAME_BODY_CHAR);
CHARACTER_CODES[0x3099] = NAME_BODY_CHAR;
CHARACTER_CODES[0x309A] = NAME_BODY_CHAR;
- // Digit
+ // Digit
Arrays.fill(CHARACTER_CODES, 0x0030, 0x0039, NAME_BODY_CHAR);
Arrays.fill(CHARACTER_CODES, 0x0660, 0x0669, NAME_BODY_CHAR);
Arrays.fill(CHARACTER_CODES, 0x06F0, 0x06F9, NAME_BODY_CHAR);
@@ -384,7 +388,7 @@ public final class XmlWriter implements IXmlWriter {
Arrays.fill(CHARACTER_CODES, 0x0E50, 0x0E59, NAME_BODY_CHAR);
Arrays.fill(CHARACTER_CODES, 0x0ED0, 0x0ED9, NAME_BODY_CHAR);
Arrays.fill(CHARACTER_CODES, 0x0F20, 0x0F29, NAME_BODY_CHAR);
- // Extender
+ // Extender
CHARACTER_CODES[0x00B7] = NAME_BODY_CHAR;
CHARACTER_CODES[0x02D0] = NAME_BODY_CHAR;
CHARACTER_CODES[0x02D1] = NAME_BODY_CHAR;
@@ -400,27 +404,31 @@ public final class XmlWriter implements IXmlWriter {
}
private final Writer writer;
- private final ArrayDeque elementNames;
+ private final ArrayDeque elementNames;
private final Set currentAttributes = new HashSet<>();
boolean elementsWritten = false;
boolean inElement = false;
boolean prologWritten = false;
+ /**
+ * Constructs an XmlWriter with the specified writer for output.
+ * @param writer the writer to write to.
+ */
public XmlWriter(final Writer writer) {
this.writer = writer;
- this.elementNames = new ArrayDeque();
+ this.elementNames = new ArrayDeque<>();
}
/**
- * Starts a document by writing a prolog.
- * Calling this method is optional.
- * When writing a document fragment, it should not be called.
+ * Starts a document by writing a prolog. Calling this method is optional. When
+ * writing a document fragment, it should not be called.
*
* @return this object
- * @throws OperationNotAllowedException if called after the first element has been written
- * or once a prolog has already been written
+ * @throws OperationNotAllowedException if called after the first element has
+ * been written or once a prolog has already been written
*/
+ @Override
public IXmlWriter startDocument() throws IOException {
if (elementsWritten) {
throw new OperationNotAllowedException("Document already started");
@@ -438,9 +446,11 @@ public IXmlWriter startDocument() throws IOException {
*
* @param elementName the name of the element, not null
* @return this object
- * @throws InvalidXmlException if the name is not valid for an xml element
- * @throws OperationNotAllowedException if called after the first element has been closed
+ * @throws InvalidXmlException if the name is not valid for an xml element
+ * @throws OperationNotAllowedException if called after the first element has
+ * been closed
*/
+ @Override
public IXmlWriter openElement(final CharSequence elementName) throws IOException {
if (elementsWritten && elementNames.isEmpty()) {
throw new OperationNotAllowedException("Root element already closed. Cannot open new element.");
@@ -461,25 +471,25 @@ public IXmlWriter openElement(final CharSequence elementName) throws IOException
}
/**
- * Writes an attribute of an element.
- * Note that this is only allowed directly after {@link #openElement(CharSequence)}
- * or {@link #attribute}.
+ * Writes an attribute of an element. Note that this is only allowed directly
+ * after {@link #openElement(CharSequence)} or {@link #attribute}.
*
- * @param name the attribute name, not null
+ * @param name the attribute name, not null
* @param value the attribute value, not null
* @return this object
- * @throws InvalidXmlException if the name is not valid for an xml attribute
- * or if a value for the attribute has already been written
- * @throws OperationNotAllowedException if called after {@link #content(CharSequence)}
- * or {@link #closeElement()} or before any call to {@link #openElement(CharSequence)}
+ * @throws InvalidXmlException if the name is not valid for an xml attribute or
+ * if a value for the attribute has already been written
+ * @throws OperationNotAllowedException if called after
+ * {@link #content(CharSequence)} or {@link #closeElement()} or before any call
+ * to {@link #openElement(CharSequence)}
*/
+ @Override
public IXmlWriter attribute(CharSequence name, CharSequence value) throws IOException {
if (elementNames.isEmpty()) {
if (elementsWritten) {
throw new OperationNotAllowedException("Root element has already been closed.");
- } else {
- throw new OperationNotAllowedException("Close called before an element has been opened.");
}
+ throw new OperationNotAllowedException("Close called before an element has been opened.");
}
if (isInvalidName(name)) {
throw new InvalidXmlException("'" + name + "' is not a valid attribute name.");
@@ -505,22 +515,21 @@ private void writeAttributeContent(CharSequence content) throws IOException {
}
/**
- * Writes content.
- * Calling this method will automatically
- * Note that this method does not use CDATA.
+ * Writes content. Calling this method will automatically Note that this method
+ * does not use CDATA.
*
* @param content the content to write
* @return this object
- * @throws OperationNotAllowedException if called before any call to {@link #openElement}
- * or after the first element has been closed
+ * @throws OperationNotAllowedException if called before any call to
+ * {@link #openElement} or after the first element has been closed
*/
+ @Override
public IXmlWriter content(CharSequence content) throws IOException {
if (elementNames.isEmpty()) {
if (elementsWritten) {
throw new OperationNotAllowedException("Root element has already been closed.");
- } else {
- throw new OperationNotAllowedException("An element must be opened before content can be written.");
- }
+ }
+ throw new OperationNotAllowedException("An element must be opened before content can be written.");
}
if (inElement) {
writer.write('>');
@@ -564,18 +573,18 @@ private boolean isOutOfRange(final char character) {
* Closes the last element written.
*
* @return this object
- * @throws OperationNotAllowedException if called before any call to {@link #openElement}
- * or after the first element has been closed
+ * @throws OperationNotAllowedException if called before any call to
+ * {@link #openElement} or after the first element has been closed
*/
+ @Override
public IXmlWriter closeElement() throws IOException {
if (elementNames.isEmpty()) {
if (elementsWritten) {
throw new OperationNotAllowedException("Root element has already been closed.");
- } else {
- throw new OperationNotAllowedException("Close called before an element has been opened.");
- }
+ }
+ throw new OperationNotAllowedException("Close called before an element has been opened.");
}
- final CharSequence elementName = (CharSequence) elementNames.pop();
+ final CharSequence elementName = elementNames.pop();
if (inElement) {
writer.write('/');
writer.write('>');
@@ -590,16 +599,16 @@ public IXmlWriter closeElement() throws IOException {
return this;
}
-
/**
- * Closes all pending elements.
- * When appropriate, resources are also flushed and closed.
- * No exception is raised when called upon a document whose
- * root element has already been closed.
+ * Closes all pending elements. When appropriate, resources are also flushed and
+ * closed. No exception is raised when called upon a document whose root element
+ * has already been closed.
*
* @return this object
- * @throws OperationNotAllowedException if called before any call to {@link #openElement}
+ * @throws OperationNotAllowedException if called before any call to
+ * {@link #openElement}
*/
+ @Override
public IXmlWriter closeDocument() throws IOException {
if (elementNames.isEmpty() && !elementsWritten) {
throw new OperationNotAllowedException("Close called before an element has been opened.");
@@ -647,4 +656,9 @@ private boolean isValidNameBody(final char character) {
final byte code = CHARACTER_CODES[character];
return (code & NAME_MASK) > 0;
}
+
+ @Override
+ public void close() throws Exception {
+ closeDocument();
+ }
}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/util/HeaderMatcherMultiplexer.java b/apache-rat-core/src/main/java/org/apache/rat/utils/DefaultLog.java
similarity index 53%
rename from apache-rat-core/src/main/java/org/apache/rat/analysis/util/HeaderMatcherMultiplexer.java
rename to apache-rat-core/src/main/java/org/apache/rat/utils/DefaultLog.java
index ed3eb7382..f421121d2 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/analysis/util/HeaderMatcherMultiplexer.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/utils/DefaultLog.java
@@ -15,42 +15,49 @@
* KIND, either express or implied. See the License for the *
* specific language governing permissions and limitations *
* under the License. *
- */
-package org.apache.rat.analysis.util;
-
-import org.apache.rat.analysis.IHeaderMatcher;
-import org.apache.rat.analysis.RatHeaderAnalysisException;
-import org.apache.rat.api.Document;
-
-import java.util.List;
+ */
+package org.apache.rat.utils;
/**
- * Delegates to an ordered set of matchers.
- *
+ * A default implementation of Log that writes to System.out and System.err
*/
-public final class HeaderMatcherMultiplexer implements IHeaderMatcher {
+public class DefaultLog implements Log {
- private final List matchers;
+ /**
+ * The instance of the default log.
+ */
+ public static final DefaultLog INSTANCE = new DefaultLog();
+
+ private Level level;
- public HeaderMatcherMultiplexer(final List matchers) {
- this.matchers = matchers;
+ private DefaultLog() {
+ level = Level.WARN;
}
- public boolean match(Document subject, String line) throws RatHeaderAnalysisException {
- boolean result = false;
- for (IHeaderMatcher matcher : matchers) {
- result = matcher.match(subject, line);
- if (result) {
+ public void setLevel(Level level) {
+ this.level = level;
+ }
+
+ public Level getLevel() {
+ return level;
+ }
+
+ @Override
+ public void log(Level level, String msg) {
+ if (this.level.ordinal() <= level.ordinal())
+ switch (level) {
+ case DEBUG:
+ case INFO:
+ case WARN:
+ System.out.format("%s: %s%n", level, msg);
+ break;
+ case ERROR:
+ System.err.format("%s: %s%n", level, msg);
+ break;
+ case OFF:
+ break;
+ default:
break;
}
- }
- return result;
}
-
- public void reset() {
- for (IHeaderMatcher matcher : matchers) {
- matcher.reset();
- }
- }
-
-}
+}
\ No newline at end of file
diff --git a/apache-rat-core/src/main/java/org/apache/rat/utils/Log.java b/apache-rat-core/src/main/java/org/apache/rat/utils/Log.java
new file mode 100644
index 000000000..82eb9b8b5
--- /dev/null
+++ b/apache-rat-core/src/main/java/org/apache/rat/utils/Log.java
@@ -0,0 +1,78 @@
+/*
+ * 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.utils;
+
+/**
+ * The definition of logging for the core. UIs are expected to provide an implementation of
+ * Log to log data to the appropriate system within the UI.
+ */
+public interface Log {
+ /**
+ * The log levels supported by logging.
+ */
+ public enum Level {
+ // these must be listed in order of decreasing noisiness.
+ /**
+ * Log debug only.
+ */
+ DEBUG,
+ /**
+ * Log info only.
+ */
+ INFO,
+ /**
+ * Log warn only.
+ */
+ WARN,
+ /**
+ * Log error only.
+ */
+ ERROR,
+ /**
+ * Log nothing.
+ */
+ OFF};
+
+ /**
+ * Writes a message at a specific log level.
+ * @param level The log level to write at.
+ * @param message the Message to write.
+ */
+ void log(Level level, String message);
+
+ default void log(Level level, Object message) {
+ log(level, message == null ? "NULL" : message.toString());
+ }
+
+ default void debug(Object message) {
+ log(Level.DEBUG, message);
+ }
+
+ default void info(Object message) {
+ log(Level.INFO, message);
+ }
+
+ default void warn(Object message) {
+ log(Level.WARN, message);
+ }
+
+ default void error(Object message) {
+ log(Level.ERROR, message);
+ }
+}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/utils/ReportingSet.java b/apache-rat-core/src/main/java/org/apache/rat/utils/ReportingSet.java
new file mode 100644
index 000000000..fa506a328
--- /dev/null
+++ b/apache-rat-core/src/main/java/org/apache/rat/utils/ReportingSet.java
@@ -0,0 +1,286 @@
+/*
+ * 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.utils;
+
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.SortedSet;
+import java.util.Spliterator;
+import java.util.TreeSet;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+
+/**
+ * A sorted set that reports insertion collisions.
+ * @param the type of object
+ */
+public class ReportingSet implements SortedSet {
+ private final SortedSet delegate;
+ private Options duplicateOption = Options.IGNORE;
+ private Log.Level duplicateLogLevel = Log.Level.WARN;
+ private Log log = DefaultLog.INSTANCE;
+ private Function duplicateFmt = (t) -> String.format("Duplicate %s (%s) detected %s", t.getClass(), t);
+
+ public enum Options { OVERWRITE, IGNORE, FAIL }
+
+ /**
+ * Constructor.
+ * Creates a TreeSet of type T.
+ */
+ public ReportingSet() {
+ this(new TreeSet());
+ }
+
+ /**
+ * Constructs.
+ *
+ * @param delegate the SortedSet to delegate to.
+ */
+ public ReportingSet(SortedSet delegate) {
+ this.delegate = delegate;
+ }
+
+ /**
+ * Sets the function to generate the log message.
+ * @param msgFmt A function to return the string to be displayed when a collision occurs.
+ * @return This for chaining.
+ */
+ public ReportingSet setMsgFormat(Function msgFmt) {
+ duplicateFmt = msgFmt;
+ return this;
+ }
+ /**
+ * If set true attempts to duplicate will throw an IllegalArgumentException.
+ * The default state is false;.
+ * @param state the state to set.
+ * @return this for chaining.
+ */
+ public ReportingSet setDuplicateOption(Options state) {
+ this.duplicateOption = state;
+ return this;
+ }
+
+ /**
+ * Sets the log that the reporting set will log to.
+ * if not set the DefaultLog is used.
+ * @param log the Log implementation to use.
+ * @return this for chaining.
+ */
+ public ReportingSet setLog(Log log) {
+ this.log = log;
+ return this;
+ }
+
+ /**
+ * Sets the log level that the reporting set will log at.
+ * if not set the default level is WARN.
+ * @param level the log level to use.
+ * @return this for chaining.
+ */
+ public ReportingSet setLogLevel(Log.Level level) {
+ this.duplicateLogLevel = level;
+ return this;
+ }
+
+ private ReportingSet sameConfig(SortedSet delegate) {
+ ReportingSet result = delegate instanceof ReportingSet ? (ReportingSet) delegate : new ReportingSet<>(delegate);
+ return result.setDuplicateOption(this.duplicateOption).setLog(this.log).setLogLevel(this.duplicateLogLevel);
+ }
+
+ /**
+ * Adds the item if it is not present. Does not report collisions.
+ * @param e the item to add.
+ * @return true if the item was added, false otherwise.
+ */
+ public boolean addIfNotPresent(T e) {
+ return add(false, e);
+ }
+
+ @Override
+ public boolean add(T e) {
+ return add(true, e);
+ }
+
+ /**
+ * Attempts to add an item. Report failures if reportDup is true.
+ * @param reportDup the reporting flag.
+ * @param e the item to add
+ * @return true if the item was added.
+ */
+ private boolean add(boolean reportDup, T e) {
+ if (delegate.contains(e)) {
+ String msg = String.format("%s",ReportingSet.this.duplicateFmt.apply(e));
+ if (reportDup) {
+ msg = String.format( "%s (action: %s)", msg, duplicateOption);
+ log.log(duplicateLogLevel, msg);
+ }
+ switch (duplicateOption) {
+ case FAIL:
+ throw new IllegalArgumentException(msg);
+ case IGNORE:
+ return false;
+ case OVERWRITE:
+ delegate.remove(e);
+ return delegate.add(e);
+ }
+ }
+ return delegate.add(e);
+ }
+
+ @Override
+ public boolean addAll(Collection extends T> c) {
+ boolean updated = false;
+ for (T e : c) {
+ updated |= add(e);
+ }
+ return updated;
+ }
+
+
+ public boolean addAllIfNotPresent(Collection extends T> c) {
+ boolean updated = false;
+ for (T e : c) {
+ updated |= addIfNotPresent(e);
+ }
+ return updated;
+ }
+
+ @Override
+ public void clear() {
+ delegate.clear();
+ }
+
+ @Override
+ public Comparator super T> comparator() {
+ return delegate.comparator();
+ }
+
+ @Override
+ public boolean contains(Object o) {
+ return delegate.contains(o);
+ }
+
+ @Override
+ public boolean containsAll(Collection> c) {
+ return delegate.containsAll(c);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ return delegate.equals(o);
+ }
+
+ @Override
+ public T first() {
+ return delegate.first();
+ }
+
+ @Override
+ public void forEach(Consumer super T> action) {
+ delegate.forEach(action);
+ }
+
+ @Override
+ public int hashCode() {
+ return delegate.hashCode();
+ }
+
+ @Override
+ public ReportingSet headSet(T toElement) {
+ return sameConfig(delegate.headSet(toElement));
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return delegate.isEmpty();
+ }
+
+ @Override
+ public Iterator iterator() {
+ return delegate.iterator();
+ }
+
+ @Override
+ public T last() {
+ return delegate.last();
+ }
+
+ @Override
+ public Stream parallelStream() {
+ return delegate.parallelStream();
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ return delegate.remove(o);
+ }
+
+ @Override
+ public boolean removeAll(Collection> c) {
+ return delegate.removeAll(c);
+ }
+
+ @Override
+ public boolean removeIf(Predicate super T> filter) {
+ return delegate.removeIf(filter);
+ }
+
+ @Override
+ public boolean retainAll(Collection> c) {
+ return delegate.retainAll(c);
+ }
+
+ @Override
+ public int size() {
+ return delegate.size();
+ }
+
+ @Override
+ public Spliterator spliterator() {
+ return delegate.spliterator();
+ }
+
+ @Override
+ public Stream stream() {
+ return delegate.stream();
+ }
+
+ @Override
+ public ReportingSet subSet(T fromElement, T toElement) {
+ return sameConfig(delegate.subSet(fromElement, toElement));
+ }
+
+ @Override
+ public ReportingSet tailSet(T fromElement) {
+ return sameConfig(delegate.tailSet(fromElement));
+ }
+
+ @Override
+ public Object[] toArray() {
+ return delegate.toArray();
+ }
+
+ @Override
+ public T[] toArray(T[] a) {
+ return delegate.toArray(a);
+ }
+}
\ No newline at end of file
diff --git a/apache-rat-core/src/main/java/org/apache/rat/walker/ArchiveWalker.java b/apache-rat-core/src/main/java/org/apache/rat/walker/ArchiveWalker.java
index 4e5ec3b70..e2196f81d 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/walker/ArchiveWalker.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/walker/ArchiveWalker.java
@@ -20,10 +20,10 @@
package org.apache.rat.walker;
import java.io.File;
-import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FilenameFilter;
import java.io.IOException;
+import java.nio.file.Files;
import org.apache.commons.compress.archivers.ArchiveEntry;
import org.apache.commons.compress.archivers.ArchiveInputStream;
@@ -63,17 +63,17 @@ public ArchiveWalker(File file, final FilenameFilter filter) throws FileNotFound
public void run(final RatReport report) throws RatException {
try {
- ArchiveInputStream input;
+ ArchiveInputStream extends ArchiveEntry> input;
/* I am really sad that classes aren't first-class objects in
Java :'( */
try {
- input = new TarArchiveInputStream(new GzipCompressorInputStream(new FileInputStream(file)));
+ input = new TarArchiveInputStream(new GzipCompressorInputStream(Files.newInputStream(file.toPath())));
} catch (IOException e) {
try {
- input = new TarArchiveInputStream(new BZip2CompressorInputStream(new FileInputStream(file)));
+ input = new TarArchiveInputStream(new BZip2CompressorInputStream(Files.newInputStream(file.toPath())));
} catch (IOException e2) {
- input = new ZipArchiveInputStream(new FileInputStream(file));
+ input = new ZipArchiveInputStream(Files.newInputStream(file.toPath()));
}
}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/walker/DirectoryWalker.java b/apache-rat-core/src/main/java/org/apache/rat/walker/DirectoryWalker.java
index c9b7f12cf..ab75cd3f2 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/walker/DirectoryWalker.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/walker/DirectoryWalker.java
@@ -19,45 +19,60 @@
package org.apache.rat.walker;
+import java.io.File;
+import java.io.FilenameFilter;
+import java.util.Arrays;
+import java.util.regex.Pattern;
+
+import org.apache.commons.io.filefilter.IOFileFilter;
import org.apache.rat.api.Document;
import org.apache.rat.api.RatException;
import org.apache.rat.document.impl.FileDocument;
import org.apache.rat.report.IReportable;
import org.apache.rat.report.RatReport;
-import java.io.File;
-import java.io.FilenameFilter;
-import java.util.Arrays;
-import java.util.regex.Pattern;
-
/**
* Walks directories.
*/
public class DirectoryWalker extends Walker implements IReportable {
- protected static final FileNameComparator COMPARATOR = new FileNameComparator();
+ private static final FileNameComparator COMPARATOR = new FileNameComparator();
+
+ private final IOFileFilter directoryFilter;
- public DirectoryWalker(File file) {
- this(file, (FilenameFilter) null);
+ /**
+ * Constructs a walker.
+ *
+ * @param file the directory to walk.
+ * @param directoryFilter directory filter to eventually exclude some directories/files from the scan.
+ */
+ public DirectoryWalker(File file, IOFileFilter directoryFilter) {
+ this(file, (FilenameFilter) null, directoryFilter);
}
/**
* Constructs a walker.
*
- * @param file not null
+ * @param file the directory to walk (not null).
* @param filter filters input files (optional),
* or null when no filtering should be performed
+ * @param directoryFilter filters directories (optional), or null when no filtering should be performed.
*/
- public DirectoryWalker(File file, final FilenameFilter filter) {
+ public DirectoryWalker(File file, final FilenameFilter filter, IOFileFilter directoryFilter) {
super(file.getPath(), file, filter);
+ this.directoryFilter = directoryFilter;
}
- public DirectoryWalker(File file, final Pattern ignoreNameRegex) {
+ /**
+ * Constructs a walker.
+ *
+ * @param file the directory to walk (not null).
+ * @param ignoreNameRegex ignore directories/files with name matching the regex.
+ * @param directoryFilter filters directories (optional), or null when no filtering should be performed.
+ */
+ public DirectoryWalker(File file, final Pattern ignoreNameRegex, IOFileFilter directoryFilter) {
super(file.getPath(), file, regexFilter(ignoreNameRegex));
- }
-
- public boolean isRestricted() {
- return false;
+ this.directoryFilter = directoryFilter;
}
/**
@@ -68,7 +83,11 @@ public boolean isRestricted() {
* @throws RatException
*/
private void processDirectory(RatReport report, final File file) throws RatException {
- if (!isRestricted(file)) {
+ if (directoryFilter != null) {
+ if (!directoryFilter.accept(file)) {
+ process(report, file);
+ }
+ } else {
process(report, file);
}
}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/walker/NameBasedHiddenFileFilter.java b/apache-rat-core/src/main/java/org/apache/rat/walker/NameBasedHiddenFileFilter.java
new file mode 100644
index 000000000..19a54ebb9
--- /dev/null
+++ b/apache-rat-core/src/main/java/org/apache/rat/walker/NameBasedHiddenFileFilter.java
@@ -0,0 +1,85 @@
+/*
+ * 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.walker;
+
+import org.apache.commons.io.filefilter.AbstractFileFilter;
+import org.apache.commons.io.filefilter.IOFileFilter;
+
+import java.io.File;
+import java.io.Serializable;
+
+/**
+ * This filter accepts {@code File}s that are hidden, e.g. file name starts with .
+ *
+ * Example, showing how to print out a list of the current directory's hidden files:
+ *
+ * Using Classic IO
+ *
+ * File dir = new File(".");
+ * String[] files = dir.list(NameBasedHiddenFileFilter.HIDDEN);
+ * for (String file : files) {
+ * System.out.println(file);
+ * }
+ *
+ *
+ * Using NIO
+ *
+ * final Path dir = Paths.get("");
+ * final AccumulatorPathVisitor visitor = AccumulatorPathVisitor.withLongCounters(NameBasedHiddenFileFilter.HIDDEN);
+ * //
+ * // Walk one dir
+ * Files.walkFileTree(dir, Collections.emptySet(), 1, visitor);
+ * System.out.println(visitor.getPathCounters());
+ * System.out.println(visitor.getFileList());
+ * //
+ * visitor.getPathCounters().reset();
+ * //
+ * // Walk dir tree
+ * Files.walkFileTree(dir, visitor);
+ * System.out.println(visitor.getPathCounters());
+ * System.out.println(visitor.getDirList());
+ * System.out.println(visitor.getFileList());
+ *
+ */
+public class NameBasedHiddenFileFilter extends AbstractFileFilter implements Serializable {
+
+ private static final long serialVersionUID = -5951069871734926741L;
+ /**
+ * Singleton instance of hidden filter.
+ */
+ public static final IOFileFilter HIDDEN = new NameBasedHiddenFileFilter();
+
+ /**
+ * Restrictive constructor.
+ */
+ protected NameBasedHiddenFileFilter() {
+ }
+
+ /**
+ * Checks to see if the file is hidden, e.g. file name starts with .
+ *
+ * @param file the File to check
+ * @return {@code true} if the file is hidden (file name starting with .), {@code false} else
+ */
+ @Override
+ public boolean accept(File file) {
+ return file.getName().startsWith(".");
+ }
+
+}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/walker/Walker.java b/apache-rat-core/src/main/java/org/apache/rat/walker/Walker.java
index 064d9ed79..daecbd154 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/walker/Walker.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/walker/Walker.java
@@ -36,22 +36,16 @@ public abstract class Walker implements IReportable {
protected final FilenameFilter filter;
protected static FilenameFilter regexFilter(final Pattern pattern) {
- return new FilenameFilter() {
- public boolean accept(File dir, String name) {
- final boolean result;
- if (pattern == null) {
- result = true;
- } else {
- result = !pattern.matcher(name).matches();
- }
- return result;
+ return (dir, name) -> {
+ final boolean result;
+ if (pattern == null) {
+ result = true;
+ } else {
+ result = !pattern.matcher(name).matches();
}
+ return result;
};
}
-
- protected boolean isRestricted(File file) {
- return file.getName().startsWith(".");
- }
protected final boolean isNotIgnored(final File file) {
boolean result = false;
diff --git a/apache-rat-core/src/main/resources/org/apache/rat/default.xml b/apache-rat-core/src/main/resources/org/apache/rat/default.xml
new file mode 100644
index 000000000..9041f7495
--- /dev/null
+++ b/apache-rat-core/src/main/resources/org/apache/rat/default.xml
@@ -0,0 +1,267 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Licensed under the Apache License, Version 2.0 (the
+ "License")
+ Licensed to the Apache Software Foundation (ASF) under
+ one
+ or more contributor license agreements; and to You under
+ the
+ Apache License, Version 2.0.
+ http://www.apache.org/licenses/LICENSE-2.0
+ https://www.apache.org/licenses/LICENSE-2.0
+ http://www.apache.org/licenses/LICENSE-2.0.html
+ https://www.apache.org/licenses/LICENSE-2.0.html
+ http://www.apache.org/licenses/LICENSE-2.0.txt
+ https://www.apache.org/licenses/LICENSE-2.0.txt
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The contents of this file are subject to the terms of the
+ Common Development and Distribution License("CDDL") (the
+ "License"). You may not use this file except in compliance
+ with the License.
+
+
+
+
+
+ Modified CDDL1 license
+
+ The contents of this file are subject to the terms of
+ the Common Development and Distribution License (the
+ "License") You may not use this file except in compliance
+ with the License.
+
+
+
+
+ http://dojotoolkit.org/community/licensing.shtml
+
+
+
+
+ Files that are autmoatically generated.
+
+
+
+
+
+ This program is free software; you can redistribute it
+ and/or modify
+ it under the terms of the GNU
+ General Public License as published by the Free Software
+ Foundation; either version 1, or (at your option) any
+ later
+ version.
+
+
+
+
+
+
+
+ This program is free software; you can
+ redistribute it and/or modify it under the terms of the
+ GNU
+ General Public License as published by the Free Software
+ Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+
+
+
+
+
+ This program is free software: you can
+ redistribute it and/or modify it under the terms of the
+ GNU
+ General Public License as published by the Free Software
+ Foundation, either version 3 of the License, or (at your
+ option) any later version.
+
+
+
+
+
+
+ Permission is hereby granted, free of charge, to
+ any person obtaining a copy of this software and associated
+ documentation files (the \"Software\"), to deal in the
+ Software
+ without restriction, including without limitation the rights
+ to
+ use, copy, modify, merge, publish, distribute, sublicense,
+ and/or sell copies of the Software, and to permit persons to
+ whom the Software is furnished to do so, subject to the
+ following conditions: The above copyright notice and this
+ permission notice shall be included in all copies or
+ substantial
+ portions of the Software. THE SOFTWARE IS PROVIDED "AS IS",
+ WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ BUT
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ FOR A
+ PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ DAMAGES OR
+ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+
+
+
+ No modifications allowed
+
+ This document and translations of it may be
+ copied and furnished to others and derivative works that
+ comment
+ on or otherwise explain it or assist in its implementation
+ may
+ be prepared copied published and distributed
+
+
+
+
+
+
+ TMF854 Version 1.0
+
+
+
+
+
+
+ Note that W3C requires a NOTICE.
+ All modifications require notes.
+
+ See
+ http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231.
+
+
+ http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231
+
+
+
+
+
+
+ Note that W3CD does not allow modifications.
+
+ See
+ http://www.w3.org/Consortium/Legal/2002/copyright-documents-20021231.
+
+ http://www.w3.org/Consortium/Legal/2002/copyright-documents-20021231
+
+
+
+
+
+
+
+
+ Redistribution and use in source and binary forms, with
+ or without modification, are permitted provided that the
+ following conditions are met:
+
+ 1. Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the
+ above copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+ 3. Neither the name of the copyright holder nor the
+ names of its contributors may be used to endorse or
+ promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ OF SUCH DAMAGE.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apache-rat-core/src/main/resources/org/apache/rat/generation-keywords.txt b/apache-rat-core/src/main/resources/org/apache/rat/generation-keywords.txt
new file mode 100644
index 000000000..f9314a659
--- /dev/null
+++ b/apache-rat-core/src/main/resources/org/apache/rat/generation-keywords.txt
@@ -0,0 +1,26 @@
+Generated text no license required
+generated by Cayenne
+Generated By:JJTree
+Generated By:JavaCC
+THIS FILE IS AUTOMATICALLY GENERATED
+NOTE: this file is autogenerated by XBeans
+This file was automatically generated by
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+# Microsoft Developer Studio Generated NMAKE File
+# Microsoft Developer Studio Generated Build File
+Generated from configure.ac by autoheader
+generated automatically by aclocal
+build.xml generated by maven from project.xml
+This file was generated by
+This file has been automatically generated.
+Automatically generated - do not modify!
+Javadoc style sheet
+SOURCE FILE GENERATATED
+Generated by the Batik
+this file is autogenerated
+This class was autogenerated
+Generated by Maven
+Autogenerated by Thrift
+DO NOT EDIT THIS FILE - it is machine generated
+This class was generated by
+Generated by javadoc
\ No newline at end of file
diff --git a/apache-rat-core/src/test/java/org/apache/rat/DefaultsTest.java b/apache-rat-core/src/test/java/org/apache/rat/DefaultsTest.java
new file mode 100644
index 000000000..ad4ebe5c9
--- /dev/null
+++ b/apache-rat-core/src/test/java/org/apache/rat/DefaultsTest.java
@@ -0,0 +1,51 @@
+/*
+ * 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;
+
+
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.Arrays;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.apache.rat.license.ILicense;
+import org.apache.rat.license.LicenseSetFactory.LicenseFilter;
+import org.junit.jupiter.api.Test;
+
+
+public class DefaultsTest {
+ private static final String[] FAMILIES = { "BSD-3", "GEN ", "AL ", "OASIS", "W3CD ", "W3C ", "GPL1 ",
+ "GPL2 ", "GPL3 ", "MIT ", "CDDL1" };
+
+ @Test
+ public void defaultConfigTest() {
+ Defaults defaults = Defaults.builder().build();
+
+ Set licenses = defaults.getLicenses(LicenseFilter.all);
+
+ Set names = new TreeSet<>();
+ licenses.forEach(x -> names.add(x.getLicenseFamily().getFamilyCategory()));
+ assertEquals(FAMILIES.length, names.size());
+ names.removeAll(Arrays.asList(FAMILIES));
+ assertTrue(names.isEmpty());
+ }
+}
diff --git a/apache-rat-core/src/test/java/org/apache/rat/ReportConfigurationTest.java b/apache-rat-core/src/test/java/org/apache/rat/ReportConfigurationTest.java
new file mode 100644
index 000000000..30acdc4cc
--- /dev/null
+++ b/apache-rat-core/src/test/java/org/apache/rat/ReportConfigurationTest.java
@@ -0,0 +1,587 @@
+/*
+ * 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;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.fail;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.SortedSet;
+import java.util.function.Function;
+
+import org.apache.commons.io.filefilter.AndFileFilter;
+import org.apache.commons.io.filefilter.DirectoryFileFilter;
+import org.apache.commons.io.filefilter.FalseFileFilter;
+import org.apache.commons.io.function.IOSupplier;
+import org.apache.rat.ReportConfiguration.NoCloseOutputStream;
+import org.apache.rat.analysis.IHeaderMatcher;
+import org.apache.rat.config.AddLicenseHeaders;
+import org.apache.rat.configuration.ConfigurationReaderTest;
+import org.apache.rat.license.ILicense;
+import org.apache.rat.license.ILicenseFamily;
+import org.apache.rat.license.LicenseSetFactory.LicenseFilter;
+import org.apache.rat.report.IReportable;
+import org.apache.rat.testhelpers.TestingLicense;
+import org.apache.rat.utils.Log;
+import org.apache.rat.utils.Log.Level;
+import org.apache.rat.utils.ReportingSet.Options;
+import org.apache.rat.walker.NameBasedHiddenFileFilter;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+
+public class ReportConfigurationTest {
+
+ private ReportConfiguration underTest;
+ private LoggingCapture log;
+
+ @BeforeEach
+ public void setup() {
+ log = new LoggingCapture();
+ underTest = new ReportConfiguration(log);
+ }
+
+ @Test
+ public void testAddAndRemoveApproveLicenseCategories() {
+ List expected = new ArrayList<>();
+ underTest.addLicense( new TestingLicense("Unapproved"));
+
+ assertThat(underTest.getApprovedLicenseCategories()).isEmpty();
+
+ TestingLicense license = new TestingLicense("TheCat");
+ underTest.addLicense(license);
+ underTest.addApprovedLicenseCategory(license.getFamily());
+ expected.add("TheCa");
+ SortedSet result = underTest.getApprovedLicenseCategories();
+ assertThat(expected).hasSize(result.size()).containsAll(result);
+ SortedSet families = underTest.getLicenseFamilies(LicenseFilter.approved);
+ assertThat(expected).hasSize(families.size());
+ SortedSet licenses = underTest.getLicenses(LicenseFilter.approved);
+ assertThat(expected).hasSize(licenses.size());
+
+ underTest.addLicense(new TestingLicense("ACat"));
+ underTest.addApprovedLicenseCategory("ACat");
+ expected.add("ACat ");
+ result = underTest.getApprovedLicenseCategories();
+ assertThat(expected).hasSize(result.size()).containsAll(result);
+ families = underTest.getLicenseFamilies(LicenseFilter.approved);
+ assertThat(expected).hasSize(families.size());
+ licenses = underTest.getLicenses(LicenseFilter.approved);
+ assertThat(expected).hasSize(licenses.size());
+
+ String[] cats = { "Spot ", "Felix" };
+ underTest.addLicense(new TestingLicense("Spot"));
+ underTest.addLicense(new TestingLicense("Felix"));
+ underTest.addApprovedLicenseCategories(Arrays.asList(cats));
+ expected.addAll(Arrays.asList(cats));
+ result = underTest.getApprovedLicenseCategories();
+ assertThat(expected).hasSize(result.size()).containsAll(result);
+ families = underTest.getLicenseFamilies(LicenseFilter.approved);
+ assertThat(expected).hasSize(families.size());
+ licenses = underTest.getLicenses(LicenseFilter.approved);
+ assertThat(expected).hasSize(licenses.size());
+
+ underTest.removeApprovedLicenseCategory("Spot ");
+ expected.remove("Spot ");
+ result = underTest.getApprovedLicenseCategories();
+ assertThat(expected).hasSize(result.size()).containsAll(result);
+ families = underTest.getLicenseFamilies(LicenseFilter.approved);
+ assertThat(expected).hasSize(families.size());
+ licenses = underTest.getLicenses(LicenseFilter.approved);
+ assertThat(expected).hasSize(licenses.size());
+
+ cats[0] = "TheCa";
+ underTest.removeApprovedLicenseCategories(Arrays.asList(cats));
+ expected.removeAll(Arrays.asList(cats));
+ result = underTest.getApprovedLicenseCategories();
+ assertThat(expected).hasSize(result.size()).containsAll(result);
+ families = underTest.getLicenseFamilies(LicenseFilter.approved);
+ assertThat(expected).hasSize(families.size());
+ licenses = underTest.getLicenses(LicenseFilter.approved);
+ assertThat(expected).hasSize(licenses.size()); }
+
+ @Test
+ public void testRemoveBeforeAddApproveLicenseCategories() {
+ underTest.addLicense( new TestingLicense("TheCat"));
+ assertThat(underTest.getApprovedLicenseCategories()).isEmpty();
+ assertThat(underTest.getLicenseFamilies(LicenseFilter.approved)).isEmpty();
+ assertThat(underTest.getLicenses(LicenseFilter.approved)).isEmpty();
+
+ underTest.removeApprovedLicenseCategory("TheCat");
+ assertThat(underTest.getApprovedLicenseCategories()).isEmpty();
+ assertThat(underTest.getLicenseFamilies(LicenseFilter.approved)).isEmpty();
+ assertThat(underTest.getLicenses(LicenseFilter.approved)).isEmpty();
+
+ underTest.addApprovedLicenseCategory("TheCat");
+ assertThat(underTest.getApprovedLicenseCategories()).isEmpty();
+ assertThat(underTest.getLicenseFamilies(LicenseFilter.approved)).isEmpty();
+ assertThat(underTest.getLicenses(LicenseFilter.approved)).isEmpty();
+ }
+
+ private ILicense testingLicense(String category, String name) {
+ ILicenseFamily family = ILicenseFamily.builder().setLicenseFamilyCategory(category).setLicenseFamilyName(name)
+ .build();
+ return new TestingLicense( family );
+ }
+
+ @Test
+ public void testAddLicense() {
+
+ List expected = new ArrayList<>();
+ assertThat(underTest.getLicenses(LicenseFilter.all)).isEmpty();
+
+ ILicense lic1 = testingLicense("TheCat", "TheName");
+ expected.add(lic1);
+ underTest.addLicense(lic1);
+ SortedSet result = underTest.getLicenses(LicenseFilter.all);
+ assertThat(expected).hasSize(result.size()).containsAll(result);
+
+ ILicense[] lics = { testingLicense("Spot", "Data's cat"), testingLicense("Felix", "Cartoon cat") };
+ expected.addAll(Arrays.asList(lics));
+ underTest.addLicenses(Arrays.asList(lics));
+ result = underTest.getLicenses(LicenseFilter.all);
+ assertThat(expected).hasSize(result.size()).containsAll(result);
+ }
+
+ @Test
+ public void copyrightMessageTest() {
+ assertThat(underTest.getCopyrightMessage()).isNull();
+ underTest.setCopyrightMessage("This is the message");
+ assertThat(underTest.getCopyrightMessage()).isEqualTo("This is the message");
+ }
+
+ @Test
+ public void inputFileFilterTest() {
+ FilenameFilter filter = mock(FilenameFilter.class);
+ assertThat(underTest.getInputFileFilter()).isNull();
+ underTest.setInputFileFilter(filter);
+ assertThat(underTest.getInputFileFilter()).isEqualTo(filter);
+ }
+
+ @Test
+ public void directoryFilterTest() {
+ assertThat(underTest.getDirectoryFilter()).isNotNull();
+ assertThat(underTest.getDirectoryFilter()).isExactlyInstanceOf(NameBasedHiddenFileFilter.class);
+
+ underTest.setDirectoryFilter(DirectoryFileFilter.DIRECTORY);
+ underTest.addDirectoryFilter(NameBasedHiddenFileFilter.HIDDEN);
+ assertThat(underTest.getDirectoryFilter()).isExactlyInstanceOf(AndFileFilter.class);
+
+ underTest.setDirectoryFilter(null);
+ assertThat(underTest.getDirectoryFilter()).isExactlyInstanceOf(FalseFileFilter.class);
+ }
+
+ @Test
+ public void licenseFamiliesTest() {
+ assertThat(underTest.getLicenseFamilies(LicenseFilter.all)).isEmpty();
+ assertThat(underTest.getLicenseFamilies(LicenseFilter.approved)).isEmpty();
+ assertThat(underTest.getLicenseFamilies(LicenseFilter.none)).isEmpty();
+
+ ILicense[] lics = { testingLicense("TheCat", "TheName"), testingLicense("Spot", "Data's cat"),
+ testingLicense("Felix", "Cartoon cat") };
+ underTest.addLicenses(Arrays.asList(lics));
+
+ assertThat(underTest.getLicenseFamilies(LicenseFilter.all)).hasSize(lics.length);
+ assertThat(underTest.getLicenseFamilies(LicenseFilter.approved)).isEmpty();
+ assertThat(underTest.getLicenseFamilies(LicenseFilter.none)).isEmpty();
+
+ underTest.addApprovedLicenseCategory(lics[1].getLicenseFamily());
+ assertThat(underTest.getLicenseFamilies(LicenseFilter.all)).hasSize(lics.length);
+ SortedSet result = underTest.getLicenseFamilies(LicenseFilter.approved);
+ assertThat(result).hasSize(1);
+ assertThat(result.first()).isEqualTo(lics[1].getLicenseFamily());
+ assertThat(underTest.getLicenseFamilies(LicenseFilter.none)).isEmpty();
+ }
+
+ @Test
+ public void licensesTest() {
+ assertThat(underTest.getLicenses(LicenseFilter.all)).isEmpty();
+ assertThat(underTest.getLicenses(LicenseFilter.approved)).isEmpty();
+ assertThat(underTest.getLicenses(LicenseFilter.none)).isEmpty();
+
+ ILicense[] lics = { testingLicense("TheCat", "TheName"), testingLicense("Spot", "Data's cat"),
+ testingLicense("Felix", "Cartoon cat") };
+ underTest.addLicenses(Arrays.asList(lics));
+
+ assertThat(underTest.getLicenses(LicenseFilter.all)).hasSize(lics.length);
+ assertThat(underTest.getLicenses(LicenseFilter.approved)).isEmpty();
+ assertThat(underTest.getLicenses(LicenseFilter.none)).isEmpty();
+
+ underTest.addApprovedLicenseCategory(lics[1].getLicenseFamily());
+ assertThat(underTest.getLicenses(LicenseFilter.all)).hasSize(lics.length);
+ SortedSet result = underTest.getLicenses(LicenseFilter.approved);
+ assertThat(result).hasSize(1);
+ assertThat(result.first()).isEqualTo(lics[1]);
+ assertThat(underTest.getLicenseFamilies(LicenseFilter.none)).isEmpty();
+ }
+
+ @Test
+ public void outputTest() throws IOException {
+ assertThat(underTest.getOutput().get()).isExactlyInstanceOf(NoCloseOutputStream.class);
+ assertThat(underTest.getWriter()).isNotNull();
+
+ ByteArrayOutputStream stream = new ByteArrayOutputStream();
+ underTest.setOut(() -> stream);
+ assertThat(underTest.getOutput().get()).isEqualTo(stream);
+ PrintWriter writer = underTest.getWriter().get();
+ assertThat(writer).isNotNull();
+ writer.write('a');
+ writer.flush();
+ assertThat(stream.toByteArray()[0]).isEqualTo((byte) 'a');
+ }
+
+ @Test
+ public void reportableTest() {
+ assertThat(underTest.getReportable()).isNull();
+ IReportable reportable = mock(IReportable.class);
+ underTest.setReportable(reportable);
+ assertThat(underTest.getReportable()).isEqualTo(reportable);
+ underTest.setReportable(null);
+ assertThat(underTest.getReportable()).isNull();
+ }
+
+ @Test
+ public void stylesheetTest() throws IOException, URISyntaxException {
+ URL url = this.getClass().getResource("ReportConfigurationTestFile");
+
+ assertThat(underTest.getStyleSheet()).isNull();
+ InputStream stream = mock(InputStream.class);
+ underTest.setStyleSheet(() -> stream);
+ assertThat(underTest.getStyleSheet().get()).isEqualTo(stream);
+ IOSupplier sup = null;
+ underTest.setStyleSheet(sup);
+ assertThat(underTest.getStyleSheet()).isNull();
+
+ File file = mock(File.class);
+ when(file.toURI()).thenReturn(url.toURI());
+ underTest.setStyleSheet(file);
+ BufferedReader d = new BufferedReader(new InputStreamReader(underTest.getStyleSheet().get()));
+ assertThat(d.readLine()).isEqualTo("/*");
+ assertThat(d.readLine()).isEqualTo(" * Licensed to the Apache Software Foundation (ASF) under one *");
+ }
+
+ @Test
+ public void testFlags() {
+ assertThat(underTest.isAddingLicenses()).isFalse();
+ assertThat(underTest.isAddingLicensesForced()).isFalse();
+ assertThat(underTest.isStyleReport()).isTrue();
+
+ underTest.setAddLicenseHeaders(AddLicenseHeaders.TRUE);
+ assertThat(underTest.isAddingLicenses()).isTrue();
+ assertThat(underTest.isAddingLicensesForced()).isFalse();
+ assertThat(underTest.isStyleReport()).isTrue();
+
+ underTest.setAddLicenseHeaders(AddLicenseHeaders.FALSE);
+ assertThat(underTest.isAddingLicenses()).isFalse();
+ assertThat(underTest.isAddingLicensesForced()).isFalse();
+ assertThat(underTest.isStyleReport()).isTrue();
+
+ underTest.setAddLicenseHeaders(AddLicenseHeaders.FORCED);
+ assertThat(underTest.isAddingLicenses()).isTrue();
+ assertThat(underTest.isAddingLicensesForced()).isTrue();
+ assertThat(underTest.isStyleReport()).isTrue();
+
+ underTest.setAddLicenseHeaders(AddLicenseHeaders.FALSE);
+ underTest.setStyleReport(false);
+ assertThat(underTest.isAddingLicenses()).isFalse();
+ assertThat(underTest.isAddingLicensesForced()).isFalse();
+ assertThat(underTest.isStyleReport()).isFalse();
+
+ underTest.setStyleReport(true);
+ assertThat(underTest.isAddingLicenses()).isFalse();
+ assertThat(underTest.isAddingLicensesForced()).isFalse();
+ assertThat(underTest.isStyleReport()).isTrue();
+ }
+
+ @Test
+ public void testValidate() {
+ final StringBuilder sb = new StringBuilder();
+ try {
+ underTest.validate(s -> sb.append(s));
+ fail("should have thrown ConfigurationException");
+ } catch (ConfigurationException e) {
+ assertThat(e.getMessage()).isEqualTo("Reportable may not be null");
+ assertThat(sb.length()).isEqualTo(0);
+ }
+
+ underTest.setReportable(mock(IReportable.class));
+ try {
+ underTest.validate(s -> sb.append(s));
+ fail("should have thrown ConfigurationException");
+ } catch (ConfigurationException e) {
+ assertThat(e.getMessage()).isEqualTo("You must specify at least one license");
+ assertThat(sb.length()).isEqualTo(0);
+ }
+
+ underTest.addLicense(testingLicense("valid", "Validation testing license"));
+ try {
+ underTest.validate(s -> sb.append(s));
+ fail("should have thrown ConfigurationException");
+ } catch (ConfigurationException e) {
+ assertThat(e.getMessage()).isEqualTo("Stylesheet must be specified if report styling is selected");
+ assertThat(sb.length()).isEqualTo(0);
+ }
+
+ underTest.setStyleSheet(()->mock(InputStream.class));
+ underTest.setStyleReport(false);
+ underTest.validate(s -> sb.append(s));
+ assertThat(sb.toString()).isEqualTo("Ignoring stylesheet because styling is not selected");
+
+ final StringBuilder sb2 = new StringBuilder();
+ underTest.setStyleReport(true);
+ underTest.validate(s -> sb2.append(s));
+ assertThat(sb2.length()).isEqualTo(0);
+ }
+
+ @Test
+ public void testSetOut() throws IOException {
+ ReportConfiguration config = new ReportConfiguration(log);
+ try (OutputStreamIntercepter osi = new OutputStreamIntercepter()) {
+ config.setOut(() -> osi);
+ assertThat(osi.closeCount).isEqualTo(0);
+ try (OutputStream os = config.getOutput().get()) {
+ assertThat(osi.closeCount).isEqualTo(0);
+ }
+ assertThat(osi.closeCount).isEqualTo(1);
+ try (OutputStream os = config.getOutput().get()) {
+ assertThat(osi.closeCount).isEqualTo(1);
+ }
+ assertThat(osi.closeCount).isEqualTo(2);
+ }
+ }
+
+ @Test
+ public void logFamilyCollisionTest() {
+ // setup
+ underTest.addFamily(ILicenseFamily.builder().setLicenseFamilyCategory("CAT").setLicenseFamilyName("name"));
+ assertFalse(log.captured.toString().contains("CAT"));
+
+ // verify default collision logs WARNING
+ underTest.addFamily(ILicenseFamily.builder().setLicenseFamilyCategory("CAT").setLicenseFamilyName("name2"));
+ assertTrue(log.captured.toString().contains("WARN"), ()->"default value not WARN");
+ assertTrue(log.captured.toString().contains("CAT"), ()->"'CAT' not found");
+
+ // verify level setting works.
+ for (Level l : Level.values()) {
+ log.clear();
+ underTest.logFamilyCollisions(l);
+ underTest.addFamily(ILicenseFamily.builder().setLicenseFamilyCategory("CAT").setLicenseFamilyName("name2"));
+ assertTrue(log.captured.toString().contains("CAT"), ()->"'CAT' not found");
+ assertTrue(log.captured.toString().contains(l.name()), ()->"logging not set to "+l);
+ }
+
+ }
+
+ @Test
+ public void familyDuplicateOptionsTest() {
+ underTest.addFamily(ILicenseFamily.builder().setLicenseFamilyCategory("CAT").setLicenseFamilyName("name"));
+ assertFalse(log.captured.toString().contains("CAT"));
+
+ // verify default second setting ignores change
+ underTest.addFamily(ILicenseFamily.builder().setLicenseFamilyCategory("CAT").setLicenseFamilyName("name2"));
+ assertTrue(log.captured.toString().contains("CAT"));
+ assertEquals("name", underTest.getLicenseFamilies(LicenseFilter.all).stream()
+ .filter(s -> s.getFamilyCategory().equals("CAT ")).map(s -> s.getFamilyName()).findFirst().get());
+
+ underTest.familyDuplicateOption(Options.OVERWRITE);
+ // verify second setting ignores change
+ underTest.addFamily(ILicenseFamily.builder().setLicenseFamilyCategory("CAT").setLicenseFamilyName("name2"));
+ assertTrue(log.captured.toString().contains("CAT"));
+ assertEquals("name2", underTest.getLicenseFamilies(LicenseFilter.all).stream()
+ .filter(s -> s.getFamilyCategory().equals("CAT ")).map(s -> s.getFamilyName()).findFirst().get());
+
+ // verify fail throws exception
+ underTest.familyDuplicateOption(Options.FAIL);
+ assertThrows( IllegalArgumentException.class, ()->underTest.addFamily(ILicenseFamily.builder().setLicenseFamilyCategory("CAT").setLicenseFamilyName("name2")));
+
+ underTest.familyDuplicateOption(Options.IGNORE);
+ }
+
+
+ @Test
+ public void logLicenseCollisionTest() {
+ // setup
+ ILicenseFamily family = ILicenseFamily.builder().setLicenseFamilyCategory("CAT").setLicenseFamilyName("family name").build();
+ IHeaderMatcher matcher = Mockito.mock(IHeaderMatcher.class);
+ when(matcher.getId()).thenReturn("Macher ID");
+ underTest.addFamily(family);
+ underTest.addLicense(ILicense.builder().setId("ID").setName("license name").setLicenseFamilyCategory(family.getFamilyCategory())
+ .setMatcher( matcher ).build(underTest.getLicenseFamilies(LicenseFilter.all)));
+
+ // verify default collistion logs WARN
+ underTest.addLicense(ILicense.builder().setId("ID").setName("license name2").setLicenseFamilyCategory(family.getFamilyCategory())
+ .setMatcher( matcher ).build(underTest.getLicenseFamilies(LicenseFilter.all)));
+ assertTrue(log.captured.toString().contains("WARN"));
+
+ log.clear();
+ underTest.logLicenseCollisions(Level.ERROR);
+
+ // verify second setting changes logs issue
+ underTest.addLicense(ILicense.builder().setId("ID").setName("license name2").setLicenseFamilyCategory(family.getFamilyCategory())
+ .setMatcher( matcher ).build(underTest.getLicenseFamilies(LicenseFilter.all)));
+ assertTrue(log.captured.toString().contains("ERROR"));
+
+ }
+
+ @Test
+ public void licenseDuplicateOptionsTest() {
+ // setup
+ ILicenseFamily family = ILicenseFamily.builder().setLicenseFamilyCategory("CAT").setLicenseFamilyName("family name").build();
+ IHeaderMatcher matcher = Mockito.mock(IHeaderMatcher.class);
+ when(matcher.getId()).thenReturn("Macher ID");
+ underTest.addFamily(family);
+ Function makeLicense = s -> ILicense.builder().setId("ID").setName(s).setLicenseFamilyCategory(family.getFamilyCategory())
+ .setMatcher( matcher ).build(underTest.getLicenseFamilies(LicenseFilter.all));
+
+ underTest.addLicense(makeLicense.apply("license name"));
+
+ // verify default second setting ignores change
+ underTest.addLicense(makeLicense.apply("license name2"));
+ assertTrue(log.captured.toString().contains("WARN"));
+ assertEquals("license name",
+ underTest.getLicenses(LicenseFilter.all).stream().map(ILicense::getName).findFirst().get());
+
+ underTest.licenseDuplicateOption(Options.OVERWRITE);
+ underTest.addLicense(makeLicense.apply("license name2"));
+ assertEquals("license name2",
+ underTest.getLicenses(LicenseFilter.all).stream().map(ILicense::getName).findFirst().get());
+
+
+ // verify fail throws exception
+ underTest.licenseDuplicateOption(Options.FAIL);
+ assertThrows( IllegalArgumentException.class, ()-> underTest.addLicense(makeLicense.apply("another name")));
+
+ }
+
+ /**
+ * Validates that the configuration contains the default approved licenses.
+ * @param config The configuration to test.
+ */
+ public static void validateDefaultApprovedLicenses(ReportConfiguration config) {
+ validateDefaultApprovedLicenses(config, 0);
+ }
+
+ /**
+ * Validates that the configuration contains the default approved licenses.
+ * @param config The configuration to test.
+ */
+ public static void validateDefaultApprovedLicenses(ReportConfiguration config, int additionalIdCount) {
+ assertThat(config.getApprovedLicenseCategories()).hasSize(ConfigurationReaderTest.EXPECTED_IDS.length + additionalIdCount);
+ for (String s : ConfigurationReaderTest.EXPECTED_IDS) {
+ assertThat(config.getApprovedLicenseCategories()).contains(ILicenseFamily.makeCategory(s));
+ }
+ }
+
+
+ /**
+ * Validates that the configruation contains the default license families.
+ * @param config the configuration to test.
+ */
+ public static void validateDefaultLicenseFamilies(ReportConfiguration config, String...additionalIds) {
+ assertThat(config.getLicenseFamilies(LicenseFilter.all)).hasSize(ConfigurationReaderTest.EXPECTED_IDS.length + additionalIds.length);
+ List expected = new ArrayList<>();
+ expected.addAll(Arrays.asList(ConfigurationReaderTest.EXPECTED_IDS));
+ expected.addAll(Arrays.asList(additionalIds));
+ for (ILicenseFamily family : config.getLicenseFamilies(LicenseFilter.all)) {
+ assertThat(expected).contains(family.getFamilyCategory().trim());
+ }
+ }
+
+ /**
+ * Validates that the configuration contains the default licenses.
+ * @param config the configuration to test.
+ */
+ public static void validateDefaultLicenses(ReportConfiguration config, String...additionalLicenses) {
+ assertThat(config.getLicenses(LicenseFilter.all)).hasSize(ConfigurationReaderTest.EXPECTED_LICENSES.length + additionalLicenses.length);
+ List expected = new ArrayList<>();
+ expected.addAll(Arrays.asList(ConfigurationReaderTest.EXPECTED_LICENSES));
+ expected.addAll(Arrays.asList(additionalLicenses));
+ for (ILicense license : config.getLicenses(LicenseFilter.all)) {
+ assertThat(expected).contains(license.getId());
+ }
+ }
+
+ /**
+ * Validates that the configuration matches the default.
+ * @param config The configuration to test.
+ */
+ public static void validateDefault(ReportConfiguration config) {
+ assertThat(config.isAddingLicenses()).isFalse();
+ assertThat(config.isAddingLicensesForced()).isFalse();
+ assertThat(config.getCopyrightMessage()).isNull();
+ assertThat(config.getInputFileFilter()).isNull();
+ assertThat(config.isStyleReport()).isTrue();
+ assertThat(config.getStyleSheet()).isNotNull().withFailMessage("Stylesheet should not be null");
+ assertThat(config.getDirectoryFilter()).isNotNull().withFailMessage("Directory filter should not be null");
+ assertThat(config.getDirectoryFilter()).isExactlyInstanceOf(NameBasedHiddenFileFilter.class);
+
+ validateDefaultApprovedLicenses(config);
+ validateDefaultLicenseFamilies(config);
+ validateDefaultLicenses(config);
+ }
+
+ private class LoggingCapture implements Log {
+
+ StringBuilder captured = new StringBuilder();
+
+ public void clear() {
+ captured = new StringBuilder();
+ }
+
+ @Override
+ public void log(Level level, String msg) {
+ captured.append( String.format("%s: %s%n", level, msg));
+ }
+
+ }
+
+ static class OutputStreamIntercepter extends OutputStream {
+
+ int closeCount = 0;
+
+ @Override
+ public void write(int arg0) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void close() {
+ ++closeCount;
+ }
+ }
+}
diff --git a/apache-rat-core/src/test/java/org/apache/rat/ReportTest.java b/apache-rat-core/src/test/java/org/apache/rat/ReportTest.java
index 444a61ca5..8632e0294 100644
--- a/apache-rat-core/src/test/java/org/apache/rat/ReportTest.java
+++ b/apache-rat-core/src/test/java/org/apache/rat/ReportTest.java
@@ -18,128 +18,72 @@
*/
package org.apache.rat;
-import org.apache.rat.analysis.util.HeaderMatcherMultiplexer;
-import org.apache.rat.test.utils.Resources;
-import org.apache.rat.walker.DirectoryWalker;
-import org.junit.Test;
+
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
-import java.io.StringWriter;
+import java.io.PrintStream;
+import java.nio.charset.StandardCharsets;
import java.util.Arrays;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.DefaultParser;
+import org.apache.commons.cli.ParseException;
+import org.apache.commons.io.FileUtils;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
public class ReportTest {
- private static final String NL = System.getProperty("line.separator");
- private static final String PARAGRAPH = "*****************************************************";
- private static final String FILE_PARAGRAPH = "=====================================================";
-
- private static final String HEADER =
- NL +
- PARAGRAPH + NL +//
- "Summary" + NL +//
- "-------" + NL +//
- "Generated at: ";
-
- private static String getElementsReports(String pElementsPath) {
- return
- NL + "Notes: 2" + NL +//
- "Binaries: 2" + NL +//
- "Archives: 1" + NL +//
- "Standards: 7" + NL +//
- "" + NL +//
- "Apache Licensed: 4" + NL +//
- "Generated Documents: 0" + NL +//
- "" + NL +//
- "JavaDocs are generated, thus a license header is optional." + NL +//
- "Generated files do not require license headers." + NL +//
- "" + NL +//
- "2 Unknown Licenses" + NL +//
- "" + NL +//
- PARAGRAPH + NL +//
- "" + NL +//
- "Files with unapproved licenses:" + NL +//
- "" + NL +//
- " " + pElementsPath + "/Source.java" + NL +//
- " " + pElementsPath + "/sub/Empty.txt" + NL +//
- "" + NL +//
- PARAGRAPH + NL +//
- "" + NL +//
- "Archives:" + NL +//
- "" + NL +//
- " + " + pElementsPath + "/dummy.jar" + NL +//
- " " + NL +//
- PARAGRAPH + NL +//
- " Files with Apache License headers will be marked AL" + NL +//
- " Binary files (which do not require any license headers) will be marked B" + NL +//
- " Compressed archives will be marked A" + NL +//
- " Notices, licenses etc. will be marked N" + NL +//
- " MIT " + pElementsPath + "/ILoggerFactory.java" + NL +//
- " B " + pElementsPath + "/Image.png" + NL +//
- " N " + pElementsPath + "/LICENSE" + NL +//
- " N " + pElementsPath + "/NOTICE" + NL +//
- " !????? " + pElementsPath + "/Source.java" + NL +//
- " AL " + pElementsPath + "/Text.txt" + NL +//
- " AL " + pElementsPath + "/TextHttps.txt" + NL +//
- " AL " + pElementsPath + "/Xml.xml" + NL +//
- " AL " + pElementsPath + "/buildr.rb" + NL +//
- " A " + pElementsPath + "/dummy.jar" + NL +//
- " B " + pElementsPath + "/plain.json" + NL +//
- " !????? " + pElementsPath + "/sub/Empty.txt" + NL +//
- " " + NL +//
- PARAGRAPH + NL +//
- NL +//
- " Printing headers for text files without a valid license header..." + NL +//
- " " + NL +//
- FILE_PARAGRAPH + NL +//
- "== File: " + pElementsPath + "/Source.java" + NL +//
- FILE_PARAGRAPH + NL + //
- "package elements;" + NL +//
- "" + NL +//
- "/*" + NL +//
- " * This file does intentionally *NOT* contain an AL license header," + NL +//
- " * because it is used in the test suite." + NL +//
- " */" + NL +//
- "public class Source {" + NL +//
- "" + NL +//
- "}" + NL +//
- "" + NL +//
- FILE_PARAGRAPH + NL +//
- "== File: " + pElementsPath + "/sub/Empty.txt" + NL +//
- FILE_PARAGRAPH + NL +//
- NL;
+ @Test
+ public void parseExclusionsForCLIUsage() {
+ final FilenameFilter filter = Report
+ .parseExclusions(Arrays.asList("", " # foo/bar", "foo", "##", " ./foo/bar"));
+ assertNotNull(filter);
}
-
+
@Test
- public void plainReportWithArchivesAndUnapprovedLicenses() throws Exception {
- StringWriter out = new StringWriter();
- HeaderMatcherMultiplexer matcherMultiplexer = new HeaderMatcherMultiplexer(Defaults.DEFAULT_MATCHERS);
- final String elementsPath = Resources.getResourceDirectory("elements/Source.java");
- final ReportConfiguration configuration = new ReportConfiguration();
- configuration.setApproveDefaultLicenses(true);
- configuration.setHeaderMatcher(matcherMultiplexer);
- Report.report(out, new DirectoryWalker(new File(elementsPath)),
- Defaults.getPlainStyleSheet(), configuration);
-
- String result = out.getBuffer().toString();
- assertTrue("'Generated at' is present in " + result,
- result.startsWith(HEADER));
-
- final int generatedAtLineEnd = result.indexOf(NL, HEADER.length());
+ public void testDefaultConfiguration() throws ParseException, IOException {
+ String[] empty = {};
+ CommandLine cl = new DefaultParser().parse(Report.buildOptions(), empty);
+ ReportConfiguration config = Report.createConfiguration("", cl);
+ ReportConfigurationTest.validateDefault(config);
+ }
- final String elementsReports = getElementsReports(elementsPath);
- assertEquals("Report created was: " + result,
- elementsReports,
- result.substring(generatedAtLineEnd + NL.length()));
+ @Test
+ public void testOutputOption() throws Exception {
+ CommandLine cl = new DefaultParser().parse(Report.buildOptions(), new String[]{ "-o", "target/test" });
+ ReportConfiguration config = Report.createConfiguration("target/test-classes/elements", cl);
+ Reporter.report(config);
+ File output = new File("target/test");
+ assertTrue(output.exists());
+ String content = FileUtils.readFileToString(output, StandardCharsets.UTF_8);
+ assertTrue(content.contains("2 Unknown Licenses"));
+ assertTrue(content.contains("target/test-classes/elements/Source.java"));
+ assertTrue(content.contains("target/test-classes/elements/sub/Empty.txt"));
}
@Test
- public void parseExclusionsForCLIUsage() throws IOException {
- final FilenameFilter filter = Report.parseExclusions(Arrays.asList("", " # foo/bar", "foo", "##", " ./foo/bar"));
- assertNotNull(filter);
+ public void testDefaultOutput() throws Exception {
+
+ PrintStream origin = System.out;
+ try {
+ File output = new File("target/sysout");
+ System.setOut(new PrintStream(output));
+ CommandLine cl = new DefaultParser().parse(Report.buildOptions(), new String[]{});
+ ReportConfiguration config = Report.createConfiguration("target/test-classes/elements", cl);
+ Reporter.report(config);
+ assertTrue(output.exists());
+ String content = FileUtils.readFileToString(output, StandardCharsets.UTF_8);
+ assertTrue(content.contains("2 Unknown Licenses"));
+ assertTrue(content.contains("target/test-classes/elements/Source.java"));
+ assertTrue(content.contains("target/test-classes/elements/sub/Empty.txt"));
+ } finally {
+ System.setOut(origin);
+ }
}
+
}
diff --git a/apache-rat-core/src/test/java/org/apache/rat/ReportTransformerTest.java b/apache-rat-core/src/test/java/org/apache/rat/ReportTransformerTest.java
index e9f6338aa..96102864c 100644
--- a/apache-rat-core/src/test/java/org/apache/rat/ReportTransformerTest.java
+++ b/apache-rat-core/src/test/java/org/apache/rat/ReportTransformerTest.java
@@ -19,14 +19,15 @@
package org.apache.rat;
import org.apache.rat.test.utils.Resources;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.StringReader;
import java.io.StringWriter;
-import static org.junit.Assert.assertNotNull;
public class ReportTransformerTest {
diff --git a/apache-rat-core/src/test/java/org/apache/rat/ReporterTest.java b/apache-rat-core/src/test/java/org/apache/rat/ReporterTest.java
new file mode 100644
index 000000000..d675b6994
--- /dev/null
+++ b/apache-rat-core/src/test/java/org/apache/rat/ReporterTest.java
@@ -0,0 +1,140 @@
+/*
+ * 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;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.util.regex.Pattern;
+
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathFactory;
+
+import org.apache.commons.io.filefilter.HiddenFileFilter;
+import org.apache.rat.test.utils.Resources;
+import org.apache.rat.testhelpers.XmlUtils;
+import org.apache.rat.utils.DefaultLog;
+import org.apache.rat.walker.DirectoryWalker;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.NodeList;
+
+/**
+ * Tests the output of the Reporter.
+ */
+public class ReporterTest {
+
+ @Test
+ public void xmlReportTest() throws Exception {
+ Defaults defaults = Defaults.builder().build();
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+
+ final String elementsPath = Resources.getResourceDirectory("elements/Source.java");
+ final ReportConfiguration configuration = new ReportConfiguration(DefaultLog.INSTANCE);
+ configuration.setStyleReport(false);
+ configuration.setFrom(defaults);
+ configuration.setReportable(new DirectoryWalker(new File(elementsPath), HiddenFileFilter.HIDDEN));
+ configuration.setOut(() -> out);
+ Reporter.report(configuration);
+ Document doc = XmlUtils.toDom(new ByteArrayInputStream(out.toByteArray()));
+
+ XPath xPath = XPathFactory.newInstance().newXPath();
+
+ XmlUtils.getNode(doc, xPath, "/rat-report[@timestamp]");
+
+ XmlUtils.checkNode(doc, xPath, "src/test/resources/elements/ILoggerFactory.java", "MIT", "true", "standard");
+ XmlUtils.checkNode(doc, xPath, "src/test/resources/elements/Image.png", null, null, "binary");
+ XmlUtils.checkNode(doc, xPath, "src/test/resources/elements/LICENSE", null, null, "notice");
+ XmlUtils.checkNode(doc, xPath, "src/test/resources/elements/NOTICE", null, null, "notice");
+ XmlUtils.checkNode(doc, xPath, "src/test/resources/elements/Source.java", "?????", "false", "standard");
+ XmlUtils.checkNode(doc, xPath, "src/test/resources/elements/Text.txt", "AL", "true", "standard");
+ XmlUtils.checkNode(doc, xPath, "src/test/resources/elements/TextHttps.txt", "AL", "true", "standard");
+ XmlUtils.checkNode(doc, xPath, "src/test/resources/elements/Xml.xml", "AL", "true", "standard");
+ XmlUtils.checkNode(doc, xPath, "src/test/resources/elements/buildr.rb", "AL", "true", "standard");
+ XmlUtils.checkNode(doc, xPath, "src/test/resources/elements/dummy.jar", null, null, "archive");
+ XmlUtils.checkNode(doc, xPath, "src/test/resources/elements/plain.json", null, null, "binary");
+ XmlUtils.checkNode(doc, xPath, "src/test/resources/elements/sub/Empty.txt", "?????", "false", "standard");
+
+ NodeList nodeList = (NodeList) xPath.compile("/rat-report/resource").evaluate(doc, XPathConstants.NODESET);
+ assertEquals(12, nodeList.getLength());
+
+ }
+
+ private static final String NL = System.getProperty("line.separator");
+ private static final String PARAGRAPH = "*****************************************************";
+ private static final String HEADER = NL + PARAGRAPH + NL + //
+ "Summary" + NL + //
+ "-------" + NL + //
+ "Generated at: ";
+
+ @Test
+ public void plainReportWithArchivesAndUnapprovedLicenses() throws Exception {
+ Defaults defaults = Defaults.builder().build();
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+
+ final String elementsPath = Resources.getResourceDirectory("elements/Source.java");
+ final ReportConfiguration configuration = new ReportConfiguration(DefaultLog.INSTANCE);
+ configuration.setFrom(defaults);
+ configuration.setReportable(new DirectoryWalker(new File(elementsPath), HiddenFileFilter.HIDDEN));
+ configuration.setOut(() -> out);
+ Reporter.report(configuration);
+
+ out.flush();
+ String document = out.toString();
+
+ assertTrue(document.startsWith(HEADER), "'Generated at' is present in " + document );
+
+ // final int generatedAtLineEnd = document.indexOf(NL, HEADER.length());
+ find("^Notes: 2$", document);
+ find("^Binaries: 2$", document);
+ find("^Archives: 1$", document);
+ find("^Standards: 7$", document);
+ find("^Apache Licensed: 4$", document);
+ find("^Generated Documents: 0$", document);
+ find("^2 Unknown Licenses$", document);
+ find("^Files with unapproved licenses:\\s+"
+ + "src/test/resources/elements/Source.java\\s+"
+ + "src/test/resources/elements/sub/Empty.txt\\s",
+ document);
+ find("^Archives:\\s+" + "\\+ src/test/resources/elements/dummy.jar\\s*", document);
+ find("MIT\\s+src/test/resources/elements/ILoggerFactory.java", document);
+ find("B\\s+src/test/resources/elements/Image.png", document);
+ find("N\\s+src/test/resources/elements/LICENSE", document);
+ find("N\\s+src/test/resources/elements/NOTICE", document);
+ find("!\\Q?????\\E\\s+src/test/resources/elements/Source.java", document);
+ find("AL\\s+src/test/resources/elements/Text.txt", document);
+ find("AL\\s+src/test/resources/elements/TextHttps.txt", document);
+ find("AL\\s+src/test/resources/elements/Xml.xml", document);
+ find("AL\\s+src/test/resources/elements/buildr.rb", document);
+ find("A\\s+src/test/resources/elements/dummy.jar", document);
+ find("B\\s+src/test/resources/elements/plain.json", document);
+ find("!\\Q?????\\E\\s+src/test/resources/elements/sub/Empty.txt", document);
+ find("== File: src/test/resources/elements/sub/Empty.txt", document);
+ }
+
+ private void find(String pattern, String document) {
+ assertTrue(
+ Pattern.compile(pattern, Pattern.MULTILINE).matcher(document).find(), () ->String.format("Could not find '%s'", pattern));
+ }
+}
diff --git a/apache-rat-core/src/test/java/org/apache/rat/analysis/AnalyserFactoryTest.java b/apache-rat-core/src/test/java/org/apache/rat/analysis/AnalyserFactoryTest.java
index 30d3365f7..3d5f87ec6 100644
--- a/apache-rat-core/src/test/java/org/apache/rat/analysis/AnalyserFactoryTest.java
+++ b/apache-rat-core/src/test/java/org/apache/rat/analysis/AnalyserFactoryTest.java
@@ -18,100 +18,113 @@
*/
package org.apache.rat.analysis;
-import org.apache.rat.api.Document;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.StringWriter;
+import java.util.Arrays;
+
+import org.apache.rat.analysis.IHeaderMatcher.State;
import org.apache.rat.document.IDocumentAnalyser;
import org.apache.rat.document.impl.MonolithicFileDocument;
+import org.apache.rat.license.ILicense;
import org.apache.rat.report.claim.impl.xml.SimpleXmlClaimReporter;
import org.apache.rat.report.xml.writer.impl.base.XmlWriter;
import org.apache.rat.test.utils.Resources;
-import org.junit.Before;
-import org.junit.Test;
+import org.apache.rat.utils.DefaultLog;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
-import java.io.StringWriter;
-
-import static org.junit.Assert.assertEquals;
public class AnalyserFactoryTest {
- private static final IHeaderMatcher MATCHES_NOTHING_MATCHER = new IHeaderMatcher() {
- public boolean match(Document subject, String line) throws RatHeaderAnalysisException {
- return false;
- }
+ private static ILicense MATCHES_NOTHING_MATCHER = mock(ILicense.class);
- public void reset() {
- }
- };
+ static {
+ when(MATCHES_NOTHING_MATCHER.matches(any())).thenReturn(State.f);
+ when(MATCHES_NOTHING_MATCHER.currentState()).thenReturn(State.f);
+ when(MATCHES_NOTHING_MATCHER.finalizeState()).thenReturn(State.f);
+ }
private StringWriter out;
private SimpleXmlClaimReporter reporter;
private IDocumentAnalyser analyser;
- @Before
+ @BeforeEach
public void setUp() throws Exception {
out = new StringWriter();
final XmlWriter writer = new XmlWriter(out);
reporter = new SimpleXmlClaimReporter(writer);
- analyser = DefaultAnalyserFactory.createDefaultAnalyser(MATCHES_NOTHING_MATCHER);
+ analyser = DefaultAnalyserFactory.createDefaultAnalyser(DefaultLog.INSTANCE, Arrays.asList(MATCHES_NOTHING_MATCHER));
}
@Test
public void standardTypeAnalyser() throws Exception {
- final MonolithicFileDocument document = new MonolithicFileDocument(Resources.getResourceFile("/elements/Text.txt"));
+ final MonolithicFileDocument document = new MonolithicFileDocument(
+ Resources.getResourceFile("/elements/Text.txt"));
analyser.analyse(document);
reporter.report(document);
- assertEquals("Open standard element", //
- "/*\n" +
- " * Licensed to the Apache Software Foundation (ASF) under one\n" +
- " * or more contributor license agreements. See the NOTICE file\n" +
- " * distributed with this work for additional information\n" +
- " * regarding copyright ownership. The ASF licenses this file\n" +
- " * to you under the Apache License, Version 2.0 (the \"License\");\n" +
- " * you may not use this file except in compliance with the License.\n" +
- " * You may obtain a copy of the License at\n" +
- " *\n" +
- " * http://www.apache.org/licenses/LICENSE-2.0\n" +
- " *\n" +
- " * Unless required by applicable law or agreed to in writing,\n" +
- " * software distributed under the License is distributed on an\n" +
- " * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n" +
- " * KIND, either express or implied. See the License for the\n" +
- " * specific language governing permissions and limitations\n" +
- " * under the License. \n" +
- " */\n" +
- "\n" +
- " \n" +
- " ", out.toString());
+ assertEquals( //
+ "/*\n"
+ + " * Licensed to the Apache Software Foundation (ASF) under one\n"
+ + " * or more contributor license agreements. See the NOTICE file\n"
+ + " * distributed with this work for additional information\n"
+ + " * regarding copyright ownership. The ASF licenses this file\n"
+ + " * to you under the Apache License, Version 2.0 (the \"License\");\n"
+ + " * you may not use this file except in compliance with the License.\n"
+ + " * You may obtain a copy of the License at\n" + " *\n"
+ + " * http://www.apache.org/licenses/LICENSE-2.0\n" + " *\n"
+ + " * Unless required by applicable law or agreed to in writing,\n"
+ + " * software distributed under the License is distributed on an\n"
+ + " * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n"
+ + " * KIND, either express or implied. See the License for the\n"
+ + " * specific language governing permissions and limitations\n" + " * under the License. \n"
+ + " */\n" + "\n" + " \n"
+ + " ",
+ out.toString(), "Open standard element");
}
@Test
public void noteTypeAnalyser() throws Exception {
- final MonolithicFileDocument document = new MonolithicFileDocument(Resources.getResourceFile("/elements/LICENSE"));
+ final MonolithicFileDocument document = new MonolithicFileDocument(
+ Resources.getResourceFile("/elements/LICENSE"));
analyser.analyse(document);
reporter.report(document);
- assertEquals("Open note element", " ", out.toString());
+ assertEquals(" ",
+ out.toString(), "Open note element");
}
@Test
public void binaryTypeAnalyser() throws Exception {
- final MonolithicFileDocument document = new MonolithicFileDocument(Resources.getResourceFile("/elements/Image.png"));
+ final MonolithicFileDocument document = new MonolithicFileDocument(
+ Resources.getResourceFile("/elements/Image.png"));
analyser.analyse(document);
reporter.report(document);
- assertEquals("Open binary element", " ", out.toString());
+ assertEquals(
+ " ",
+ out.toString(), "Open binary element");
}
@Test
public void archiveTypeAnalyser() throws Exception {
- final MonolithicFileDocument document = new MonolithicFileDocument(Resources.getResourceFile("/elements/dummy.jar"));
+ final MonolithicFileDocument document = new MonolithicFileDocument(
+ Resources.getResourceFile("/elements/dummy.jar"));
analyser.analyse(document);
reporter.report(document);
- assertEquals("Open archive element", " ", out.toString());
+ assertEquals(
+ " ", out.toString(), "Open archive element");
}
@Test
public void archiveTypeAnalyserIntelliJ() throws Exception {
- final MonolithicFileDocument document = new MonolithicFileDocument(Resources.getResourceFile("/elements/dummy.jar"));
+ final MonolithicFileDocument document = new MonolithicFileDocument(
+ Resources.getResourceFile("/elements/dummy.jar"));
analyser.analyse(document);
reporter.report(document);
- assertEquals("Open archive element", " ", out.toString());
+ assertEquals(
+ " ", out.toString(), "Open archive element");
}
}
diff --git a/apache-rat-core/src/test/java/org/apache/rat/analysis/HeaderCheckWorkerTest.java b/apache-rat-core/src/test/java/org/apache/rat/analysis/HeaderCheckWorkerTest.java
index e7ad80976..e231ad097 100644
--- a/apache-rat-core/src/test/java/org/apache/rat/analysis/HeaderCheckWorkerTest.java
+++ b/apache-rat-core/src/test/java/org/apache/rat/analysis/HeaderCheckWorkerTest.java
@@ -15,26 +15,29 @@
* KIND, either express or implied. See the License for the *
* specific language governing permissions and limitations *
* under the License. *
- */
+ */
package org.apache.rat.analysis;
-import org.apache.rat.analysis.license.ApacheSoftwareLicense20;
-import org.apache.rat.api.Document;
-import org.apache.rat.document.MockLocation;
-import org.junit.Test;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertFalse;
import java.io.StringReader;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
+import org.apache.rat.api.Document;
+import org.apache.rat.license.ILicense;
+import org.apache.rat.testhelpers.TestingLicense;
+import org.apache.rat.testhelpers.TestingLocation;
+import org.junit.jupiter.api.Test;
+
public class HeaderCheckWorkerTest {
@Test
public void isFinished() throws Exception {
- final Document subject = new MockLocation("subject");
- HeaderCheckWorker worker = new HeaderCheckWorker(new StringReader(""), new ApacheSoftwareLicense20(), subject);
+ final Document subject = new TestingLocation("subject");
+ ILicense matcher = new TestingLicense();
+ HeaderCheckWorker worker = new HeaderCheckWorker(new StringReader(""), matcher, subject);
assertFalse(worker.isFinished());
worker.read();
assertTrue(worker.isFinished());
diff --git a/apache-rat-core/src/test/java/org/apache/rat/analysis/generation/JavaDocLicenseNotRequiredTest.java b/apache-rat-core/src/test/java/org/apache/rat/analysis/generation/JavaDocLicenseNotRequiredTest.java
deleted file mode 100644
index 2f22cdc84..000000000
--- a/apache-rat-core/src/test/java/org/apache/rat/analysis/generation/JavaDocLicenseNotRequiredTest.java
+++ /dev/null
@@ -1,82 +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.analysis.generation;
-
-import org.apache.commons.io.IOUtils;
-import org.apache.rat.api.Document;
-import org.apache.rat.document.MockLocation;
-import org.apache.rat.report.claim.impl.xml.MockClaimReporter;
-import org.apache.rat.test.utils.Resources;
-import org.junit.Before;
-import org.junit.Test;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileReader;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-public class JavaDocLicenseNotRequiredTest {
-
- private MockClaimReporter reporter;
- private JavaDocLicenseNotRequired license;
-
- @Before
- public void setUp() throws Exception {
- license = new JavaDocLicenseNotRequired();
- reporter = new MockClaimReporter();
- }
-
- @Test
- public void matchIndexDoc() throws Exception {
- boolean result = readAndMatch("index.html");
- assertTrue("Is a javadoc", result);
- }
-
- @Test
- public void matchClassDoc() throws Exception {
- boolean result = readAndMatch("ArchiveElement.html");
- assertTrue("Is a javadoc", result);
- }
-
- @Test
- public void matchNonJavaDoc() throws Exception {
- boolean result = readAndMatch("notjavadoc.html");
- assertFalse("Not javadocs and so should return null", result);
- }
-
- boolean readAndMatch(String name) throws Exception {
- File file = Resources.getResourceFile("javadocs/" + name);
- boolean result = false;
- BufferedReader in = null;
- try {
- in = new BufferedReader(new FileReader(file));
- String line = in.readLine();
- final Document subject = new MockLocation("subject");
- while (line != null && !result) {
- result = license.match(subject, line);
- line = in.readLine();
- }
- } finally {
- IOUtils.closeQuietly(in);
- }
- return result;
- }
- }
diff --git a/apache-rat-core/src/test/java/org/apache/rat/analysis/license/AbstractLicenseTest.java b/apache-rat-core/src/test/java/org/apache/rat/analysis/license/AbstractLicenseTest.java
new file mode 100644
index 000000000..ad17c909b
--- /dev/null
+++ b/apache-rat-core/src/test/java/org/apache/rat/analysis/license/AbstractLicenseTest.java
@@ -0,0 +1,148 @@
+/*
+ * 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.analysis.license;
+
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.StringReader;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.rat.Defaults;
+import org.apache.rat.analysis.IHeaderMatcher.State;
+import org.apache.rat.analysis.matchers.FullTextMatcher;
+import org.apache.rat.api.MetaData;
+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;
+import org.apache.rat.testhelpers.TestingLicense;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
+
+
+/**
+ * Test to see if short form license information will be recognized correctly.
+ *
+ */
+abstract public class AbstractLicenseTest {
+ private static int NAME = 0;
+ private static int TEXT = 1;
+
+ private Defaults defaults;
+ protected MetaData data;
+
+
+ protected AbstractLicenseTest() {
+ }
+
+
+ @BeforeEach
+ public void setup() {
+ data = new MetaData();
+ defaults = Defaults.builder().build();
+ }
+
+ protected ILicense extractCategory(String id) {
+ TestingLicense testingLicense = new TestingLicense();
+ testingLicense.setId(id);
+ ILicense result = LicenseSetFactory.search(testingLicense, defaults.getLicenses(LicenseFilter.all));
+ if (result == null) {
+ fail("No licenses for id: " + id);
+ }
+ return result;
+ }
+
+ @ParameterizedTest
+ @MethodSource("parameterProvider")
+ public void testMatchProcessing(String id, String familyPattern, String name, String notes, String[][] targets) throws IOException {
+ ILicense license = extractCategory(id);
+ String family = ILicenseFamily.makeCategory(familyPattern);
+ try {
+ for (String[] target : targets) {
+ if (processText(license, target[TEXT])) {
+ data.reportOnLicense(license);
+ assertNotNull(data.get(MetaData.RAT_URL_HEADER_CATEGORY),"No URL HEADER CATEGORY");
+ assertEquals(family,
+ data.get(MetaData.RAT_URL_HEADER_CATEGORY).getValue(), license.toString());
+ assertNotNull(data.get(MetaData.RAT_URL_LICENSE_FAMILY_CATEGORY), "No URL LICENSE FAMILY CATEGORY");
+ assertEquals(family,
+ data.get(MetaData.RAT_URL_LICENSE_FAMILY_CATEGORY).getValue(), license.toString());
+ if (StringUtils.isNotBlank(notes)) {
+ assertNotNull(data.get(MetaData.RAT_URL_HEADER_SAMPLE), "No URL HEADER SAMPLE");
+ assertEquals(FullTextMatcher.prune(notes),
+ FullTextMatcher.prune(data.get(MetaData.RAT_URL_HEADER_SAMPLE).getValue()), license.toString());
+ } else {
+ assertNull(data.get(MetaData.RAT_URL_HEADER_SAMPLE), "URL HEADER SAMPLE was not null");
+ }
+ assertNotNull(data.get(MetaData.RAT_URL_LICENSE_FAMILY_NAME), "No URL LICENSE FAMILY NAME");
+ assertEquals(name,
+ data.get(MetaData.RAT_URL_LICENSE_FAMILY_NAME).getValue(), license.toString());
+ data.clear();
+ } else {
+ fail(license + " was not matched by " + target[NAME]);
+ }
+ license.reset();
+ }
+ } finally {
+ license.reset();
+ }
+
+ }
+
+ private boolean processText(ILicense license, String text) throws IOException {
+ try (BufferedReader in = new BufferedReader(new StringReader(text))) {
+ String line;
+ while (null != (line = in.readLine())) {
+ if (license.matches(line) == State.t) {
+ return true;
+ }
+ }
+ return license.finalizeState().asBoolean();
+ }
+ }
+
+ @ParameterizedTest
+ @MethodSource("parameterProvider")
+ public void testEmbeddedStrings(String id, String family, String name, String notes, String[][] targets) throws IOException {
+ String formats[] = { "%s", "now is not the time %s for copyright", "#%s", "##%s", "## %s", "##%s##", "## %s ##",
+ "/*%s*/", "/* %s */" };
+
+ ILicense license = extractCategory(id);
+ try {
+ for (String[] target : targets) {
+ for (String fmt : formats) {
+ boolean found = processText(license, String.format(fmt, target[TEXT]));
+ license.reset();
+ assertTrue(found, ()->String.format("%s %s did not match pattern '%s' for target string %s", id,
+ name, fmt, target[NAME]));
+ }
+ }
+ } finally {
+ license.reset();
+ }
+ }
+}
diff --git a/apache-rat-core/src/test/java/org/apache/rat/analysis/license/ApacheSoftwareLicense20ShortTest.java b/apache-rat-core/src/test/java/org/apache/rat/analysis/license/ApacheSoftwareLicense20ShortTest.java
deleted file mode 100644
index 5cdde45a9..000000000
--- a/apache-rat-core/src/test/java/org/apache/rat/analysis/license/ApacheSoftwareLicense20ShortTest.java
+++ /dev/null
@@ -1,55 +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.analysis.license;
-
-import static org.junit.Assert.assertTrue;
-
-import org.junit.Test;
-
-/**
- * Test to see if short form license information will be recognized correctly.
- *
- * @see https://www.apache.org/legal/src-headers.html#is-a-short-form-of-the-source-header-available
- *
- * @author Karl Heinz Marbaise
- *
- */
-public class ApacheSoftwareLicense20ShortTest {
-
- private static final String SHORT_LICENSE = "Licensed to the Apache Software Foundation (ASF) "
- + "under one or more contributor license agreements; and to You under the Apache License, Version 2.0.";
-
- @Test
- public void apacheShortLicenseShouldBeIdentified() {
- ApacheSoftwareLicense20 worker = new ApacheSoftwareLicense20();
- assertTrue(worker.matches(ApacheSoftwareLicense20.FIRST_LICENSE_LINE_SHORT));
- }
-
- @Test
- public void apacheShortLicenseShouldBeIdentifiedWithDifferentPreAndPostFixes() {
- ApacheSoftwareLicense20 worker = new ApacheSoftwareLicense20();
- assertTrue(worker.matches(SHORT_LICENSE));
- assertTrue(worker.matches("# " + SHORT_LICENSE));
- assertTrue(worker.matches("##" + SHORT_LICENSE));
- assertTrue(worker.matches("##" + SHORT_LICENSE + "##"));
- assertTrue(worker.matches("/* " + SHORT_LICENSE + "*/"));
- assertTrue(worker.matches("/* " + SHORT_LICENSE + "*/"));
- }
-
-}
diff --git a/apache-rat-core/src/test/java/org/apache/rat/analysis/license/ApacheSoftwareLicense20Test.java b/apache-rat-core/src/test/java/org/apache/rat/analysis/license/ApacheSoftwareLicense20Test.java
deleted file mode 100644
index 838ae0b8f..000000000
--- a/apache-rat-core/src/test/java/org/apache/rat/analysis/license/ApacheSoftwareLicense20Test.java
+++ /dev/null
@@ -1,70 +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.analysis.license;
-
-import org.apache.rat.api.Document;
-import org.apache.rat.document.MockLocation;
-import org.apache.rat.report.claim.impl.xml.MockClaimReporter;
-import org.junit.Before;
-import org.junit.Test;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-public class ApacheSoftwareLicense20Test {
-
- private MockClaimReporter reporter;
-
- @Before
- public void setUp() throws Exception {
- reporter = new MockClaimReporter();
- }
-
- @Test
- public void matches() throws Exception {
- ApacheSoftwareLicense20 worker = new ApacheSoftwareLicense20();
- assertTrue(worker.matches(ApacheSoftwareLicense20.FIRST_LICENSE_LINE));
- assertTrue(worker.matches(" Licensed under the Apache License, Version 2.0 (the \"License\");"));
- assertTrue(worker.matches("Licensed under the Apache License, Version 2.0 (the \"License\");"));
- assertTrue(worker.matches(" * Licensed under the Apache License, Version 2.0 (the \"License\");"));
- assertTrue(worker.matches(" // Licensed under the Apache License, Version 2.0 (the \"License\");"));
- assertTrue(worker.matches(" /* Licensed under the Apache License, Version 2.0 (the \"License\");"));
- assertTrue(worker.matches(" Licensed under the Apache License, Version 2.0 (the \"License\");"));
- assertTrue(worker.matches(" ## Licensed under the Apache License, Version 2.0 (the \"License\");"));
- assertTrue(worker.matches(" ## Licensed under the Apache License, Version 2.0 (the \"License\") ##);"));
- assertFalse(worker.matches("'Behold, Telemachus! (nor fear the sight,)"));
- }
-
- @Test
- public void match() throws Exception {
- ApacheSoftwareLicense20 worker = new ApacheSoftwareLicense20();
- final Document subject = new MockLocation("subject");
- assertTrue(worker.match(subject, ApacheSoftwareLicense20.FIRST_LICENSE_LINE));
- assertTrue(worker.match(subject, " Licensed under the Apache License, Version 2.0 (the \"License\");"));
- assertTrue(worker.match(subject, "Licensed under the Apache License, Version 2.0 (the \"License\");"));
- assertTrue(worker.match(subject, " * Licensed under the Apache License, Version 2.0 (the \"License\");"));
- assertTrue(worker.match(subject, " // Licensed under the Apache License, Version 2.0 (the \"License\");"));
- assertTrue(worker.match(subject, " /* Licensed under the Apache License, Version 2.0 (the \"License\");"));
- assertTrue(worker.match(subject, " Licensed under the Apache License, Version 2.0 (the \"License\");"));
- assertTrue(worker.match(subject, " ## Licensed under the Apache License, Version 2.0 (the \"License\");"));
- assertTrue(worker.match(subject, " ## Licensed under the Apache License, Version 2.0 (the \"License\") ##);"));
- assertFalse(worker.match(subject, "'Behold, Telemachus! (nor fear the sight,)"));
- }
-
-}
diff --git a/apache-rat-core/src/test/java/org/apache/rat/analysis/license/ApacheSoftwareLicenseTest.java b/apache-rat-core/src/test/java/org/apache/rat/analysis/license/ApacheSoftwareLicenseTest.java
new file mode 100644
index 000000000..e1c00e522
--- /dev/null
+++ b/apache-rat-core/src/test/java/org/apache/rat/analysis/license/ApacheSoftwareLicenseTest.java
@@ -0,0 +1,83 @@
+/*
+ * 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.analysis.license;
+
+import java.util.stream.Stream;
+
+import org.junit.jupiter.params.provider.Arguments;
+
+/**
+ * Apache Software License detection tests.
+ *
+ */
+public class ApacheSoftwareLicenseTest extends AbstractLicenseTest {
+
+ public static final String id = "AL";
+ public static final String name = "Apache License Version 2.0";
+ private static String[][] targets = {
+ { "short", "Licensed under the Apache License, Version 2.0 (the \"License\")" },
+ { "short2",
+ "Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements; and to You under the Apache License, Version 2.0." },
+ { "http", "http://www.apache.org/licenses/LICENSE-2.0" },
+ { "https", "https://www.apache.org/licenses/LICENSE-2.0" },
+ { "html", "http://www.apache.org/licenses/LICENSE-2.0.html" },
+ { "htmls", "https://www.apache.org/licenses/LICENSE-2.0.html" },
+ { "txt", "http://www.apache.org/licenses/LICENSE-2.0.txt" },
+ { "txts", "https://www.apache.org/licenses/LICENSE-2.0.txt" },
+ { "fullTxt",
+ "Licensed under the Apache License, Version 2.0 (the \"License\")\nyou may not use this file except "
+ + "in compliance with the License.\nYou may obtain a copy of the License at\n"
+ + "http://www.apache.org/licenses/LICENSE-2.0\nUnless required by applicable "
+ + "law or agreed to in writing, software\ndistributed under the License is "
+ + "distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either "
+ + "express or implied.\nSee the License for the specific language governing permissions and\n"
+ + "limitations under the License.\n" },
+ { "spdx-tab", "SPDX-License-Identifier:\tApache-2.0" },
+ { "spdx-space", "SPDX-License-Identifier: Apache-2.0" },
+ { "long text",
+ "/*\n" + " * Licensed under the Apache License, Version 2.0 (the \"License\");\n"
+ + " * you may not use this file except in compliance with the License.\n" + " *\n"
+ + " * You may obtain a copy of the License at\n"
+ + " * http://www.apache.org/licenses/LICENSE-2.0\n" + " *\n"
+ + " * Unless required by applicable law or agreed to in writing, software\n"
+ + " * distributed under the License is distributed on an \"AS IS\" BASIS,\n"
+ + " * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n"
+ + " * See the License for the specific language governing permissions and\n"
+ + " * limitations under the License.\n" + " */\n" }
+
+ };
+
+ public static Stream parameterProvider() {
+ return Stream.of(Arguments.of(id, id, name, null, targets));
+ }
+
+//
+// @Test(timeout = 2000) // may need to be adjusted if many more files are added
+// public void goodFiles() throws Exception {
+// IHeaderMatcher matcher = new MultiplexLicense("goodFiles", AbstractMatcherTest.extractCategory(category));
+// DirectoryScanner.testFilesInDir("appliedAL20/good", matcher, true);
+// }
+//
+// @Test(timeout = 2000) // may need to be adjusted if many more files are added
+// public void badFiles() throws Exception {
+// IHeaderMatcher matcher = new MultiplexLicense("badFiles", AbstractMatcherTest.extractCategory(category));
+// DirectoryScanner.testFilesInDir("appliedAL20/bad", matcher, false);
+// }
+
+}
diff --git a/apache-rat-core/src/test/java/org/apache/rat/analysis/license/AppliedApacheSoftwareLicense20Test.java b/apache-rat-core/src/test/java/org/apache/rat/analysis/license/AppliedApacheSoftwareLicense20Test.java
deleted file mode 100644
index 94c0917ac..000000000
--- a/apache-rat-core/src/test/java/org/apache/rat/analysis/license/AppliedApacheSoftwareLicense20Test.java
+++ /dev/null
@@ -1,109 +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.analysis.license;
-
-import org.apache.commons.io.IOUtils;
-import org.apache.rat.api.Document;
-import org.apache.rat.document.MockLocation;
-import org.apache.rat.report.claim.impl.xml.MockClaimReporter;
-import org.apache.rat.test.utils.Resources;
-import org.junit.Before;
-import org.junit.Test;
-
-import java.io.BufferedReader;
-import java.io.StringReader;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-public class AppliedApacheSoftwareLicense20Test {
-
- private static final String HEADER
- = "/*\n"
- + " * Copyright 2012-2013 FooBar.\n"
- + " *\n"
- + " * Licensed under the Apache License, Version 2.0 (the \"License\");\n"
- + " * you may not use this file except in compliance with the License.\n"
- + " *\n"
- + " * You may obtain a copy of the License at\n"
- + " * http://www.apache.org/licenses/LICENSE-2.0\n"
- + " *\n"
- + " * Unless required by applicable law or agreed to in writing, software\n"
- + " * distributed under the License is distributed on an \"AS IS\" BASIS,\n"
- + " * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n"
- + " * See the License for the specific language governing permissions and\n"
- + " * limitations under the License.\n"
- + " */\n";
-
- private AppliedApacheSoftwareLicense20 license;
-
- private MockClaimReporter reporter;
-
- @Before
- public void setUp() throws Exception {
- license = new AppliedApacheSoftwareLicense20("FooBar");
- reporter = new MockClaimReporter();
- }
-
- @Test
- public void match() throws Exception {
- BufferedReader in = new BufferedReader(new StringReader(HEADER));
- String line = in.readLine();
- boolean result = false;
- final Document subject = new MockLocation("subject");
- while (line != null) {
- result = license.match(subject, line);
- line = in.readLine();
- }
- assertTrue("Applied AL2.0 license should be matched", result);
- license.reset();
- result = license.match(subject, "New line");
- assertFalse("After reset, content should build up again", result);
- }
-
- @Test
- public void noMatch() throws Exception {
- BufferedReader in = null;
- try {
- in = Resources.getBufferedResourceReader("elements/Source.java");
- String line = in.readLine();
- boolean result = false;
- final Document subject = new MockLocation("subject");
- while (line != null) {
- result = license.match(subject, line);
- line = in.readLine();
- }
- assertFalse("Applied AL2.0 license should not be matched", result);
- license.reset();
- } finally {
- IOUtils.closeQuietly(in);
- }
- }
-
- @Test(timeout = 2000) // may need to be adjusted if many more files are added
- public void goodFiles() throws Exception {
- DirectoryScanner.testFilesInDir("appliedAL20/good", license, true);
- }
-
- @Test(timeout = 2000) // may need to be adjusted if many more files are added
- public void baddFiles() throws Exception {
- DirectoryScanner.testFilesInDir("appliedAL20/bad", license, false);
- }
-
-}
diff --git a/apache-rat-core/src/test/java/org/apache/rat/analysis/license/AppliedApacheSoftwareLicenseTest.java b/apache-rat-core/src/test/java/org/apache/rat/analysis/license/AppliedApacheSoftwareLicenseTest.java
new file mode 100644
index 000000000..7f2df2119
--- /dev/null
+++ b/apache-rat-core/src/test/java/org/apache/rat/analysis/license/AppliedApacheSoftwareLicenseTest.java
@@ -0,0 +1,57 @@
+/*
+ * 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.analysis.license;
+
+import java.util.stream.Stream;
+
+import org.junit.jupiter.params.provider.Arguments;
+
+public class AppliedApacheSoftwareLicenseTest extends AbstractLicenseTest {
+
+ private static String ID = "ASL";
+ private static String NAME = "Applied Apache License Version 2.0";
+ private static String[][] targets = { { "simple", "/*\n" + " * Copyright 2012-2013 FooBar.\n" + " *\n"
+ + " * Licensed under the Apache License, Version 2.0 (the \"License\");\n"
+ + " * you may not use this file except in compliance with the License.\n" + " *\n"
+ + " * You may obtain a copy of the License at\n" + " * http://www.apache.org/licenses/LICENSE-2.0\n"
+ + " *\n" + " * Unless required by applicable law or agreed to in writing, software\n"
+ + " * distributed under the License is distributed on an \"AS IS\" BASIS,\n"
+ + " * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n"
+ + " * See the License for the specific language governing permissions and\n"
+ + " * limitations under the License.\n" + " */\n" } };
+
+ public static Stream parameterProvider() {
+ return Stream.of(Arguments.of(ID, ApacheSoftwareLicenseTest.id, ApacheSoftwareLicenseTest.name, null, targets));
+ }
+
+ /*
+
+
+ @Test(timeout = 2000) // may need to be adjusted if many more files are added
+ public void goodFiles() throws Exception {
+ DirectoryScanner.testFilesInDir("appliedAL20/good", license, true);
+ }
+
+ @Test(timeout = 2000) // may need to be adjusted if many more files are added
+ public void baddFiles() throws Exception {
+ DirectoryScanner.testFilesInDir("appliedAL20/bad", license, false);
+ }
+ */
+
+}
diff --git a/apache-rat-core/src/test/java/org/apache/rat/analysis/license/CDDL1LicenseTest.java b/apache-rat-core/src/test/java/org/apache/rat/analysis/license/CDDL1LicenseTest.java
index 3afe377e2..d0008085f 100644
--- a/apache-rat-core/src/test/java/org/apache/rat/analysis/license/CDDL1LicenseTest.java
+++ b/apache-rat-core/src/test/java/org/apache/rat/analysis/license/CDDL1LicenseTest.java
@@ -18,71 +18,32 @@
*/
package org.apache.rat.analysis.license;
-import org.apache.rat.analysis.IHeaderMatcher;
-import org.apache.rat.api.Document;
-import org.apache.rat.document.MockLocation;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-public class CDDL1LicenseTest {
-
- private static final String LICENSE_LINE =
- " DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.\n\n"
- + "Copyright 2011-2013 Tirasa. All rights reserved.\n\n"
- + "The contents of this file are subject to the terms of the Common Development\n"
- + "and Distribution License(\"CDDL\") (the \"License\"). You may not use this file\n"
- + "except in compliance with the License.\n\n"
- + "You can obtain a copy of the License at https://oss.oracle.com/licenses/CDDL\n"
- + "See the License for the specific language governing permissions and limitations\n"
- + "under the License.";
-
- /**
- * To ease testing provide a map with a given license version and the string to test for.
- */
- private static Map licenseStringMap;
-
- private Document subject;
-
- @BeforeClass
- public static void initLicensesUnderTest() {
- licenseStringMap = new HashMap<>();
- licenseStringMap.put(new CDDL1License(), LICENSE_LINE);
- assertEquals(1, licenseStringMap.entrySet().size());
- }
-
- @Before
- public final void initSubject() {
- this.subject = new MockLocation("subject");
+import java.util.stream.Stream;
+
+import org.junit.jupiter.params.provider.Arguments;
+
+public class CDDL1LicenseTest extends AbstractLicenseTest {
+ public static final String id = "CDDL1";
+ public static final String name = "COMMON DEVELOPMENT AND DISTRIBUTION LICENSE Version 1.0";
+ private static String[][] targets = {
+ { "fullTxt",
+ "The contents of this file are subject to the terms of the Common Development "
+ + "and Distribution License(\"CDDL\") (the \"License\"). You may not use this file "
+ + "except in compliance with the License. " },
+ { "longerTxt",
+ " DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. "
+ + "Copyright 2011-2013 Tirasa. All rights reserved. "
+ + "The contents of this file are subject to the terms of the Common Development "
+ + "and Distribution License(\"CDDL\") (the \"License\"). You may not use this file "
+ + "except in compliance with the License. "
+ + "You can obtain a copy of the License at https://oss.oracle.com/licenses/CDDL "
+ + "See the License for the specific language governing permissions and limitations "
+ + "under the License." },
+ { "spdx-tab", "SPDX-License-Identifier:\tCDDL-1.0" },
+ { "spdx-space", "SPDX-License-Identifier: CDDL-1.0" } };
+
+ public static Stream parameterProvider() {
+ return Stream.of(Arguments.of( id, id, name, null, targets));
}
- @Test
- public void testNegativeMatches() throws Exception {
- for (Map.Entry licenseUnderTest : licenseStringMap.entrySet()) {
- assertFalse(licenseUnderTest.getKey().match(subject, "'Behold, Telemachus! (nor fear the sight,)"));
- }
- }
-
- @Test
- public void testPositiveMatchInDocument() throws Exception {
- for (Map.Entry licenseUnderTest : licenseStringMap.entrySet()) {
- assertTrue(licenseUnderTest.getKey().match(subject, "\t" + licenseUnderTest.getValue()));
- assertTrue(licenseUnderTest.getKey().match(subject, " " + licenseUnderTest.getValue()));
- assertTrue(licenseUnderTest.getKey().match(subject, licenseUnderTest.getValue()));
- assertTrue(licenseUnderTest.getKey().match(subject, " * " + licenseUnderTest.getValue()));
- assertTrue(licenseUnderTest.getKey().match(subject, " // " + licenseUnderTest.getValue()));
- assertTrue(licenseUnderTest.getKey().match(subject, " /* " + licenseUnderTest.getValue()));
- assertTrue(licenseUnderTest.getKey().match(subject, " /** " + licenseUnderTest.getValue()));
- assertTrue(licenseUnderTest.getKey().match(subject, " " + licenseUnderTest.getValue()));
- assertTrue(licenseUnderTest.getKey().match(subject, " ## " + licenseUnderTest.getValue()));
- assertTrue(licenseUnderTest.getKey().match(subject, " ## " + licenseUnderTest.getValue() + " ##"));
- }
- }
}
diff --git a/apache-rat-core/src/test/java/org/apache/rat/analysis/license/CopyrightHeaderTest.java b/apache-rat-core/src/test/java/org/apache/rat/analysis/license/CopyrightHeaderTest.java
deleted file mode 100644
index 5699cf589..000000000
--- a/apache-rat-core/src/test/java/org/apache/rat/analysis/license/CopyrightHeaderTest.java
+++ /dev/null
@@ -1,76 +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.analysis.license;
-
-import org.apache.rat.api.Document;
-import org.apache.rat.api.MetaData;
-import org.apache.rat.document.MockLocation;
-import org.apache.rat.report.claim.impl.xml.MockClaimReporter;
-import org.junit.Before;
-import org.junit.Test;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-public class CopyrightHeaderTest {
-
- private static final String[] MATCHING_HEADERS =
- { "/* Copyright 2012 FooBar.*/"
- , "/* copyright 2012 foobar.*/"
- , "/* Copyright 2012-2013 FooBar.*/" };
- private static final String[] NON_MATCHING_HEADERS =
- { "/* Copyright*/"
- , "/* Copyright FooBar.*/"
- , "/* Copyright 2013*/"
- , "/* Copyright 123a*/"
- , "/* Copyright 123f oobar*/"
- , "/* Copyright 2013FooBar*/"
- , "/* Copyright 2012 2013 FooBar.*/" };
-
- private CopyrightHeader header;
- private MockClaimReporter reporter;
- private Document subject = new MockLocation("subject");
-
- @Before
- public void setUp() throws Exception {
- header = new CopyrightHeader(MetaData.RAT_LICENSE_FAMILY_CATEGORY_DATUM_ASL,MetaData.RAT_LICENSE_FAMILY_NAME_DATUM_APACHE_LICENSE_VERSION_2_0,"","FooBar");
- reporter = new MockClaimReporter();
- subject = new MockLocation("subject");
- }
-
- @Test
- public void match() throws Exception {
- for (String line : MATCHING_HEADERS) {
- assertTrue("Copyright Header should be matched", header.match(subject, line));
- header.reset();
- assertFalse("After reset, content should build up again", header.match(subject, "New line"));
- header.reset();
- }
- }
-
- @Test
- public void noMatch() throws Exception {
- for (String line : NON_MATCHING_HEADERS) {
- assertFalse("Copyright Header shouldn't be matched", header.match(subject, line));
- header.reset();
- assertTrue("After reset, content should build up again", header.match(subject, MATCHING_HEADERS[0]));
- header.reset();
- }
- }
-}
diff --git a/apache-rat-core/src/test/java/org/apache/rat/analysis/license/DirectoryScanner.java b/apache-rat-core/src/test/java/org/apache/rat/analysis/license/DirectoryScanner.java
index 8d9a67b7b..57eb1b9a5 100644
--- a/apache-rat-core/src/test/java/org/apache/rat/analysis/license/DirectoryScanner.java
+++ b/apache-rat-core/src/test/java/org/apache/rat/analysis/license/DirectoryScanner.java
@@ -18,46 +18,47 @@
package org.apache.rat.analysis.license;
-import static org.junit.Assert.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.fail;
import java.io.BufferedReader;
import java.io.File;
import org.apache.commons.io.IOUtils;
-import org.apache.rat.analysis.IHeaderMatcher;
-import org.apache.rat.api.Document;
-import org.apache.rat.document.MockLocation;
+import org.apache.rat.analysis.IHeaderMatcher.State;
+import org.apache.rat.license.ILicense;
import org.apache.rat.test.utils.Resources;
-import org.junit.Assert;
+import org.junit.jupiter.api.Test;
class DirectoryScanner {
@SuppressWarnings("boxing") // OK in test code
/**
* Get list of files in a directory, and scan for license matches
+ *
* @param directory the directory containing the files
* @param matcher the license matcher
* @param expected the expected result of the each scan
* @throws Exception
*/
- public static void testFilesInDir(String directory, IHeaderMatcher matcher, boolean expected) throws Exception {
+ @Test
+ public static void testFilesInDir(String directory, ILicense license, boolean expected) throws Exception {
final File[] resourceFiles = Resources.getResourceFiles(directory);
if (resourceFiles.length == 0) {
- Assert.fail("No files found under "+directory);
+ fail("No files found under " + directory);
}
- for(File f : resourceFiles) {
- final Document subject = new MockLocation(f.toString());
+ for (File f : resourceFiles) {
BufferedReader br = null;
try {
boolean result = false;
br = Resources.getBufferedReader(f);
String line;
- while(!result && (line = br.readLine()) != null) {
- result = matcher.match(subject, line);
+ while (!result && (line = br.readLine()) != null) {
+ result = license.matches(line) == State.t;
}
- assertEquals(f.toString(), expected, result);
+ assertEquals(expected, result, f.toString());
} finally {
- matcher.reset();
+ license.reset();
IOUtils.closeQuietly(br);
}
}
diff --git a/apache-rat-core/src/test/java/org/apache/rat/analysis/license/GPL123LicenseTest.java b/apache-rat-core/src/test/java/org/apache/rat/analysis/license/GPL123LicenseTest.java
deleted file mode 100644
index 9c4fd80e8..000000000
--- a/apache-rat-core/src/test/java/org/apache/rat/analysis/license/GPL123LicenseTest.java
+++ /dev/null
@@ -1,87 +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.analysis.license;
-
-import org.apache.rat.analysis.IHeaderMatcher;
-import org.apache.rat.api.Document;
-import org.apache.rat.document.MockLocation;
-import org.apache.rat.report.claim.impl.xml.MockClaimReporter;
-import org.junit.Before;
-import org.junit.Test;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-/**
- * Tests GPL license occurrences within comments and other characters.
- * Works for GPL1 to GPL3.
- */
-public class GPL123LicenseTest {
- MockClaimReporter reporter;
- Document subject;
-
- /**
- * To ease testing provide a map with a given license version and the string to test for.
- */
- private static Map licenseStringMap;
-
- /**
- * If you replace this with BeforeClass and make this method static the build fails at line 67.
- */
- @Before
- public void initLicensesUnderTest() {
- licenseStringMap = new HashMap<>();
- licenseStringMap.put(new GPL1License(), GPL1License.FIRST_LICENSE_LINE);
- licenseStringMap.put(new GPL2License(), GPL2License.FIRST_LICENSE_LINE);
- licenseStringMap.put(new GPL3License(), GPL3License.FIRST_LICENSE_LINE);
- }
-
- @Before
- public final void initReporter() {
- this.reporter = new MockClaimReporter();
- this.subject = new MockLocation("subject");
- }
-
- @Test
- public void testNegativeMatches() throws Exception {
- for (Map.Entry licenseUnderTest : licenseStringMap.entrySet()) {
- assertFalse(licenseUnderTest.getKey().match(subject, "'Behold, Telemachus! (nor fear the sight,)"));
- }
- }
-
- @Test
- public void testPositiveMatchInDocument() throws Exception {
- for (Map.Entry licenseUnderTest : licenseStringMap.entrySet()) {
- assertTrue(licenseUnderTest.getKey().match(subject, "\t" + licenseUnderTest.getValue()));
- assertTrue(licenseUnderTest.getKey().match(subject, " " + licenseUnderTest.getValue()));
- assertTrue(licenseUnderTest.getKey().match(subject, licenseUnderTest.getValue()));
- assertTrue(licenseUnderTest.getKey().match(subject, " * " + licenseUnderTest.getValue()));
- assertTrue(licenseUnderTest.getKey().match(subject, " // " + licenseUnderTest.getValue()));
- assertTrue(licenseUnderTest.getKey().match(subject, " /* " + licenseUnderTest.getValue()));
- assertTrue(licenseUnderTest.getKey().match(subject, " /** " + licenseUnderTest.getValue()));
- assertTrue(licenseUnderTest.getKey().match(subject, " " + licenseUnderTest.getValue()));
- assertTrue(licenseUnderTest.getKey().match(subject, " ## " + licenseUnderTest.getValue()));
- assertTrue(licenseUnderTest.getKey().match(subject, " ## " + licenseUnderTest.getValue() + " ##"));
- }
- }
-
-}
diff --git a/apache-rat-core/src/test/java/org/apache/rat/analysis/license/GPLLicenseTest.java b/apache-rat-core/src/test/java/org/apache/rat/analysis/license/GPLLicenseTest.java
new file mode 100644
index 000000000..7d0a51eae
--- /dev/null
+++ b/apache-rat-core/src/test/java/org/apache/rat/analysis/license/GPLLicenseTest.java
@@ -0,0 +1,64 @@
+/*
+ * 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.analysis.license;
+
+import java.util.stream.Stream;
+
+import org.junit.jupiter.params.provider.Arguments;
+
+/**
+ * Tests GPL license occurrences within comments and other characters. Works for
+ * GPL1 to GPL3.
+ */
+
+public class GPLLicenseTest extends AbstractLicenseTest {
+
+ private static Arguments GPL1 = Arguments.of( "GPL1", "GPL1", "GNU General Public License, version 1", null,
+ new String[][] {
+ { "fulltext", "This program is free software; you can redistribute it and/or modify\n "
+ + "it under the terms of the GNU General Public License as published by\n "
+ + "the Free Software Foundation; either version 1, or (at your option)\n " + "any later version." },
+ { "spdx-tab", "SPDX-License-Identifier:\tGPL-1.0-only" },
+ { "spdx-space", "SPDX-License-Identifier: GPL-1.0-only" }, } );
+
+ private static Arguments GPL2 = Arguments.of( "GPL2", "GPL2", "GNU General Public License, version 2", null,
+ new String[][] {
+ { "fulltext",
+ "This program is free software; you can redistribute it and/or\n"
+ + "modify it under the terms of the GNU General Public License\n"
+ + "as published by the Free Software Foundation; either version 2\n"
+ + "of the License, or (at your option) any later version." },
+ { "spdx-tab", "SPDX-License-Identifier:\tGPL-2.0-only" },
+ { "spdx-space", "SPDX-License-Identifier: GPL-2.0-only" }, } );
+
+ private static Arguments GPL3 = Arguments.of( "GPL3", "GPL3", "GNU General Public License, version 3", null,
+ new String[][] {
+ { "fulltext",
+ "This program is free software: you can redistribute it and/or modify\n"
+ + " it under the terms of the GNU General Public License as published by\n"
+ + " the Free Software Foundation, either version 3 of the License, or\n"
+ + " (at your option) any later version." },
+ { "spdx-tab", "SPDX-License-Identifier:\tGPL-3.0-only" },
+ { "spdx-space", "SPDX-License-Identifier: GPL-3.0-only" }, } );
+
+
+ public static Stream parameterProvider() {
+ return Stream.of(GPL1, GPL2, GPL3);
+ }
+}
diff --git a/apache-rat-core/src/test/java/org/apache/rat/analysis/license/GeneratedLicenseTest.java b/apache-rat-core/src/test/java/org/apache/rat/analysis/license/GeneratedLicenseTest.java
new file mode 100644
index 000000000..b8232440a
--- /dev/null
+++ b/apache-rat-core/src/test/java/org/apache/rat/analysis/license/GeneratedLicenseTest.java
@@ -0,0 +1,51 @@
+/*
+ * 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.analysis.license;
+
+import java.util.stream.Stream;
+
+import org.junit.jupiter.params.provider.Arguments;
+
+public class GeneratedLicenseTest extends AbstractLicenseTest {
+ private static String id = "GEN";
+ private static String name = "Generated Files";
+ private static String notes = "Files that are autmoatically generated.";
+ private static String[][] targets = { { "Cayenne", "generated by Cayenne" }, { "JJTree", "Generated By:JJTree" },
+ { "JavaCC", "Generated By:JavaCC" }, { "AUTOMATIC", "THIS FILE IS AUTOMATICALLY GENERATED" },
+ { "XBeans", "NOTE: this file is autogenerated by XBeans" },
+ { "automatic", "This file was automatically generated by" },
+ { "do not edit", "# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!" },
+ { "NMAKE", "# Microsoft Developer Studio Generated NMAKE File" },
+ { "MDS Build", "# Microsoft Developer Studio Generated Build File" },
+ { "autoheader", "Generated from configure.ac by autoheader" },
+ { "aclocal", "generated automatically by aclocal" },
+ { "maven project", "build.xml generated by maven from project.xml" },
+ { "generated", "This file was generated by" }, { "auto", "This file has been automatically generated." },
+ { "do not modify", "Automatically generated - do not modify!" }, { "javadoc style", "Javadoc style sheet" },
+ { "SOURCE", "SOURCE FILE GENERATATED" }, { "Batik", "Generated by the Batik" },
+ { "file autogenerated", "this file is autogenerated" },
+ { "class autogenerated", "This class was autogenerated" }, { "maven", "Generated by Maven" },
+ { "Thrift", "Autogenerated by Thrift" },
+ { "machine generated", "DO NOT EDIT THIS FILE - it is machine generated" },
+ { "generated by", "This class was generated by" }, { "javadoc", "Generated by javadoc" } };
+
+ public static Stream parameterProvider() {
+ return Stream.of(Arguments.of( id, id, name, notes, targets));
+ }
+}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/license/GPL3License.java b/apache-rat-core/src/test/java/org/apache/rat/analysis/license/IllumosLicenseTest.java
similarity index 60%
rename from apache-rat-core/src/main/java/org/apache/rat/analysis/license/GPL3License.java
rename to apache-rat-core/src/test/java/org/apache/rat/analysis/license/IllumosLicenseTest.java
index c9a84fdce..319979767 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/analysis/license/GPL3License.java
+++ b/apache-rat-core/src/test/java/org/apache/rat/analysis/license/IllumosLicenseTest.java
@@ -18,20 +18,19 @@
*/
package org.apache.rat.analysis.license;
-import org.apache.rat.api.MetaData;
+import java.util.stream.Stream;
-/**
- * License matches GPL3 or later.
- */
-public class GPL3License extends FullTextMatchingLicense {
- public static final String FIRST_LICENSE_LINE = "This program is free software: you can redistribute it and/or modify\n" +
- " it under the terms of the GNU General Public License as published by\n" +
- " the Free Software Foundation, either version 3 of the License, or\n" +
- " (at your option) any later version.";
+import org.junit.jupiter.params.provider.Arguments;
+
+public class IllumosLicenseTest extends AbstractLicenseTest {
+ private static String id = "ILLUMOS";
+ private static String note = "Modified CDDL1 license";
+ private static String[][] targets = { { "illumos",
+ "The contents of this file are subject to the terms of the "
+ + "Common Development and Distribution License (the \"License\") "
+ + "You may not use this file except in compliance with the License. " } };
- public GPL3License() {
- super(MetaData.RAT_LICENSE_FAMILY_CATEGORY_DATUM_GPL3,
- MetaData.RAT_LICENSE_FAMILY_NAME_DATUM_GPL_VERSION_3,
- "", FIRST_LICENSE_LINE);
+ public static Stream parameterProvider() {
+ return Stream.of(Arguments.of(id, CDDL1LicenseTest.id, CDDL1LicenseTest.name, note, targets));
}
}
diff --git a/apache-rat-core/src/test/java/org/apache/rat/analysis/license/MITLicenseTest.java b/apache-rat-core/src/test/java/org/apache/rat/analysis/license/MITLicenseTest.java
index 9635aa6c4..be8c25477 100644
--- a/apache-rat-core/src/test/java/org/apache/rat/analysis/license/MITLicenseTest.java
+++ b/apache-rat-core/src/test/java/org/apache/rat/analysis/license/MITLicenseTest.java
@@ -18,67 +18,18 @@
*/
package org.apache.rat.analysis.license;
-import org.apache.rat.analysis.IHeaderMatcher;
-import org.apache.rat.api.Document;
-import org.apache.rat.document.MockLocation;
-import org.junit.Before;
-import org.junit.Test;
+import java.util.stream.Stream;
-import java.util.HashMap;
-import java.util.Map;
+import org.junit.jupiter.params.provider.Arguments;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
+public class MITLicenseTest extends AbstractLicenseTest {
+ private static String id = "MIT";
+ private static String name = "The MIT License";
+ private static String[][] targets = { { "fulltext",
+ "Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \\\"Software\\\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE." },
+ { "spdx-tab", "SPDX-License-Identifier:\tMIT" }, { "spdx-space", "SPDX-License-Identifier: MIT" }, };
-public class MITLicenseTest {
- private Document subject;
-
- /**
- * To ease testing provide a map with a given license version and the string to test for.
- */
- private static Map licenseStringMap;
-
- /**
- * If you replace this with BeforeClass and make this method static the build fails at line 71.
- */
- @Before
- public void initLicensesUnderTest() {
- licenseStringMap = new HashMap<>();
- licenseStringMap.put(new MITLicense(),
- MITLicense.FIRST_LICENSE_LINE
- + "\n" + MITLicense.MIDDLE_LICENSE_LINE
- + "\r\n * " + MITLicense.AS_IS_LICENSE_LINE);
- assertEquals(1, licenseStringMap.entrySet().size());
- }
-
-
- @Before
- public final void initReporter() {
- this.subject = new MockLocation("subject");
+ public static Stream parameterProvider() {
+ return Stream.of(Arguments.of(id, id, name, null, targets));
}
-
- @Test
- public void testNegativeMatches() throws Exception {
- for (Map.Entry licenseUnderTest : licenseStringMap.entrySet()) {
- assertFalse(licenseUnderTest.getKey().match(subject, "'Behold, Telemachus! (nor fear the sight,)"));
- }
- }
-
- @Test
- public void testPositiveMatchInDocument() throws Exception {
- for (Map.Entry licenseUnderTest : licenseStringMap.entrySet()) {
- assertTrue(licenseUnderTest.getKey().match(subject, "\t" + licenseUnderTest.getValue()));
- assertTrue(licenseUnderTest.getKey().match(subject, " " + licenseUnderTest.getValue()));
- assertTrue(licenseUnderTest.getKey().match(subject, licenseUnderTest.getValue()));
- assertTrue(licenseUnderTest.getKey().match(subject, " * " + licenseUnderTest.getValue()));
- assertTrue(licenseUnderTest.getKey().match(subject, " // " + licenseUnderTest.getValue()));
- assertTrue(licenseUnderTest.getKey().match(subject, " /* " + licenseUnderTest.getValue()));
- assertTrue(licenseUnderTest.getKey().match(subject, " /** " + licenseUnderTest.getValue()));
- assertTrue(licenseUnderTest.getKey().match(subject, " " + licenseUnderTest.getValue()));
- assertTrue(licenseUnderTest.getKey().match(subject, " ## " + licenseUnderTest.getValue()));
- assertTrue(licenseUnderTest.getKey().match(subject, " ## " + licenseUnderTest.getValue() + " ##"));
- }
- }
-
}
diff --git a/apache-rat-core/src/test/java/org/apache/rat/analysis/license/OASISLicenseTest.java b/apache-rat-core/src/test/java/org/apache/rat/analysis/license/OASISLicenseTest.java
index 7e4692185..a439827c2 100644
--- a/apache-rat-core/src/test/java/org/apache/rat/analysis/license/OASISLicenseTest.java
+++ b/apache-rat-core/src/test/java/org/apache/rat/analysis/license/OASISLicenseTest.java
@@ -18,100 +18,33 @@
*/
package org.apache.rat.analysis.license;
-import org.apache.commons.io.IOUtils;
-import org.apache.rat.api.Document;
-import org.apache.rat.document.MockLocation;
-import org.apache.rat.report.claim.impl.xml.MockClaimReporter;
-import org.apache.rat.test.utils.Resources;
-import org.junit.Before;
-import org.junit.Test;
+import java.util.stream.Stream;
-import java.io.BufferedReader;
-import java.io.StringReader;
+import org.junit.jupiter.params.provider.Arguments;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
+public class OASISLicenseTest extends AbstractLicenseTest {
-public class OASISLicenseTest {
+ private static String id = "OASIS";
+ private static String name = "OASIS Open License";
+ private static String notes = "No modifications allowed";
+ private static String[][] targets = { { "fulltext",
+ "This document and translations of it may be copied and furnished to "
+ + "others and derivative works that comment on or otherwise explain it or assist "
+ + "in its implementation may be prepared copied published and distributed"
+ + "\\nCopyright OASIS Open, 1999" }, };
- private static final String LICENSE = "\n" +
- "\n";
-
- private OASISLicense license;
-
- private MockClaimReporter reporter;
-
- @Before
- public void setUp() throws Exception {
- license = new OASISLicense();
- reporter = new MockClaimReporter();
- }
-
- @Test
- public void match() throws Exception {
- BufferedReader in = null;
- try {
- in = new BufferedReader(new StringReader(LICENSE));
- String line = in.readLine();
- boolean result = false;
- final Document subject = new MockLocation("subject");
- while (line != null) {
- result = license.match(subject, line);
- line = in.readLine();
- }
- assertTrue("OASIS license should be matched", result);
- license.reset();
- result = license.match(subject, "New line");
- assertFalse("After reset, content should build up again", result);
- } finally {
- IOUtils.closeQuietly(in);
- }
+ public static Stream parameterProvider() {
+ return Stream.of(Arguments.of(id, id, name, notes, targets));
}
-
- @Test
- public void noMatch() throws Exception {
- BufferedReader in = null;
- try {
- in = Resources.getBufferedResourceReader("elements/Source.java");
- String line = in.readLine();
- boolean result = false;
- final Document subject = new MockLocation("subject");
- while (line != null) {
- result = license.match(subject, line);
- line = in.readLine();
- }
- assertFalse("OASIS license should not be matched", result);
- license.reset();
- } finally {
- IOUtils.closeQuietly(in);
- }
- }
-
+ /*
@Test(timeout = 2000) // may need to be adjusted if many more files are added
public void goodFiles() throws Exception {
DirectoryScanner.testFilesInDir("oasis/good", license, true);
}
-
+
@Test(timeout = 2000) // may need to be adjusted if many more files are added
public void baddFiles() throws Exception {
DirectoryScanner.testFilesInDir("oasis/bad", license, false);
}
-
+ */
}
diff --git a/apache-rat-core/src/test/java/org/apache/rat/analysis/license/W3CLicenseTest.java b/apache-rat-core/src/test/java/org/apache/rat/analysis/license/W3CLicenseTest.java
index 6397bbdee..2fde04c0c 100644
--- a/apache-rat-core/src/test/java/org/apache/rat/analysis/license/W3CLicenseTest.java
+++ b/apache-rat-core/src/test/java/org/apache/rat/analysis/license/W3CLicenseTest.java
@@ -15,45 +15,30 @@
* KIND, either express or implied. See the License for the *
* specific language governing permissions and limitations *
* under the License. *
- */
+ */
package org.apache.rat.analysis.license;
-import org.apache.rat.api.Document;
-import org.apache.rat.document.MockLocation;
-import org.apache.rat.report.claim.impl.xml.MockClaimReporter;
-import org.junit.Before;
-import org.junit.Test;
+import java.util.stream.Stream;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
+import org.junit.jupiter.params.provider.Arguments;
-public class W3CLicenseTest {
- public static final String COPYRIGHT_URL
- = "http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231";
-
- public static final String COPYRIGHT_URL_COMMENTED
- = "# http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231 #";
-
- public static final String COPYRIGHT_URL_XML
- = "";
-
- private W3CLicense license;
- private MockClaimReporter reporter;
+public class W3CLicenseTest extends AbstractLicenseTest {
- @Before
- public void setUp() throws Exception {
- license = new W3CLicense();
- reporter = new MockClaimReporter();
- }
+ private static String W3C_note = "Note that W3C requires a NOTICE.\n" + "All modifications require notes.\n"
+ + "See http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231.";
+ private static Arguments W3C = Arguments.of( "W3C", "W3C", "W3C Software Copyright", W3C_note,
+ new String[][] { { "fulltext", "http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231" },
+ { "spdx-tab", "SPDX-License-Identifier:\tW3C" },
+ { "spdx-space", "SPDX-License-Identifier: W3C" }, } );
- @Test
- public void match() throws Exception {
- final Document subject = new MockLocation("subject");
- assertTrue("Expected matcher to return license", license.match(subject, COPYRIGHT_URL));
- assertTrue("Expected matcher to return license", license.match(subject, COPYRIGHT_URL_COMMENTED));
- assertTrue("Expected matcher to return license", license.match(subject, COPYRIGHT_URL_XML));
- assertFalse("Return null if the license isn't matched", license.match(subject, "Bogus"));
- }
+ private static String W3CD_note = "Note that W3CD does not allow modifications.\n"
+ + "See http://www.w3.org/Consortium/Legal/2002/copyright-documents-20021231.";
+ private static Arguments W3CD = Arguments.of("W3CD", "W3CD","W3C Document Copyright", W3CD_note, new String[][] {
+ { "fulltext", "http://www.w3.org/Consortium/Legal/2002/copyright-documents-20021231" }, } );
+ public static Stream parameterProvider() {
+ return Stream.of(W3C, W3CD);
+ }
+
}
diff --git a/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/AndMatcherTest.java b/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/AndMatcherTest.java
new file mode 100644
index 000000000..a8ac49994
--- /dev/null
+++ b/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/AndMatcherTest.java
@@ -0,0 +1,78 @@
+/*
+ * 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.analysis.matchers;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.Arrays;
+
+import org.apache.rat.analysis.IHeaderMatcher;
+import org.apache.rat.analysis.IHeaderMatcher.State;
+import org.apache.rat.testhelpers.TestingMatcher;
+import org.junit.jupiter.api.Test;
+
+
+public class AndMatcherTest {
+
+ private void assertValues(IHeaderMatcher target, State hello, State world, State finalize) {
+ assertEquals(State.i, target.currentState());
+ assertEquals(hello, target.matches("hello"));
+ assertEquals(hello, target.currentState());
+ assertEquals(world, target.matches("world"));
+ assertEquals(world, target.currentState());
+ assertEquals(finalize, target.finalizeState());
+ assertEquals(finalize, target.currentState());
+ }
+
+ @Test
+ public void trueTest() {
+ IHeaderMatcher one = new TestingMatcher("one", true);
+ IHeaderMatcher two = new TestingMatcher("two", false, true);
+ AndMatcher target = new AndMatcher("Testing", Arrays.asList(one, two));
+ assertValues(target, State.i, State.t, State.t);
+ target.reset();
+ assertEquals(State.i, one.currentState());
+ assertEquals(State.i, two.currentState());
+ assertEquals(State.i, target.currentState());
+ }
+
+ @Test
+ public void falseTest() {
+ IHeaderMatcher one = new TestingMatcher("one", true);
+ IHeaderMatcher two = new TestingMatcher("two", false, false);
+ AndMatcher target = new AndMatcher("Testing", Arrays.asList(one, two));
+ assertValues(target, State.i, State.i, State.f);
+ target.reset();
+ assertEquals(State.i, one.currentState());
+ assertEquals(State.i, two.currentState());
+ assertEquals(State.i, target.currentState());
+ }
+
+ @Test
+ public void indeterminentTest() {
+ IHeaderMatcher one = new TestingMatcher("one", false, false);
+ IHeaderMatcher two = new TestingMatcher("two", false, false);
+ AndMatcher target = new AndMatcher("Testing", Arrays.asList(one, two));
+ assertValues(target, State.i, State.i, State.f);
+ target.reset();
+ assertEquals(State.i, one.currentState());
+ assertEquals(State.i, two.currentState());
+ assertEquals(State.i, target.currentState());
+ }
+}
diff --git a/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/CopyrightMatcherTest.java b/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/CopyrightMatcherTest.java
new file mode 100644
index 000000000..32f6820ee
--- /dev/null
+++ b/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/CopyrightMatcherTest.java
@@ -0,0 +1,119 @@
+/*
+ * 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.analysis.matchers;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Stream;
+
+import org.apache.rat.analysis.IHeaderMatcher.State;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+public class CopyrightMatcherTest {
+ private final static int NAME = 0;
+ private final static int TEXT = 1;
+ // to be added
+ private static String[] prefix = { "Copyright", "©", "(C)", "(c)" };
+
+ private final static String[] D = { "-d", " 1990-1991" };
+ private final static String[] DO = { "-d-o", " 1990-1991 an owner" };
+ private final static String[] OD = { "-o-d", " an owner 1990-1991" };
+ private final static String[] DOS = { "-d-o-s", " 1990 - 1991 an owner" };
+ private final static String[] ODS = { "-o-d-s", " an owner 1990 - 1991" };
+ private final static String[] S = { "-s", " 1990" };
+ private final static String[] O = { "-o", " an owner" };
+ private final static String[] OS = { "-o-s", " an owner 1990" };
+ private final static String[] SO = { "-s-o", " 1990 an owner" };
+
+ private static final int TOTAL_TESTS = prefix.length * 9;
+
+ static Arguments startStopOwner = Arguments.of("start-stop-owner", "1990", "1991", "an owner",
+ expandResults( DO, OD, DOS, ODS) , expandResults( D, S, O, OS, SO ));
+ static Arguments startOwner = Arguments.of( "start-owner", "1990", null, "an owner",
+ expandResults( OS, SO, OD, ODS ), expandResults( D, DO, DOS, S, O ) );
+ static Arguments start = Arguments.of("start", "1990", null, null, expandResults(D, DO, DOS, S, SO ),
+ expandResults(OD, ODS, O, OS ) );
+ static Arguments owner = Arguments.of("owner", null, null, "an owner", expandResults( O, OD, ODS, OS ),
+expandResults( DO, DOS, S, D, SO ) );
+ static Arguments nada = Arguments.of("nada", null, null, null, expandResults( D, DO, DOS, S, SO ),
+ expandResults( OD, ODS, O, OS ) );
+
+
+
+ public static Stream parameterProvider() {
+ return Stream.of( startStopOwner, startOwner, start, owner, nada);
+ }
+
+ private static String[][] expandResults( String[]...args) {
+ List arry = new ArrayList<>();
+ for (String pfx : prefix) {
+ Arrays.stream(args).map(origin -> new String[] { pfx + origin[0], pfx + origin[1] })
+ .forEach(arry::add);
+ }
+ return arry.toArray(new String[arry.size()][2]);
+ }
+
+ private static void verify(String testName, String[][] pass, String[][] fail) {
+ assertEquals(TOTAL_TESTS, pass.length + fail.length, "Wrong number of pass/fail tests");
+ Set passSet = new HashSet();
+ Arrays.stream(pass).forEach(s -> passSet.add(s[0]));
+ Set failSet = new HashSet();
+ Arrays.stream(fail).forEach(s -> failSet.add(s[0]));
+ for (String s : passSet) {
+ assertFalse(failSet.contains(s), ()->String.format("%s is in both pass and fail sets for %s", s, testName));
+ }
+ }
+
+ @ParameterizedTest
+ @MethodSource("parameterProvider")
+ public void testPass(String testName, String start, String stop, String owner, String[][] pass,
+ String[][] fail) {
+ verify(testName, pass, fail);
+ CopyrightMatcher matcher = new CopyrightMatcher(start, stop, owner);
+ for (String[] target : pass) {
+ assertEquals(State.i, matcher.currentState(), ()->String.format("%s:%s failed", testName, target[NAME]));
+ assertEquals(State.t, matcher.matches(target[TEXT]), ()->String.format("%s:%s failed", testName, target[NAME]));
+ matcher.reset();
+ assertEquals(State.i, matcher.currentState(),()->String.format("%s:%s failed", testName, target[NAME]));
+ }
+ }
+
+ @ParameterizedTest
+ @MethodSource("parameterProvider")
+ public void testFail(String testName, String start, String stop, String owner, String[][] pass,
+ String[][] fail) {
+ verify(testName, pass, fail);
+ CopyrightMatcher matcher = new CopyrightMatcher(start, stop, owner);
+ for (String[] target : fail) {
+ assertEquals( State.i, matcher.currentState(), ()->String.format("%s:%s passed", testName, target[NAME]));
+ assertEquals( State.i, matcher.matches(target[TEXT]), ()->String.format("%s:%s passed", testName, target[NAME]));
+ assertEquals( State.f, matcher.finalizeState(), ()->String.format("%s:%s passed", testName, target[NAME]));
+ matcher.reset();
+ assertEquals( State.i, matcher.currentState(), ()->String.format("%s:%s passed", testName, target[NAME]));
+ }
+ }
+}
diff --git a/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/FullTextMatcherTest.java b/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/FullTextMatcherTest.java
new file mode 100644
index 000000000..03a3251c9
--- /dev/null
+++ b/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/FullTextMatcherTest.java
@@ -0,0 +1,76 @@
+/*
+ * 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.analysis.matchers;
+
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.apache.rat.analysis.IHeaderMatcher.State;
+
+public class FullTextMatcherTest {
+
+ FullTextMatcher target = new FullTextMatcher("Hello world");
+
+ @BeforeEach
+ public void setup() {
+ target.reset();
+ }
+
+ @Test
+ public void testMatch() {
+ assertEquals( State.i, target.currentState());
+ assertEquals( State.i, target.matches("what in the world"));
+ assertEquals( State.i, target.currentState());
+ assertEquals( State.t, target.matches("hello world"));
+ assertEquals( State.t, target.currentState());
+ assertEquals( State.t, target.finalizeState());
+ assertEquals( State.t, target.currentState());
+ target.reset();
+ assertEquals( State.i, target.currentState());
+ }
+
+ @Test
+ public void testNoMatch() {
+ assertEquals( State.i, target.currentState());
+ assertEquals( State.i, target.matches("what in the world"));
+ assertEquals( State.i, target.currentState());
+ assertEquals( State.i, target.matches("hello there"));
+ assertEquals( State.i, target.currentState());
+ assertEquals( State.f, target.finalizeState());
+ assertEquals( State.f, target.currentState());
+ target.reset();
+ assertEquals( State.i, target.currentState());
+ }
+
+ @Test
+ public void testTrueIsAlwaysTrue() {
+ assertEquals( State.i, target.currentState());
+ assertEquals( State.t, target.matches("hello world"));
+ assertEquals( State.t, target.currentState());
+ assertEquals( State.t, target.matches("A non matching line"));
+ assertEquals( State.t, target.currentState());
+ assertEquals( State.t, target.finalizeState());
+ assertEquals( State.t, target.currentState());
+ target.reset();
+ assertEquals( State.i, target.currentState());
+ }
+}
diff --git a/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/NotMatcherTest.java b/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/NotMatcherTest.java
new file mode 100644
index 000000000..806b6573d
--- /dev/null
+++ b/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/NotMatcherTest.java
@@ -0,0 +1,63 @@
+/*
+ * 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.analysis.matchers;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.apache.rat.analysis.IHeaderMatcher;
+import org.apache.rat.analysis.IHeaderMatcher.State;
+import org.apache.rat.testhelpers.TestingMatcher;
+import org.junit.jupiter.api.Test;
+
+public class NotMatcherTest {
+
+ private void assertValues(IHeaderMatcher target, State hello, State world, State finalize) {
+ assertEquals(State.i, target.currentState());
+ assertEquals( hello, target.matches("hello"), "hello match");
+ assertEquals( hello, target.currentState(), "hello current");
+ assertEquals(world, target.matches("world"), "world match");
+ assertEquals( world, target.currentState(), "world current");
+ assertEquals(finalize, target.finalizeState(), "finalize match");
+ assertEquals(finalize, target.currentState(), "finalize current");
+ }
+
+ @Test
+ public void testTrue() {
+ IHeaderMatcher one = new TestingMatcher("one", true);
+ NotMatcher target = new NotMatcher("Testing", one);
+ assertValues(target, State.f, State.f, State.f);
+
+ one = new TestingMatcher("one", false, true);
+ target = new NotMatcher("Testing", one);
+ assertValues(target, State.i, State.f, State.f);
+ target.reset();
+ assertEquals(State.i, target.currentState());
+ }
+
+ @Test
+ public void testFalse() {
+ TestingMatcher one = new TestingMatcher("one", false, false);
+ one.finalState = State.t;
+ NotMatcher target = new NotMatcher("Testing", one);
+ assertValues(target, State.i, State.i, State.f);
+ target.reset();
+ assertEquals(State.i, target.currentState());
+
+ }
+}
diff --git a/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/OrMatcherTest.java b/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/OrMatcherTest.java
new file mode 100644
index 000000000..81478b37b
--- /dev/null
+++ b/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/OrMatcherTest.java
@@ -0,0 +1,77 @@
+/*
+ * 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.analysis.matchers;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.Arrays;
+
+import org.apache.rat.analysis.IHeaderMatcher;
+import org.apache.rat.analysis.IHeaderMatcher.State;
+import org.apache.rat.testhelpers.TestingMatcher;
+import org.junit.jupiter.api.Test;
+
+public class OrMatcherTest {
+
+ private void assertValues(IHeaderMatcher target, State hello, State world, State finalize) {
+ assertEquals(State.i, target.currentState());
+ assertEquals( hello, target.matches("hello"), "hello match");
+ assertEquals( hello, target.currentState(), "hello current");
+ assertEquals(world, target.matches("world"), "world match");
+ assertEquals( world, target.currentState(), "world current");
+ assertEquals(finalize, target.finalizeState(), "finalize match");
+ assertEquals(finalize, target.currentState(), "finalize current");
+ }
+
+ @Test
+ public void trueTest() {
+ IHeaderMatcher one = new TestingMatcher("one", false, false);
+ IHeaderMatcher two = new TestingMatcher("two", false, true);
+ OrMatcher target = new OrMatcher("Testing", Arrays.asList(one, two));
+ assertValues(target, State.i, State.t, State.t);
+ target.reset();
+ assertEquals(State.i, one.currentState());
+ assertEquals(State.i, two.currentState());
+ assertEquals(State.i, target.currentState());
+ }
+
+ @Test
+ public void falseTest() {
+ IHeaderMatcher one = new TestingMatcher("one", false, false);
+ IHeaderMatcher two = new TestingMatcher("two", false, false);
+ OrMatcher target = new OrMatcher("Testing", Arrays.asList(one, two));
+ assertValues(target, State.i, State.i, State.f);
+ target.reset();
+ assertEquals(State.i, one.currentState());
+ assertEquals(State.i, two.currentState());
+ assertEquals(State.i, target.currentState());
+ }
+
+ @Test
+ public void indeterminentTest() {
+ IHeaderMatcher one = new TestingMatcher("one", false, false);
+ IHeaderMatcher two = new TestingMatcher("two", false, false);
+ OrMatcher target = new OrMatcher("Testing", Arrays.asList(one, two));
+ assertValues(target, State.i, State.i, State.f);
+ target.reset();
+ assertEquals(State.i, one.currentState());
+ assertEquals(State.i, two.currentState());
+ assertEquals(State.i, target.currentState());
+ }
+}
diff --git a/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/SPDXMatcherTest.java b/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/SPDXMatcherTest.java
new file mode 100644
index 000000000..124ed357b
--- /dev/null
+++ b/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/SPDXMatcherTest.java
@@ -0,0 +1,86 @@
+/*
+ * 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.analysis.matchers;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.apache.rat.analysis.IHeaderMatcher;
+import org.apache.rat.analysis.IHeaderMatcher.State;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+public class SPDXMatcherTest {
+
+ IHeaderMatcher target = SPDXMatcherFactory.INSTANCE.create("hello");
+
+ @BeforeEach
+ public void setup() {
+ target.reset();
+ }
+
+ @Test
+ public void testMatch() {
+ assertEquals(State.i, target.currentState());
+ assertEquals(State.i, target.matches("SPDX-License-Identifier: Apache-2"));
+ assertEquals(State.i, target.currentState());
+ assertEquals(State.t, target.matches("SPDX-License-Identifier: hello"));
+ assertEquals(State.t, target.currentState());
+ assertEquals(State.t, target.finalizeState());
+ assertEquals(State.t, target.currentState());
+ target.reset();
+ assertEquals(State.i, target.currentState());
+ }
+
+ @Test
+ public void testNoMatch() {
+ assertEquals(State.i, target.currentState());
+ assertEquals(State.i, target.matches("SPDX-License-Identifier: Apache-2"));
+ assertEquals(State.i, target.currentState());
+ assertEquals(State.i, target.matches("SPDX-License-Identifier: MIT"));
+ assertEquals(State.i, target.currentState());
+ assertEquals(State.f, target.finalizeState());
+ assertEquals(State.f, target.currentState());
+ target.reset();
+ assertEquals(State.i, target.currentState());
+ }
+
+ @Test
+ public void testTrueIsAlwaysTrue() {
+ assertEquals(State.i, target.currentState());
+ assertEquals(State.t, target.matches("SPDX-License-Identifier: hello"));
+ assertEquals(State.t, target.currentState());
+ assertEquals(State.t, target.matches("SPDX-License-Identifier: Apache-2"));
+ assertEquals(State.t, target.currentState());
+ assertEquals(State.t, target.finalizeState());
+ assertEquals(State.t, target.currentState());
+ target.reset();
+ assertEquals(State.i, target.currentState());
+ }
+
+ @Test
+ public void testResetClearsLastMatch() {
+
+ assertEquals(State.i, target.currentState());
+ assertEquals(State.t, target.matches("SPDX-License-Identifier: hello"));
+ assertEquals(State.t, target.currentState());
+ target.reset();
+ assertEquals(State.i, target.currentState());
+ assertEquals(State.i, target.matches("Something weird"));;
+ }
+}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/license/W3CLicense.java b/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/SimpleCopyrightTests.java
similarity index 55%
rename from apache-rat-core/src/main/java/org/apache/rat/analysis/license/W3CLicense.java
rename to apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/SimpleCopyrightTests.java
index 4325397ef..b836f6470 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/analysis/license/W3CLicense.java
+++ b/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/SimpleCopyrightTests.java
@@ -15,22 +15,29 @@
* KIND, either express or implied. See the License for the *
* specific language governing permissions and limitations *
* under the License. *
- */
-package org.apache.rat.analysis.license;
+ */
+package org.apache.rat.analysis.matchers;
-import org.apache.rat.api.MetaData;
+import static org.junit.jupiter.api.Assertions.assertEquals;
-public class W3CLicense extends SimplePatternBasedLicense {
+import org.apache.rat.analysis.IHeaderMatcher.State;
+import org.junit.jupiter.api.Test;
- private static final String NOTES
- = "Note that W3C requires a NOTICE. All modifications require notes. See http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231.";
- private static final String COPYRIGHT_URL
- = "http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231";
+public class SimpleCopyrightTests {
+
+ CopyrightMatcher target = new CopyrightMatcher(null,null,null);
- public W3CLicense() {
- super(MetaData.RAT_LICENSE_FAMILY_CATEGORY_DATUM_W3C,
- MetaData.RAT_LICENSE_FAMILY_NAME_DATUM_W3C_SOFTWARE_COPYRIGHT, NOTES,
- new String[]{COPYRIGHT_URL});
+ @Test
+ public void testTrueIsAlwaysTrue() {
+ assertEquals( State.i, target.currentState());
+ assertEquals( State.t, target.matches("hello Copyright 1999"));
+ assertEquals( State.t, target.currentState());
+ assertEquals( State.t, target.matches("A non matching line"));
+ assertEquals( State.t, target.currentState());
+ assertEquals( State.t, target.finalizeState());
+ assertEquals( State.t, target.currentState());
+ target.reset();
+ assertEquals( State.i, target.currentState());
}
}
diff --git a/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/SimpleRegexMatcherTest.java b/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/SimpleRegexMatcherTest.java
new file mode 100644
index 000000000..53dee7607
--- /dev/null
+++ b/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/SimpleRegexMatcherTest.java
@@ -0,0 +1,77 @@
+/*
+ * 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.analysis.matchers;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.regex.Pattern;
+
+import org.apache.rat.analysis.IHeaderMatcher.State;
+
+public class SimpleRegexMatcherTest {
+
+ SimpleRegexMatcher target = new SimpleRegexMatcher(Pattern.compile("hello\\sworld"));
+
+ @BeforeEach
+ public void setup() {
+ target.reset();
+ }
+
+ @Test
+ public void testMatch() {
+ assertEquals( State.i, target.currentState());
+ assertEquals( State.i, target.matches("what in the world"));
+ assertEquals( State.i, target.currentState());
+ assertEquals( State.t, target.matches("hello world"));
+ assertEquals( State.t, target.currentState());
+ assertEquals( State.t, target.finalizeState());
+ assertEquals( State.t, target.currentState());
+ target.reset();
+ assertEquals( State.i, target.currentState());
+ }
+
+ @Test
+ public void testNoMatch() {
+ assertEquals( State.i, target.currentState());
+ assertEquals( State.i, target.matches("what in the world"));
+ assertEquals( State.i, target.currentState());
+ assertEquals( State.i, target.matches("hello there"));
+ assertEquals( State.i, target.currentState());
+ assertEquals( State.f, target.finalizeState());
+ assertEquals( State.f, target.currentState());
+ target.reset();
+ assertEquals( State.i, target.currentState());
+ }
+
+ @Test
+ public void testTrueIsAlwaysTrue() {
+ assertEquals( State.i, target.currentState());
+ assertEquals( State.t, target.matches("hello world"));
+ assertEquals( State.t, target.currentState());
+ assertEquals( State.t, target.matches("A non matching line"));
+ assertEquals( State.t, target.currentState());
+ assertEquals( State.t, target.finalizeState());
+ assertEquals( State.t, target.currentState());
+ target.reset();
+ assertEquals( State.i, target.currentState());
+ }
+}
diff --git a/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/SimpleTextMatcherTest.java b/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/SimpleTextMatcherTest.java
new file mode 100644
index 000000000..2ad73d6bf
--- /dev/null
+++ b/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/SimpleTextMatcherTest.java
@@ -0,0 +1,88 @@
+/*
+ * 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.analysis.matchers;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.apache.rat.analysis.IHeaderMatcher.State;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+public class SimpleTextMatcherTest {
+
+ SimpleTextMatcher target;
+
+ @BeforeEach
+ public void setup() {
+ target = new SimpleTextMatcher("hello");
+ }
+
+ @Test
+ public void testMatch() {
+ assertEquals(State.i, target.currentState());
+ assertEquals(State.i, target.matches("what in the world"));
+ assertEquals(State.i, target.currentState());
+ assertEquals(State.t, target.matches("hello world"));
+ assertEquals(State.t, target.currentState());
+ assertEquals(State.t, target.finalizeState());
+ assertEquals(State.t, target.currentState());
+ target.reset();
+ assertEquals(State.i, target.currentState());
+ }
+
+ @Test
+ public void testNoMatch() {
+ assertEquals(State.i, target.currentState());
+ assertEquals(State.i, target.matches("what in the world"));
+ assertEquals(State.i, target.currentState());
+ assertEquals(State.i, target.matches("hell o'there"));
+ assertEquals(State.i, target.currentState());
+ assertEquals(State.f, target.finalizeState());
+ assertEquals(State.f, target.currentState());
+ target.reset();
+ assertEquals(State.i, target.currentState());
+ }
+
+ @Test
+ public void testTrueIsAlwaysTrue() {
+ assertEquals(State.i, target.currentState());
+ assertEquals(State.t, target.matches("hello world"));
+ assertEquals(State.t, target.currentState());
+ assertEquals(State.t, target.matches("A non matching line"));
+ assertEquals(State.t, target.currentState());
+ assertEquals(State.t, target.finalizeState());
+ assertEquals(State.t, target.currentState());
+ target.reset();
+ assertEquals(State.i, target.currentState());
+ }
+
+ @Test
+ public void testIndeterminent() {
+ target = new SimpleTextMatcher("not a match");
+ assertEquals(State.i, target.currentState());
+ assertEquals(State.i, target.matches("hello world"));
+ assertEquals(State.i, target.currentState());
+ assertEquals(State.i, target.matches("A non matching line"));
+ assertEquals(State.i, target.currentState());
+ assertEquals(State.f, target.finalizeState());
+ assertEquals(State.f, target.currentState());
+ target.reset();
+ assertEquals(State.i, target.currentState());
+ }
+}
diff --git a/apache-rat-core/src/test/java/org/apache/rat/analysis/util/MatcherMultiplexerTest.java b/apache-rat-core/src/test/java/org/apache/rat/analysis/util/MatcherMultiplexerTest.java
deleted file mode 100644
index 68d89105c..000000000
--- a/apache-rat-core/src/test/java/org/apache/rat/analysis/util/MatcherMultiplexerTest.java
+++ /dev/null
@@ -1,78 +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.analysis.util;
-
-import org.apache.rat.analysis.IHeaderMatcher;
-import org.apache.rat.analysis.MockLicenseMatcher;
-import org.apache.rat.api.Document;
-import org.apache.rat.document.MockLocation;
-import org.apache.rat.report.claim.impl.xml.MockClaimReporter;
-import org.junit.Before;
-import org.junit.Test;
-
-import java.util.Arrays;
-
-import static org.junit.Assert.assertEquals;
-
-public class MatcherMultiplexerTest {
-
- private static final String LINE_ONE = "Line One";
- private static final String LINE_TWO = "Line Two";
-
- private MockClaimReporter reporter;
- private MockLicenseMatcher matcherOne;
- private MockLicenseMatcher matcherTwo;
-
- private HeaderMatcherMultiplexer multiplexer;
-
- @Before
- public void setUp() {
- matcherOne = new MockLicenseMatcher();
- matcherTwo = new MockLicenseMatcher();
- multiplexer = new HeaderMatcherMultiplexer(Arrays.asList(matcherOne, matcherTwo));
- reporter = new MockClaimReporter();
- }
-
- @Test
- public void testMatcherLine() throws Exception {
- matcherOne.result = false;
- matcherTwo.result = false;
- final Document subject = new MockLocation("subject");
- multiplexer.match(subject, LINE_ONE);
- assertEquals("One line", 1, matcherOne.lines.size());
- assertEquals("Same as line passed", LINE_ONE, matcherOne.lines.get(0));
- assertEquals("One line", 1, matcherTwo.lines.size());
- assertEquals("Same as line passed", LINE_ONE, matcherTwo.lines.get(0));
- multiplexer.match(subject, LINE_TWO);
- assertEquals("One line", 2, matcherOne.lines.size());
- assertEquals("Same as line passed", LINE_TWO, matcherOne.lines.get(1));
- assertEquals("One line", 2, matcherTwo.lines.size());
- assertEquals("Same as line passed", LINE_TWO, matcherTwo.lines.get(1));
- }
-
- @Test
- public void testReset() {
- multiplexer.reset();
- assertEquals("Reset once", 1, matcherOne.resets);
- assertEquals("Reset once", 1, matcherTwo.resets);
- multiplexer.reset();
- assertEquals("Reset twice", 2, matcherOne.resets);
- assertEquals("Reset twice", 2, matcherTwo.resets);
- }
-}
diff --git a/apache-rat-core/src/test/java/org/apache/rat/annotation/TestLicenseAppender.java b/apache-rat-core/src/test/java/org/apache/rat/annotation/TestLicenseAppender.java
index 71e09d965..188ca7949 100644
--- a/apache-rat-core/src/test/java/org/apache/rat/annotation/TestLicenseAppender.java
+++ b/apache-rat-core/src/test/java/org/apache/rat/annotation/TestLicenseAppender.java
@@ -18,11 +18,8 @@
*/
package org.apache.rat.annotation;
-import org.apache.commons.io.IOUtils;
-import org.apache.rat.test.utils.Resources;
-import org.junit.ClassRule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
import java.io.BufferedReader;
import java.io.File;
@@ -31,12 +28,17 @@
import java.io.IOException;
import java.io.Writer;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
+import org.apache.commons.io.FileUtils;
+import org.apache.rat.test.utils.Resources;
+import org.apache.rat.utils.DefaultLog;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
public class TestLicenseAppender {
- @ClassRule
- public static final TemporaryFolder baseTempFolder = new TemporaryFolder();
+
+ @TempDir
+ private File baseTempFolder;
+
private static final String FIRST_LICENSE_LINE = " Licensed to the Apache Software Foundation (ASF) under one";
@@ -48,89 +50,46 @@ private interface NewFileReader {
void readFile(BufferedReader r) throws IOException;
}
- private static String getTemporaryFileWithName(String fileName) throws IOException {
+ private String getTemporaryFileWithName(String fileName) throws IOException {
if (fileName != null) {
- return baseTempFolder.newFile(fileName).getAbsolutePath();
- } else {
- return baseTempFolder.newFile().getAbsolutePath();
+ return new File(baseTempFolder,fileName).getAbsolutePath();
}
+ return File.createTempFile("tla", null, baseTempFolder).getAbsolutePath();
}
private static void createTestFile(String fileName,
FileCreator creator)
throws IOException {
- FileWriter w = null;
- try {
- creator.createFile(w = new FileWriter(fileName));
- } finally {
- IOUtils.closeQuietly(w);
- }
- }
-
- private static void tryToDelete(File f) {
- if (f != null && f.exists() && !f.delete()) {
- f.deleteOnExit();
+ try (FileWriter w = new FileWriter(fileName)) {
+ creator.createFile(w);
}
}
- private static void commonTestTemplate(String relativeName,
+ private void commonTestTemplate(String relativeName,
FileCreator creator,
NewFileReader reader)
throws IOException {
String name = getTemporaryFileWithName(relativeName);
- try {
+
createTestFile(name, creator);
ApacheV2LicenseAppender appender =
- new ApacheV2LicenseAppender();
+ new ApacheV2LicenseAppender(DefaultLog.INSTANCE);
appender.append(new File(name));
- BufferedReader r = null;
- try {
- r = new BufferedReader(new FileReader(name + ".new"));
+ try (BufferedReader r = new BufferedReader(new FileReader(name + ".new"))){
reader.readFile(r);
- } finally {
- IOUtils.closeQuietly(r);
}
- } finally {
- tryToDelete(new File(name));
- tryToDelete(new File(name + ".new"));
- }
+ FileUtils.delete( new File(name+".new"));
+ FileUtils.delete( new File(name));
}
- private static NewFileReader checkLines(final String firstLine,
- final String secondLine) {
+ private static NewFileReader checkLines(final String ... lines) {
return new NewFileReader() {
public void readFile(BufferedReader r) throws IOException {
- String line = r.readLine();
- assertEquals("First line is incorrect",
- firstLine, line);
- if (secondLine != null) {
- line = r.readLine();
- assertEquals("Second line is incorrect",
- secondLine, line);
- }
- }
- };
- }
-
- private static NewFileReader checkLines(final String firstLine,
- final String secondLine,
- final String thirdLine) {
- return new NewFileReader() {
- public void readFile(BufferedReader r) throws IOException {
- String line = r.readLine();
- assertEquals("First line is incorrect",
- firstLine, line);
- if (secondLine != null) {
- line = r.readLine();
- assertEquals("Second line is incorrect",
- secondLine, line);
- }
- if (thirdLine != null) {
- line = r.readLine();
- assertEquals("Third line is incorrect",
- thirdLine, line);
+ for (int i=0; i\n");
}
},
- checkLines(commentLine, null));
+ checkLines(commentLine));
}
@Test
@@ -254,7 +212,7 @@ public void createFile(Writer writer)
writer.write("}\n");
}
},
- checkLines(firstLine, null));
+ checkLines(firstLine));
}
@Test
@@ -270,7 +228,7 @@ public void createFile(Writer writer)
writer.write("}\n");
}
},
- checkLines(firstLine, null));
+ checkLines(firstLine));
}
@Test
@@ -286,7 +244,7 @@ public void createFile(Writer writer)
writer.write(" of any importance\n");
}
},
- checkLines(firstLine, null));
+ checkLines(firstLine));
}
@Test
@@ -302,7 +260,7 @@ public void createFile(Writer writer)
writer.write("cool = true\n");
}
},
- checkLines(firstLine, null));
+ checkLines(firstLine));
}
@Test
@@ -324,16 +282,16 @@ public void createFile(Writer writer)
public void readFile(BufferedReader reader)
throws IOException {
String line = reader.readLine();
- assertEquals("First line is incorrect",
- newFirstLine, line);
+ assertEquals(
+ newFirstLine, line, "First line is incorrect");
while ((line = reader.readLine()) != null) {
if (line.length() == 0) {
line = reader.readLine();
break;
}
}
- assertEquals("Package line is incorrect",
- firstLine, line);
+ assertEquals(
+ firstLine, line, "Package line is incorrect");
}
});
}
@@ -351,7 +309,7 @@ public void createFile(Writer writer)
writer.write("end\n");
}
},
- checkLines(firstLine, null));
+ checkLines(firstLine));
}
@Test
@@ -383,7 +341,7 @@ public void createFile(Writer writer)
writer.write("print \"Hello world\"\n");
}
},
- checkLines(firstLine, null));
+ checkLines(firstLine));
}
@Test
@@ -431,7 +389,7 @@ public void createFile(Writer writer)
writer.write("puts \"Hello world\"\n");
}
},
- checkLines(firstLine, null));
+ checkLines(firstLine));
}
@Test
@@ -482,7 +440,7 @@ public void createFile(Writer writer)
writer.write("}\n");
}
},
- checkLines(firstLine, null));
+ checkLines(firstLine));
}
@Test
@@ -498,7 +456,7 @@ public void createFile(Writer writer)
writer.write(" }\n");
}
},
- checkLines(firstLine, null));
+ checkLines(firstLine));
}
@Test
@@ -515,7 +473,7 @@ public void createFile(Writer writer)
writer.write("}\n");
}
},
- checkLines(firstLine, null));
+ checkLines(firstLine));
}
@Test
@@ -542,28 +500,21 @@ public void createFile(Writer writer)
@Test
public void fileWithBOM() throws IOException {
File f = Resources.getResourceFile("violations/FilterTest.cs");
- try {
- ApacheV2LicenseAppender appender =
- new ApacheV2LicenseAppender();
- appender.append(f);
-
- BufferedReader r = null;
- try {
- r = new BufferedReader(new FileReader(f.getAbsolutePath()
- + ".new"));
- assertEquals("/*", r.readLine());
- String line = null;
- while ((line = r.readLine()) != null) {
- if (line.trim().length() == 0) {
- break;
- }
+
+ ApacheV2LicenseAppender appender =
+ new ApacheV2LicenseAppender(DefaultLog.INSTANCE);
+ appender.append(f);
+
+ try (BufferedReader r = new BufferedReader(new FileReader(f.getAbsolutePath()
+ + ".new"))) {
+ assertEquals("/*", r.readLine());
+ String line = null;
+ while ((line = r.readLine()) != null) {
+ if (line.trim().length() == 0) {
+ break;
}
- assertEquals("#if NET_2_0", r.readLine());
- } finally {
- IOUtils.closeQuietly(r);
}
- } finally {
- tryToDelete(new File(f.getAbsolutePath() + ".new"));
+ assertEquals("#if NET_2_0", r.readLine());
}
}
@@ -610,19 +561,8 @@ public void createFile(Writer writer)
writer.write("EndProject\n");
}
},
- new NewFileReader() {
- public void readFile(BufferedReader r) throws IOException {
- String line = r.readLine();
- assertEquals("First line is incorrect",
- firstLine, line);
- line = r.readLine();
- assertEquals("Second line is incorrect",
- secondLine, line);
- line = r.readLine();
- assertEquals("Third line is incorrect",
- thirdLine, line);
- }
- });
+ checkLines(firstLine, secondLine, thirdLine)
+ );
}
@Test
@@ -663,19 +603,8 @@ public void createFile(Writer writer)
writer.write("EndGlobal \n");
}
},
- new NewFileReader() {
- public void readFile(BufferedReader r) throws IOException {
- String line = r.readLine();
- assertEquals("First line is incorrect",
- firstLine, line);
- line = r.readLine();
- assertEquals("Second line is incorrect",
- secondLine, line);
- line = r.readLine();
- assertEquals("Third line is incorrect",
- thirdLine, line);
- }
- });
+ checkLines(firstLine, secondLine, thirdLine)
+ );
}
@Test
@@ -718,20 +647,30 @@ public void createFile(Writer writer)
writer.write("EndGlobal \n");
}
},
+ checkLines(firstLine, secondLine, thirdLine, forthLine)
+ );
+ }
+
+ @Test
+ public void addLicenseMarkdown() throws IOException {
+ String filename = "tmp.md";
+
+ commonTestTemplate(filename, new FileCreator() {
+ public void createFile(Writer writer)
+ throws IOException {
+ writer.write("## This is the first header\n");
+ writer.write(" * this is a list entry\n");
+ writer.write(" * this is another list entry\n");
+ writer.write(" ");
+ writer.write("## This is the second header\n");
+ }
+ },
new NewFileReader() {
public void readFile(BufferedReader r) throws IOException {
String line = r.readLine();
- assertEquals("First line is incorrect",
- firstLine, line);
- line = r.readLine();
- assertEquals("Second line is incorrect",
- secondLine, line);
- line = r.readLine();
- assertEquals("Third line is incorrect",
- thirdLine, line);
+ assertEquals(
+ "
+ src/it/CustomLicense/src/**/
**/.bzrignore
@@ -97,40 +103,28 @@
- org.eclipse.m2e
- lifecycle-mapping
- 1.0.0
-
-
-
-
-
-
- org.apache.maven.plugins
-
-
- maven-plugin-plugin
-
- [3.3,)
-
- descriptor
- helpmojo
-
-
-
-
-
-
-
-
-
-
-
- org.apache.maven.plugins
- maven-surefire-plugin
+ org.eclipse.m2e
+ lifecycle-mapping
+ 1.0.0
- 1
- -Dfile.encoding=ISO-8859-1
+
+
+
+
+ org.apache.maven.plugins
+ maven-plugin-plugin
+ [3.3,)
+
+ descriptor
+ helpmojo
+
+
+
+
+
+
+
+
@@ -144,6 +138,7 @@
${project.build.directory}/local-repo
src/it/settings.xml
verify
+ true
@@ -157,19 +152,34 @@
-
org.apache.rat
apache-rat-core
+ ${project.parent.version}
- junit
- junit
+ org.apache.rat
+ apache-rat-core
+ ${project.parent.version}
+ test-jar
+ tests
+ test
org.mockito
mockito-core
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-api
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-engine
+ test
org.apache.maven.plugin-tools
@@ -181,31 +191,35 @@
org.apache.maven
maven-artifact
${mavenVersion}
+ provided
org.apache.maven
- maven-artifact-manager
+ maven-model
${mavenVersion}
+ provided
org.apache.maven
- maven-model
+ maven-plugin-api
${mavenVersion}
+ provided
org.apache.maven
- maven-plugin-api
+ maven-core
${mavenVersion}
provided
org.apache.maven
- maven-project
+ maven-settings
${mavenVersion}
+ test
org.apache.maven
- maven-settings
+ maven-compat
${mavenVersion}
test
@@ -214,6 +228,10 @@
doxia-core
${doxiaVersion}
+
+ org.codehaus.plexus
+ plexus-container-default
+
xerces
xercesImpl
@@ -239,11 +257,23 @@
org.apache.maven.doxia
doxia-integration-tools
${doxiaSitetoolsVersion}
+
+
+ org.codehaus.plexus
+ plexus-container-default
+
+
org.apache.maven.doxia
doxia-site-renderer
${doxiaSitetoolsVersion}
+
+
+ org.codehaus.plexus
+ plexus-container-default
+
+
org.apache.maven.reporting
@@ -253,23 +283,38 @@
org.apache.maven.shared
maven-shared-utils
- 3.3.4
+ 3.4.2
- org.apache.maven.shared
+ org.apache.maven.plugin-testing
maven-plugin-testing-harness
- 1.1
+ 3.3.0
+ test
+
+
+ org.assertj
+ assertj-core
test
org.codehaus.plexus
plexus-utils
- 3.4.2
+ 3.5.1
org.apache.commons
commons-lang3
- 3.5
+
+
+ org.slf4j
+ slf4j-simple
+ 2.0.11
+ test
+
+
+ nl.basjes.gitignore
+ gitignore-reader
+ 1.3.1
diff --git a/apache-rat-plugin/src/it/CustomLicense/invoker.properties b/apache-rat-plugin/src/it/CustomLicense/invoker.properties
new file mode 100644
index 000000000..6e8c3479e
--- /dev/null
+++ b/apache-rat-plugin/src/it/CustomLicense/invoker.properties
@@ -0,0 +1,16 @@
+# 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.
+
+invoker.goals = clean apache-rat:check
diff --git a/apache-rat-plugin/src/it/CustomLicense/pom.xml b/apache-rat-plugin/src/it/CustomLicense/pom.xml
new file mode 100644
index 000000000..4a03c4872
--- /dev/null
+++ b/apache-rat-plugin/src/it/CustomLicense/pom.xml
@@ -0,0 +1,59 @@
+
+
+
+ 4.0.0
+ org.apache.rat.test
+ custom-license
+ 1.0
+
+
+
+ org.apache.rat
+ apache-rat-plugin
+ @pom.version@
+
+ false
+
+
+ CC
+ Creative Commons
+
+
+
+
+ CC
+ CC-BY-NC-ND
+
+ Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International
+
+ Attribution-NonCommercial-NoDerivatives
+
+
+
+
+ CC
+
+
+ pom.xml
+ invoker.properties
+
+
+
+
+
+
diff --git a/apache-rat-plugin/src/it/CustomLicense/src/main/java/nl/basjes/something/Something.java b/apache-rat-plugin/src/it/CustomLicense/src/main/java/nl/basjes/something/Something.java
new file mode 100644
index 000000000..4a7f38d95
--- /dev/null
+++ b/apache-rat-plugin/src/it/CustomLicense/src/main/java/nl/basjes/something/Something.java
@@ -0,0 +1,26 @@
+/*
+ * ***********************************************************************
+ * Ok, this file is really Apache _ licensed but it has a fake header
+ * that does not match the Apache rules to test custom license validation.
+ * ***********************************************************************
+ *
+ * Something toolkit
+ * Copyright (C) 2019-2024 Niels Basjes
+ *
+ * This work is licensed under the Creative Commons
+ * Attribution-NonCommercial-NoDerivatives 4.0 International License.
+ *
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://creativecommons.org/licenses/by-nc-nd/4.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.
+ */
+package nl.basjes.something;
+
+public class Something {
+ private static final String something = "No real code";
+}
diff --git a/apache-rat-plugin/src/it/RAT-268/module1/pom.xml b/apache-rat-plugin/src/it/RAT-268/module1/pom.xml
index 896861ec8..0cdc850c0 100644
--- a/apache-rat-plugin/src/it/RAT-268/module1/pom.xml
+++ b/apache-rat-plugin/src/it/RAT-268/module1/pom.xml
@@ -15,10 +15,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-
+
4.0.0
org.apache.rat.test
diff --git a/apache-rat-plugin/src/it/RAT-268/module3/pom.xml b/apache-rat-plugin/src/it/RAT-268/module3/pom.xml
index 2f41709fd..f7a4fb9a0 100644
--- a/apache-rat-plugin/src/it/RAT-268/module3/pom.xml
+++ b/apache-rat-plugin/src/it/RAT-268/module3/pom.xml
@@ -15,10 +15,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-
+
4.0.0
org.apache.rat.test
diff --git a/apache-rat-plugin/src/it/RAT-268/pom.xml b/apache-rat-plugin/src/it/RAT-268/pom.xml
index 8886a6c01..ae0df78b1 100644
--- a/apache-rat-plugin/src/it/RAT-268/pom.xml
+++ b/apache-rat-plugin/src/it/RAT-268/pom.xml
@@ -15,22 +15,17 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-
+
4.0.0
org.apache.rat.test
rat268
1.0
pom
-
module1
module2/module2.pom
module3/pom.xml
-
diff --git a/apache-rat-plugin/src/it/it1/pom.xml b/apache-rat-plugin/src/it/it1/pom.xml
index 58eea9b7b..ca62ab392 100644
--- a/apache-rat-plugin/src/it/it1/pom.xml
+++ b/apache-rat-plugin/src/it/it1/pom.xml
@@ -15,12 +15,9 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-
+
4.0.0
- org.apache.rat.test
+ org.codehaus.mojo.rat.test
it1
1.0
@@ -30,21 +27,83 @@
apache-rat-plugin
@pom.version@
+
+
+ YAL
+ Yet another license
+
+
+
+ YAL
+
-
- YAL__
- Yet Another Software License
-
-
- Yet Another License
-
+
+ MyLicense
+ YAL
+ Yet Another License
+
+
+ GEN
+ CpyrT
+ Copyright with tags
+
+
+ 1990
+ 1991
+ foo
+
+
+
+ GEN
+ RegxT
+ Regex with tag
+
+ regex tag
+
+
+ GEN
+ SpdxT
+ Spdx with tag
+
+ spxd-tag
+
+
+ GEN
+ TextT
+ Text with tag
+
+ text-tag
+
+
+ GEN
+ Not
+ Not testing
+
+
+ not test text
+
+
+
+ GEN
+ All
+ All testing
+
+
+ all test text
+ all spdx text
+
+
+
+ GEN
+ Any
+ Any testing
+
+
+ any test text
+ any spdx text
+
-
-
- Yet Another Software License
-
-
src.apt
diff --git a/apache-rat-plugin/src/it/it1/verify.groovy b/apache-rat-plugin/src/it/it1/verify.groovy
index 1d1080979..cdf9899c7 100644
--- a/apache-rat-plugin/src/it/it1/verify.groovy
+++ b/apache-rat-plugin/src/it/it1/verify.groovy
@@ -14,6 +14,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-content = new File( basedir, 'target/rat.txt' ).text
-assert content.contains( 'YAL__ src.apt' )
\ No newline at end of file
+f = new File( basedir, 'target/rat.txt' )
+assert f.exists()
+
+content = f.text
+
+assert content.contains( 'YAL src.apt' )
\ No newline at end of file
diff --git a/apache-rat-plugin/src/it/it4_RAT-168/pom.xml b/apache-rat-plugin/src/it/it4_RAT-168/pom.xml
index 0a419e3fa..471eeb3a4 100644
--- a/apache-rat-plugin/src/it/it4_RAT-168/pom.xml
+++ b/apache-rat-plugin/src/it/it4_RAT-168/pom.xml
@@ -15,10 +15,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-
+
4.0.0
org.apache.rat.test
it4rat168
diff --git a/apache-rat-plugin/src/main/java/org/apache/rat/mp/AbstractRatMojo.java b/apache-rat-plugin/src/main/java/org/apache/rat/mp/AbstractRatMojo.java
index 97a0e8dfe..9147a51d1 100644
--- a/apache-rat-plugin/src/main/java/org/apache/rat/mp/AbstractRatMojo.java
+++ b/apache-rat-plugin/src/main/java/org/apache/rat/mp/AbstractRatMojo.java
@@ -1,5 +1,3 @@
-package org.apache.rat.mp;
-
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
@@ -18,8 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
+package org.apache.rat.mp;
-import static org.apache.rat.mp.util.ConfigurationHelper.newInstance;
import static org.apache.rat.mp.util.ExclusionHelper.addEclipseDefaults;
import static org.apache.rat.mp.util.ExclusionHelper.addIdeaDefaults;
import static org.apache.rat.mp.util.ExclusionHelper.addMavenDefaults;
@@ -28,43 +26,48 @@
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
-import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
-import java.io.PrintWriter;
import java.io.Reader;
-import java.io.StringWriter;
-import java.io.Writer;
import java.lang.reflect.UndeclaredThrowableException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.nio.file.Files;
import java.util.ArrayList;
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 javax.xml.transform.TransformerConfigurationException;
+import java.util.Objects;
+import java.util.SortedSet;
+import java.util.function.Consumer;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
-
-import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
-import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.plugin.logging.Log;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
+import org.apache.rat.ConfigurationException;
import org.apache.rat.Defaults;
-import org.apache.rat.Report;
import org.apache.rat.ReportConfiguration;
-import org.apache.rat.analysis.IHeaderMatcher;
-import org.apache.rat.analysis.util.HeaderMatcherMultiplexer;
-import org.apache.rat.api.RatException;
+import org.apache.rat.analysis.license.DeprecatedConfig;
import org.apache.rat.config.SourceCodeManagementSystems;
+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.LicenseFilter;
+import org.apache.rat.license.SimpleLicenseFamily;
import org.apache.rat.mp.util.ScmIgnoreParser;
+import org.apache.rat.mp.util.ignore.GlobIgnoreMatcher;
+import org.apache.rat.mp.util.ignore.IgnoreMatcher;
+import org.apache.rat.mp.util.ignore.IgnoringDirectoryScanner;
import org.apache.rat.report.IReportable;
-import org.apache.rat.report.claim.ClaimStatistic;
import org.codehaus.plexus.util.DirectoryScanner;
/**
@@ -79,50 +82,58 @@ public abstract class AbstractRatMojo extends AbstractMojo {
private File basedir;
/**
- * Specifies the licenses to accept. Deprecated, use {@link #licenses}
- * instead.
+ * Specifies the licenses to accept. By default, these are added to the default
+ * licenses, unless you set {@link #addDefaultLicenseMatchers} to false.
*
- * @deprecated Use {@link #licenses} instead.
+ * @since 0.8
*/
- @Deprecated
@Parameter
- private HeaderMatcherSpecification[] licenseMatchers;
+ private String[] defaultLicenseFiles;
+
+ @Parameter
+ private String[] additionalLicenseFiles;
/**
- * Specifies the licenses to accept. By default, these are added to the
- * default licenses, unless you set {@link #addDefaultLicenseMatchers} to
- * false.
- *
- * @since 0.8
+ * Whether to add the default list of licenses.
*/
- @Parameter
- private IHeaderMatcher[] licenses;
+ @Parameter(property = "rat.addDefaultLicenses", defaultValue = "true")
+ private boolean addDefaultLicenses;
/**
- * The set of approved license family names.
- *
- * @deprecated Use {@link #licenseFamilies} instead.
+ * Whether to add the default list of license matchers.
*/
- @Deprecated
- private LicenseFamilySpecification[] licenseFamilyNames;
+ @Parameter(property = "rat.addDefaultLicenseMatchers", defaultValue = "true")
+ private boolean addDefaultLicenseMatchers;
+
+ @Parameter(required = false)
+ private String[] approvedLicenses;
+ @Parameter(property = "rat.approvedFile")
+ private String approvedLicenseFile;
+
/**
* Specifies the license families to accept.
*
* @since 0.8
+ * @deprecated
*/
+ @Deprecated // remove in v1.0
@Parameter
- private ILicenseFamily[] licenseFamilies;
-
+ private SimpleLicenseFamily[] licenseFamilies;
+
/**
- * Whether to add the default list of license matchers.
+ * This is an object to accept both License of DeprecatedConfig objects.
*/
- @Parameter(property = "rat.addDefaultLicenseMatchers", defaultValue = "true")
- private boolean addDefaultLicenseMatchers;
+ @Deprecated // convert this to an org.apache.rat.mp.License object in v1.0
+ @Parameter
+ private Object[] licenses;
+
+ @Parameter
+ private Family[] families;
/**
- * Specifies files, which are included in the report. By default, all files
- * are included.
+ * Specifies files, which are included in the report. By default, all files are
+ * included.
*/
@Parameter
private String[] includes;
@@ -131,36 +142,36 @@ public abstract class AbstractRatMojo extends AbstractMojo {
* Specifies a file, from which to read includes. Basically, an alternative to
* specifying the includes as a list.
*/
- @Parameter(property="rat.includesFile")
+ @Parameter(property = "rat.includesFile")
private String includesFile;
/**
- * Specifies the include files character set. Defaults to @code{${project.build.sourceEncoding}),
- * or @code{UTF8}.
+ * Specifies the include files character set. Defaults
+ * to @code{${project.build.sourceEncoding}), or @code{UTF8}.
*/
- @Parameter(property="rat.includesFileCharset", defaultValue="${project.build.sourceEncoding}")
+ @Parameter(property = "rat.includesFileCharset", defaultValue = "${project.build.sourceEncoding}")
private String includesFileCharset;
/**
- * Specifies files, which are excluded in the report. By default, no files
- * are excluded.
+ * Specifies files, which are excluded in the report. By default, no files are
+ * excluded.
*/
@Parameter
private String[] excludes;
/**
* Specifies a file, from which to read excludes. Basically, an alternative to
- * specifying the excludes as a list. The excludesFile is assumed to be using the
- * UFT8 character set.
+ * specifying the excludes as a list. The excludesFile is assumed to be using
+ * the UFT8 character set.
*/
- @Parameter(property="rat.excludesFile")
+ @Parameter(property = "rat.excludesFile")
private String excludesFile;
/**
- * Specifies the include files character set. Defaults to @code{${project.build.sourceEncoding}),
- * or @code{UTF8}.
+ * Specifies the include files character set. Defaults
+ * to @code{${project.build.sourceEncoding}), or @code{UTF8}.
*/
- @Parameter(property="rat.excludesFileCharset", defaultValue="${project.build.sourceEncoding}")
+ @Parameter(property = "rat.excludesFileCharset", defaultValue = "${project.build.sourceEncoding}")
private String excludesFileCharset;
/**
@@ -169,20 +180,20 @@ public abstract class AbstractRatMojo extends AbstractMojo {
*
*/
@Parameter(property = "rat.useDefaultExcludes", defaultValue = "true")
private boolean useDefaultExcludes;
/**
- * Whether to use the Maven specific default excludes when scanning for
- * files. Maven specific default excludes are given by the constant
+ * Whether to use the Maven specific default excludes when scanning for files.
+ * Maven specific default excludes are given by the constant
* MAVEN_DEFAULT_EXCLUDES: The target
directory, the
* cobertura.ser
file, and so on.
*/
@@ -190,8 +201,8 @@ public abstract class AbstractRatMojo extends AbstractMojo {
private boolean useMavenDefaultExcludes;
/**
- * Whether to parse source code management system (SCM) ignore files and use their contents as excludes.
- * At the moment this works for the following SCMs:
+ * Whether to parse source code management system (SCM) ignore files and use
+ * their contents as excludes. At the moment this works for the following SCMs:
*
* @see org.apache.rat.config.SourceCodeManagementSystems
*/
@@ -199,18 +210,17 @@ public abstract class AbstractRatMojo extends AbstractMojo {
private boolean parseSCMIgnoresAsExcludes;
/**
- * Whether to use the Eclipse specific default excludes when scanning for
- * files. Eclipse specific default excludes are given by the constant
+ * Whether to use the Eclipse specific default excludes when scanning for files.
+ * Eclipse specific default excludes are given by the constant
* ECLIPSE_DEFAULT_EXCLUDES: The .classpath
and
- * .project
files, the .settings
directory, and so
- * on.
+ * .project
files, the .settings
directory, and so on.
*/
@Parameter(property = "rat.useEclipseDefaultExcludes", defaultValue = "true")
private boolean useEclipseDefaultExcludes;
/**
- * Whether to use the IDEA specific default excludes when scanning for
- * files. IDEA specific default excludes are given by the constant
+ * Whether to use the IDEA specific default excludes when scanning for files.
+ * IDEA specific default excludes are given by the constant
* IDEA_DEFAULT_EXCLUDES: The *.iml
, *.ipr
and
* *.iws
files and the .idea
directory.
*/
@@ -218,14 +228,15 @@ public abstract class AbstractRatMojo extends AbstractMojo {
private boolean useIdeaDefaultExcludes;
/**
- * Whether to exclude subprojects. This is recommended, if you want a
- * separate apache-rat-plugin report for each subproject.
+ * Whether to exclude subprojects. This is recommended, if you want a separate
+ * apache-rat-plugin report for each subproject.
*/
@Parameter(property = "rat.excludeSubprojects", defaultValue = "true")
private boolean excludeSubProjects;
/**
- * Will skip the plugin execution, e.g. for technical builds that do not take license compliance into account.
+ * Will skip the plugin execution, e.g. for technical builds that do not take
+ * license compliance into account.
*
* @since 0.11
*/
@@ -233,7 +244,8 @@ public abstract class AbstractRatMojo extends AbstractMojo {
protected boolean skip;
/**
- * Holds the maven-internal project to allow resolution of artifact properties during mojo runs.
+ * Holds the maven-internal project to allow resolution of artifact properties
+ * during mojo runs.
*/
@Parameter(defaultValue = "${project}", required = true, readonly = true)
protected MavenProject project;
@@ -245,55 +257,177 @@ protected MavenProject getProject() {
return project;
}
- /**
- * Returns the set of {@link IHeaderMatcher header matchers} to use.
- *
- * @return list of license matchers to use
- * @throws MojoFailureException An error in the plugin configuration was detected.
- * @throws MojoExecutionException An error occurred while calculating the result.
- */
- private List mergeLicenseMatchers()
- throws MojoFailureException, MojoExecutionException {
- List matchers = new ArrayList<>();
-
- if (licenses != null) {
- matchers.addAll(Arrays.asList(licenses));
- getLog().info("Added " + licenses.length + " additional default licenses.");
+ protected Defaults.Builder getDefaultsBuilder() {
+ Defaults.Builder result = Defaults.builder();
+ if (defaultLicenseFiles != null) {
+ for (String defaultLicenseFile : defaultLicenseFiles) {
+ try {
+ result.add(defaultLicenseFile);
+ } catch (MalformedURLException e) {
+ throw new ConfigurationException(defaultLicenseFile + " is not a valid license file", e);
+ }
+ }
+ }
+ return result;
+ }
+
+ @Deprecated // remove this for version 1.0
+ private Stream getLicenses() {
+ if (licenses == null) {
+ return Stream.empty();
}
+ return Arrays.stream(licenses).filter( s -> {return s instanceof License;}).map(License.class::cast);
+ }
- if (licenseMatchers != null) {
- for (final HeaderMatcherSpecification spec : licenseMatchers) {
- matchers.add(newInstance(IHeaderMatcher.class, spec.getClassName()));
+ @Deprecated // remove this for version 1.0
+ private Stream getDeprecatedConfigs() {
+ if (licenses == null) {
+ return Stream.empty();
+ }
+ return Arrays.stream(licenses).filter( s -> {return s instanceof DeprecatedConfig;}).map(DeprecatedConfig.class::cast);
+ }
+
+ @Deprecated // remove this for version 1.0
+ private void reportDeprecatedProcessing()
+ {
+ if (getDeprecatedConfigs().findAny().isPresent()) {
+ Log log = getLog();
+ log.warn("Configuration uses deprecated configuration. Please upgrade to v0.17 configuration options");
+ }
+ }
+
+ @Deprecated // remove this for version 1.0
+ private void processLicenseFamilies(ReportConfiguration config) {
+ List families = getDeprecatedConfigs().map(DeprecatedConfig::getLicenseFamily).filter(Objects::nonNull).collect(Collectors.toList());
+ if (licenseFamilies != null) {
+ for (SimpleLicenseFamily slf : licenseFamilies) {
+ if (StringUtils.isBlank(slf.getFamilyCategory())) {
+ families.stream().filter( f -> f.getFamilyName().equalsIgnoreCase(slf.getFamilyName())).findFirst()
+ .ifPresent(config::addApprovedLicenseCategory);
+ } else {
+ config.addApprovedLicenseCategory(ILicenseFamily.builder().setLicenseFamilyCategory(slf.getFamilyCategory())
+ .setLicenseFamilyName(StringUtils.defaultIfBlank(slf.getFamilyName(), slf.getFamilyCategory()))
+ .build());
+ }
+ }
+ }
+ }
+
+ private org.apache.rat.utils.Log makeLog() {
+ return new org.apache.rat.utils.Log() {
+ Log log = getLog();
+ @Override
+ public void log(Level level, String msg) {
+ switch (level)
+ {
+ case DEBUG:
+ log.debug(msg);
+ break;
+ case INFO:
+ log.info(msg);;
+ break;
+ case WARN:
+ log.warn(msg);
+ break;
+ case ERROR:
+ log.error(msg);
+ break;
+ }
+ }};
+ }
+
+ protected ReportConfiguration getConfiguration() throws MojoExecutionException {
+ ReportConfiguration config = new ReportConfiguration(makeLog());
+ reportDeprecatedProcessing();
+ if (addDefaultLicenses) {
+ config.setFrom(getDefaultsBuilder().build());
+ } else {
+ config.setStyleSheet(Defaults.getPlainStyleSheet());
+ }
+ if (additionalLicenseFiles != null) {
+ for (String licenseFile : additionalLicenseFiles) {
+ try {
+ URL url = new File(licenseFile).toURI().toURL();
+ Format fmt = Format.fromName(licenseFile);
+ MatcherReader mReader = fmt.matcherReader();
+ if (mReader != null) {
+ mReader.addMatchers(url);
+ }
+ LicenseReader lReader = fmt.licenseReader();
+ if (lReader != null) {
+ lReader.addLicenses(url);
+ config.addLicenses(lReader.readLicenses());
+ config.addApprovedLicenseCategories(lReader.approvedLicenseId());
+ }
+ } catch (MalformedURLException e) {
+ throw new ConfigurationException(licenseFile + " is not a valid license file", e);
+ }
+ }
+ }
+ if (families != null || getDeprecatedConfigs().findAny().isPresent()) {
+ Log log = getLog();
+ if (log.isDebugEnabled()) {
+ log.debug(String.format("%s license families loaded from pom", families.length));
+ }
+ Consumer logger = log.isDebugEnabled() ? (l) -> log.debug(String.format("Family: %s", l))
+ : (l) -> {
+ };
+
+ Consumer process = logger.andThen(config::addFamily);
+ getDeprecatedConfigs().map(DeprecatedConfig::getLicenseFamily).filter(Objects::nonNull).forEach(process);
+ if (families != null) { // TODO remove if check in v1.0
+ Arrays.stream(families).map(Family::build).forEach(process);
}
}
- if (addDefaultLicenseMatchers) {
- getLog().info("Enabled default license matchers.");
- matchers.addAll(Defaults.DEFAULT_MATCHERS);
+ processLicenseFamilies(config);
+
+ if (approvedLicenses != null && approvedLicenses.length > 0) {
+ Arrays.stream(approvedLicenses).forEach(config::addApprovedLicenseCategory);
}
- logLicenseMatchers(matchers);
- return matchers;
+ if (licenses != null) {
+ Log log = getLog();
+ if (log.isDebugEnabled()) {
+ log.debug(String.format("%s licenses loaded from pom", licenses.length));
+ }
+ Consumer logger = log.isDebugEnabled() ? (l) -> log.debug(String.format("License: %s", l))
+ : (l) -> {
+ };
+ Consumer addApproved = (approvedLicenses == null || approvedLicenses.length == 0)
+ ? (l) -> config.addApprovedLicenseCategory(l.getLicenseFamily())
+ : (l) -> {
+ };
+
+ Consumer process = logger.andThen(config::addLicense).andThen(addApproved);
+ SortedSet families = config.getLicenseFamilies(LicenseFilter.all);
+ getDeprecatedConfigs().map(DeprecatedConfig::getLicense).filter(Objects::nonNull)
+ .map(x -> x.build(families)).forEach(process);
+ getLicenses().map(x -> x.build(families)).forEach(process);
+ }
+
+ config.setReportable(getReportable());
+ return config;
}
- private void logLicenseMatchers(List matchers) {
+ protected void logLicenses(Collection licenses) {
if (getLog().isDebugEnabled()) {
- getLog().debug("The following license matchers are activated:");
- for (IHeaderMatcher matcher : matchers) {
- getLog().debug("* " + matcher.toString());
+ getLog().debug("The following " + licenses.size() + " licenses are activated:");
+ for (ILicense license : licenses) {
+ getLog().debug("* " + license.toString());
}
}
-
}
/**
* Creates an iterator over the files to check.
*
* @return A container of files, which are being checked.
- * @throws MojoExecutionException in case of errors. I/O errors result in UndeclaredThrowableExceptions.
+ * @throws MojoExecutionException in case of errors. I/O errors result in
+ * UndeclaredThrowableExceptions.
*/
- protected IReportable getResources() throws MojoExecutionException {
- final DirectoryScanner ds = new DirectoryScanner();
+ private IReportable getReportable() throws MojoExecutionException {
+ final IgnoringDirectoryScanner ds = new IgnoringDirectoryScanner();
ds.setBasedir(basedir);
setExcludes(ds);
setIncludes(ds);
@@ -312,9 +446,7 @@ private void logAboutIncludedFiles(final String[] files) {
if (files.length == 0) {
getLog().warn("No resources included.");
} else {
- getLog().info(
- files.length
- + " resources included");
+ getLog().debug(files.length + " resources included");
if (getLog().isDebugEnabled()) {
for (final String resource : files) {
getLog().debug(" - included " + resource);
@@ -329,8 +461,7 @@ private void whenDebuggingLogExcludedFiles(final DirectoryScanner ds) {
if (excludedFiles.length == 0) {
getLog().debug("No excluded resources.");
} else {
- getLog().debug(
- "Excluded " + excludedFiles.length + " resources:");
+ getLog().debug("Excluded " + excludedFiles.length + " resources:");
for (final String resource : excludedFiles) {
getLog().debug(" - excluded " + resource);
}
@@ -339,216 +470,204 @@ private void whenDebuggingLogExcludedFiles(final DirectoryScanner ds) {
}
private void setIncludes(DirectoryScanner ds) throws MojoExecutionException {
- if ((includes != null && includes.length > 0) || includesFile != null) {
- final List includeList = new ArrayList<>();
- if (includes != null) {
- includeList.addAll(Arrays.asList(includes));
- }
- if (includesFile != null) {
- final String charset = includesFileCharset == null ? "UTF8" : includesFileCharset;
- final File f = new File(includesFile);
- if (!f.isFile()) {
- getLog().error("IncludesFile not found: " + f.getAbsolutePath());
- } else {
- getLog().info("Includes loaded from file " + includesFile + ", using character set " + charset);
- }
- includeList.addAll(getPatternsFromFile(f, charset));
- }
+ if ((includes != null && includes.length > 0) || includesFile != null) {
+ final List includeList = new ArrayList<>();
+ if (includes != null) {
+ includeList.addAll(Arrays.asList(includes));
+ }
+ if (includesFile != null) {
+ final String charset = includesFileCharset == null ? "UTF8" : includesFileCharset;
+ final File f = new File(includesFile);
+ if (!f.isFile()) {
+ getLog().error("IncludesFile not found: " + f.getAbsolutePath());
+ } else {
+ getLog().debug("Includes loaded from file " + includesFile + ", using character set " + charset);
+ }
+ includeList.addAll(getPatternsFromFile(f, charset));
+ }
ds.setIncludes(includeList.toArray(new String[includeList.size()]));
}
}
private List getPatternsFromFile(File pFile, String pCharset) throws MojoExecutionException {
- InputStream is = null;
- BufferedInputStream bis = null;
- Reader r = null;
- BufferedReader br = null;
- Throwable th = null;
- final List patterns = new ArrayList<>();
- try {
- is = new FileInputStream(pFile);
- bis = new BufferedInputStream(is);
- r = new InputStreamReader(bis, pCharset);
- br = new BufferedReader(r);
- for (;;) {
- final String s = br.readLine();
- if (s == null) {
- break;
- }
- patterns.add(s);
- }
- br.close();
- br = null;
- r.close();
- r = null;
- bis.close();
- bis = null;
- is.close();
- is = null;
- } catch (Throwable t) {
- th = t;
- } finally {
- if (br != null) { try { br.close(); } catch (Throwable t) { if (th == null) { th = t; } } }
- if (r != null) { try { r.close(); } catch (Throwable t) { if (th == null) { th = t; } } }
- if (bis != null) { try { bis.close(); } catch (Throwable t) { if (th == null) { th = t; } } }
- if (is != null) { try { is.close(); } catch (Throwable t) { if (th == null) { th = t; } } }
- }
- if (th != null) {
- if (th instanceof RuntimeException) { throw (RuntimeException) th; }
- if (th instanceof Error) { throw (Error) th; }
- throw new MojoExecutionException(th.getMessage(), th);
- }
- return patterns;
+ InputStream is = null;
+ BufferedInputStream bis = null;
+ Reader r = null;
+ BufferedReader br = null;
+ Throwable th = null;
+ final List patterns = new ArrayList<>();
+ try {
+ is = Files.newInputStream(pFile.toPath());
+ bis = new BufferedInputStream(is);
+ r = new InputStreamReader(bis, pCharset);
+ br = new BufferedReader(r);
+ for (;;) {
+ final String s = br.readLine();
+ if (s == null) {
+ break;
+ }
+ patterns.add(s);
+ }
+ br.close();
+ br = null;
+ r.close();
+ r = null;
+ bis.close();
+ bis = null;
+ is.close();
+ is = null;
+ } catch (Throwable t) {
+ th = t;
+ } finally {
+ if (br != null) {
+ try {
+ br.close();
+ } catch (Throwable t) {
+ if (th == null) {
+ th = t;
+ }
+ }
+ }
+ if (r != null) {
+ try {
+ r.close();
+ } catch (Throwable t) {
+ if (th == null) {
+ th = t;
+ }
+ }
+ }
+ if (bis != null) {
+ try {
+ bis.close();
+ } catch (Throwable t) {
+ if (th == null) {
+ th = t;
+ }
+ }
+ }
+ if (is != null) {
+ try {
+ is.close();
+ } catch (Throwable t) {
+ if (th == null) {
+ th = t;
+ }
+ }
+ }
+ }
+ if (th != null) {
+ if (th instanceof RuntimeException) {
+ throw (RuntimeException) th;
+ }
+ if (th instanceof Error) {
+ throw (Error) th;
+ }
+ throw new MojoExecutionException(th.getMessage(), th);
+ }
+ return patterns;
}
- private void setExcludes(DirectoryScanner ds) throws MojoExecutionException {
- final List excludeList = mergeDefaultExclusions();
+ private void setExcludes(IgnoringDirectoryScanner ds) throws MojoExecutionException {
+ final List ignoreMatchers = mergeDefaultExclusions();
if (excludes == null || excludes.length == 0) {
- getLog().info("No excludes explicitly specified.");
+ getLog().debug("No excludes explicitly specified.");
} else {
- getLog().info(excludes.length + " explicit excludes.");
- for (final String exclude : excludes) {
+ getLog().debug(excludes.length + " explicit excludes.");
+ for (final String exclude : excludes) {
getLog().debug("Exclude: " + exclude);
}
}
+
+ final List globExcludes = new ArrayList<>();
+ for (IgnoreMatcher ignoreMatcher : ignoreMatchers) {
+ if (ignoreMatcher instanceof GlobIgnoreMatcher) {
+ // The glob matching we do via the DirectoryScanner
+ globExcludes.addAll(((GlobIgnoreMatcher) ignoreMatcher).getExclusionLines());
+ } else {
+ // All others (git) are used directly
+ ds.addIgnoreMatcher(ignoreMatcher);
+ }
+ }
+
if (excludes != null) {
- Collections.addAll(excludeList, excludes);
+ Collections.addAll(globExcludes, excludes);
}
- if (!excludeList.isEmpty()) {
- final String[] allExcludes = excludeList.toArray(new String[excludeList
- .size()]);
+ if (!globExcludes.isEmpty()) {
+ final String[] allExcludes = globExcludes.toArray(new String[globExcludes.size()]);
ds.setExcludes(allExcludes);
}
}
- private List mergeDefaultExclusions() throws MojoExecutionException {
- final Set results = new HashSet<>();
+ private List mergeDefaultExclusions() throws MojoExecutionException {
+ List ignoreMatchers = new ArrayList<>();
- addPlexusAndScmDefaults(getLog(), useDefaultExcludes, results);
- addMavenDefaults(getLog(), useMavenDefaultExcludes, results);
- addEclipseDefaults(getLog(), useEclipseDefaultExcludes, results);
- addIdeaDefaults(getLog(), useIdeaDefaultExcludes, results);
+ final GlobIgnoreMatcher basicRules = new GlobIgnoreMatcher();
+
+ basicRules.addRules(addPlexusAndScmDefaults(getLog(), useDefaultExcludes));
+ basicRules.addRules(addMavenDefaults(getLog(), useMavenDefaultExcludes));
+ basicRules.addRules(addEclipseDefaults(getLog(), useEclipseDefaultExcludes));
+ basicRules.addRules(addIdeaDefaults(getLog(), useIdeaDefaultExcludes));
if (parseSCMIgnoresAsExcludes) {
- getLog().info("Will parse SCM ignores for exclusions...");
- results.addAll(ScmIgnoreParser.getExclusionsFromSCM(getLog(), project.getBasedir()));
- getLog().info("Finished adding exclusions from SCM ignore files.");
+ getLog().debug("Will parse SCM ignores for exclusions...");
+ ignoreMatchers.addAll(ScmIgnoreParser.getExclusionsFromSCM(getLog(), project.getBasedir()));
+ getLog().debug("Finished adding exclusions from SCM ignore files.");
}
- if (excludeSubProjects && project != null
- && project.getModules() != null) {
- for (final Object o : project.getModules()) {
- final String moduleSubPath = (String) o;
- if (new File( basedir, moduleSubPath ).isDirectory()) {
- results.add(moduleSubPath + "/**/*");
- }
- else {
- results.add(StringUtils.substringBeforeLast( moduleSubPath, "/" ) + "/**/*");
+ if (excludeSubProjects && project != null && project.getModules() != null) {
+ for (final String moduleSubPath : project.getModules()) {
+ if (new File(basedir, moduleSubPath).isDirectory()) {
+ basicRules.addRule(moduleSubPath + "/**/*");
+ } else {
+ basicRules.addRule(StringUtils.substringBeforeLast(moduleSubPath, "/") + "/**/*");
}
}
}
- getLog().debug("Finished creating list of implicit excludes.");
- if (results.isEmpty()) {
- getLog().info("No excludes implicitly specified.");
- } else {
- getLog().info(
- results.size()
- + " implicit excludes.");
- for (final String exclude : results) {
- getLog().debug("Implicit exclude: " + exclude);
+ if (getLog().isDebugEnabled()) {
+ getLog().debug("Finished creating list of implicit excludes.");
+ if (basicRules.getExclusionLines().isEmpty() && ignoreMatchers.isEmpty()) {
+ getLog().debug("No excludes implicitly specified.");
+ } else {
+ if (!basicRules.getExclusionLines().isEmpty()) {
+ getLog().debug(basicRules.getExclusionLines().size() + " implicit excludes.");
+ for (final String exclude : basicRules.getExclusionLines()) {
+ getLog().debug("Implicit exclude: " + exclude);
+ }
+ }
+ for (IgnoreMatcher ignoreMatcher : ignoreMatchers) {
+ if (ignoreMatcher instanceof GlobIgnoreMatcher) {
+ GlobIgnoreMatcher globIgnoreMatcher = (GlobIgnoreMatcher) ignoreMatcher;
+ if (!globIgnoreMatcher.getExclusionLines().isEmpty()) {
+ getLog().debug(globIgnoreMatcher.getExclusionLines().size() + " implicit excludes from SCM.");
+ for (final String exclude : globIgnoreMatcher.getExclusionLines()) {
+ getLog().debug("Implicit exclude: " + exclude);
+ }
+ }
+ } else {
+ getLog().debug("Implicit exclude: \n" + ignoreMatcher);
+ }
+ }
}
}
if (excludesFile != null) {
- final File f = new File(excludesFile);
- if (!f.isFile()) {
- getLog().error("Excludes file not found: " + f.getAbsolutePath());
- }
- if (!f.canRead()) {
- getLog().error("Excludes file not readable: " + f.getAbsolutePath());
- }
- final String charset = excludesFileCharset == null ? "UTF8" : excludesFileCharset;
- getLog().info("Loading excludes from file " + f + ", using character set " + charset);
- results.addAll(getPatternsFromFile(f, charset));
- }
-
- return new ArrayList<>(results);
- }
-
- /**
- * Creates the report as a string.
- *
- * @param styleSheet The style sheet to use when formatting the report
- * @return Report contents
- * @throws MojoFailureException An error in the plugin configuration was detected.
- * @throws MojoExecutionException An error occurred while creating the report.
- */
- protected String createReport(InputStream styleSheet)
- throws MojoExecutionException, MojoFailureException {
- StringWriter sw = new StringWriter();
- PrintWriter pw = null;
- try {
- pw = new PrintWriter(sw);
- createReport(new PrintWriter(sw), styleSheet);
- final String result = sw.toString();
- pw.close();
- pw = null;
- sw.close();
- sw = null;
- return result;
- } catch (IOException e) {
- throw new MojoExecutionException(e.getMessage(), e);
- } finally {
- IOUtils.closeQuietly(pw);
- IOUtils.closeQuietly(sw);
- }
- }
-
- /**
- * Writes the report to the given stream.
- *
- * @param out The target writer, to which the report is being written.
- * @param style The stylesheet to use, or null
for raw XML
- * @return the current statistic.
- * @throws MojoFailureException An error in the plugin configuration was detected.
- * @throws MojoExecutionException Another error occurred while creating the report.
- */
- protected ClaimStatistic createReport(Writer out, InputStream style)
- throws MojoExecutionException, MojoFailureException {
- final ReportConfiguration configuration = getConfiguration();
- try {
- if (style != null) {
- return Report.report(out, getResources(), style, configuration);
- } else {
- return Report.report(getResources(), out, configuration);
+ final File f = new File(excludesFile);
+ if (!f.isFile()) {
+ getLog().error("Excludes file not found: " + f.getAbsolutePath());
+ }
+ if (!f.canRead()) {
+ getLog().error("Excludes file not readable: " + f.getAbsolutePath());
}
- } catch (final TransformerConfigurationException | RatException | InterruptedException | IOException e) {
- throw new MojoExecutionException(e.getMessage(), e);
+ final String charset = excludesFileCharset == null ? "UTF8" : excludesFileCharset;
+ getLog().debug("Loading excludes from file " + f + ", using character set " + charset);
+ basicRules.addRules(getPatternsFromFile(f, charset));
}
- }
- protected ReportConfiguration getConfiguration()
- throws MojoFailureException, MojoExecutionException {
- final ReportConfiguration configuration = new ReportConfiguration();
- configuration.setHeaderMatcher(new HeaderMatcherMultiplexer(
- mergeLicenseMatchers()));
- configuration.setApprovedLicenseNames(mergeApprovedLicenseNames());
- configuration.setApproveDefaultLicenses(addDefaultLicenseMatchers);
- return configuration;
- }
-
- private List mergeApprovedLicenseNames()
- throws MojoExecutionException, MojoFailureException {
- final List list = new ArrayList<>();
- if (licenseFamilies != null) {
- getLog().info("Added " + licenseFamilies.length + " custom approved licenses.");
- list.addAll(Arrays.asList(licenseFamilies));
+ if (!basicRules.isEmpty()) {
+ ignoreMatchers.add(basicRules);
}
- if (licenseFamilyNames != null) {
- for (final LicenseFamilySpecification spec : licenseFamilyNames) {
- list.add(newInstance(ILicenseFamily.class, spec.getClassName()));
- }
- }
- return list;
+
+ return ignoreMatchers;
}
}
diff --git a/apache-rat-plugin/src/main/java/org/apache/rat/mp/All.java b/apache-rat-plugin/src/main/java/org/apache/rat/mp/All.java
new file mode 100644
index 000000000..72700ac12
--- /dev/null
+++ b/apache-rat-plugin/src/main/java/org/apache/rat/mp/All.java
@@ -0,0 +1,41 @@
+/*
+ * 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.mp;
+
+import org.apache.rat.analysis.IHeaderMatcher;
+import org.apache.rat.analysis.IHeaderMatcher.Builder;
+import org.apache.rat.configuration.builders.AllBuilder;
+
+public class All extends EnclosingMatcher implements IHeaderMatcher.Builder {
+
+ AllBuilder builder = Builder.all();
+
+ public All() {
+ }
+
+ @Override
+ protected void setMatcher(IHeaderMatcher.Builder builder) {
+ this.builder.add(builder);
+ }
+
+ @Override
+ public IHeaderMatcher build() {
+ return builder.build();
+ }
+}
diff --git a/apache-rat-plugin/src/main/java/org/apache/rat/mp/Any.java b/apache-rat-plugin/src/main/java/org/apache/rat/mp/Any.java
new file mode 100644
index 000000000..77cda43e1
--- /dev/null
+++ b/apache-rat-plugin/src/main/java/org/apache/rat/mp/Any.java
@@ -0,0 +1,41 @@
+/*
+ * 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.mp;
+
+import org.apache.rat.analysis.IHeaderMatcher;
+import org.apache.rat.analysis.IHeaderMatcher.Builder;
+import org.apache.rat.configuration.builders.AnyBuilder;
+
+public class Any extends EnclosingMatcher implements IHeaderMatcher.Builder {
+
+ AnyBuilder builder = Builder.any();
+
+ public Any() {
+ }
+
+ @Override
+ protected void setMatcher(IHeaderMatcher.Builder builder) {
+ this.builder.add(builder);
+ }
+
+ @Override
+ public IHeaderMatcher build() {
+ return builder.build();
+ }
+}
diff --git a/apache-rat-plugin/src/main/java/org/apache/rat/mp/Copyright.java b/apache-rat-plugin/src/main/java/org/apache/rat/mp/Copyright.java
new file mode 100644
index 000000000..034a105e5
--- /dev/null
+++ b/apache-rat-plugin/src/main/java/org/apache/rat/mp/Copyright.java
@@ -0,0 +1,44 @@
+/*
+ * 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.mp;
+
+import org.apache.maven.plugins.annotations.Parameter;
+import org.apache.rat.analysis.IHeaderMatcher;
+import org.apache.rat.configuration.builders.CopyrightBuilder;
+
+public class Copyright extends CopyrightBuilder {
+
+ @Parameter(required = false)
+ private String start;
+
+ @Parameter(required = false)
+ private String stop;
+
+ @Parameter(required = false)
+ private String owner;
+
+ public Copyright() {
+ }
+
+ @Override
+ public IHeaderMatcher build() {
+ setStart(start).setEnd(stop).setOwner(owner);
+ return super.build();
+ }
+}
diff --git a/apache-rat-plugin/src/main/java/org/apache/rat/mp/EnclosingMatcher.java b/apache-rat-plugin/src/main/java/org/apache/rat/mp/EnclosingMatcher.java
new file mode 100644
index 000000000..d85f9c903
--- /dev/null
+++ b/apache-rat-plugin/src/main/java/org/apache/rat/mp/EnclosingMatcher.java
@@ -0,0 +1,62 @@
+/*
+ * 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.mp;
+
+import org.apache.maven.plugins.annotations.Parameter;
+import org.apache.rat.analysis.IHeaderMatcher;
+
+abstract class EnclosingMatcher {
+
+ protected abstract void setMatcher(IHeaderMatcher.Builder builder);
+
+ @Parameter(required = false)
+ public void setAll(All all) {
+ setMatcher(all);
+ }
+
+ @Parameter(required = false)
+ public void setAny(Any any) {
+ setMatcher(any);
+ }
+
+ @Parameter(required = false)
+ public void setText(Text text) {
+ setMatcher(text);
+ }
+
+ @Parameter(required = false)
+ public void setCopyright(Copyright copyright) {
+ setMatcher(copyright);
+ }
+
+ @Parameter(required = false)
+ public void setRegex(Regex regex) {
+ setMatcher(regex);
+ }
+
+ @Parameter(required = false)
+ public void setSpdx(Spdx spdx) {
+ setMatcher(spdx);
+ }
+
+ @Parameter(required = false)
+ public void setNot(Not not) {
+ setMatcher(not);
+ }
+}
diff --git a/apache-rat-core/src/test/java/org/apache/rat/config/ConfigurationUtilTest.java b/apache-rat-plugin/src/main/java/org/apache/rat/mp/Family.java
similarity index 55%
rename from apache-rat-core/src/test/java/org/apache/rat/config/ConfigurationUtilTest.java
rename to apache-rat-plugin/src/main/java/org/apache/rat/mp/Family.java
index e62891019..0b790164f 100644
--- a/apache-rat-core/src/test/java/org/apache/rat/config/ConfigurationUtilTest.java
+++ b/apache-rat-plugin/src/main/java/org/apache/rat/mp/Family.java
@@ -1,14 +1,3 @@
-package org.apache.rat.config;
-
-import org.apache.rat.api.MetaData;
-import org.apache.rat.license.GPL1LicenseFamily;
-import org.apache.rat.license.ILicenseFamily;
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
@@ -27,18 +16,30 @@
* specific language governing permissions and limitations
* under the License.
*/
-public class ConfigurationUtilTest {
- @Test
- public void toNamesIsNullSafe() {
- assertTrue(ConfigurationUtil.toNames(null).isEmpty());
+package org.apache.rat.mp;
+
+import org.apache.maven.plugins.annotations.Parameter;
+import org.apache.rat.license.ILicenseFamily;
+
+public class Family {
+
+ private final ILicenseFamily.Builder builder = ILicenseFamily.builder();
+
+ @Parameter(required = true)
+ private String id;
+
+ @Parameter(required = true)
+ private String name;
+
+ public Family() {
}
- @Test
- public void toNamesIsEmptyArraySafe() {
- assertTrue(ConfigurationUtil.toNames(new ILicenseFamily[0]).isEmpty());
+ public ILicenseFamily build() {
+ return builder.setLicenseFamilyCategory(id).setLicenseFamilyName(name).build();
}
- @Test
- public void toNamesRegular() {
- assertEquals(MetaData.RAT_LICENSE_FAMILY_NAME_VALUE_GPL_VERSION_1, ConfigurationUtil.toNames(new ILicenseFamily[]{new GPL1LicenseFamily()}).get(0));
+
+ @Override
+ public String toString() {
+ return '{' + id + ':' + name + '}';
}
}
diff --git a/apache-rat-plugin/src/main/java/org/apache/rat/mp/FilesReportable.java b/apache-rat-plugin/src/main/java/org/apache/rat/mp/FilesReportable.java
index ae339edd3..82c2c8cbe 100644
--- a/apache-rat-plugin/src/main/java/org/apache/rat/mp/FilesReportable.java
+++ b/apache-rat-plugin/src/main/java/org/apache/rat/mp/FilesReportable.java
@@ -1,5 +1,12 @@
package org.apache.rat.mp;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.nio.file.Files;
+
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
@@ -26,41 +33,27 @@
import org.apache.rat.report.IReportable;
import org.apache.rat.report.RatReport;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.Reader;
-
-
/**
* Implementation of IReportable that traverses over a set of files.
*/
-class FilesReportable implements IReportable
-{
+class FilesReportable implements IReportable {
private final File basedir;
private final String[] files;
- FilesReportable( File basedir, String[] files )
- throws IOException
- {
- final File currentDir = new File( System.getProperty( "user.dir" ) ).getCanonicalFile();
+ FilesReportable(File basedir, String[] files) throws IOException {
+ final File currentDir = new File(System.getProperty("user.dir")).getCanonicalFile();
final File f = basedir.getCanonicalFile();
- if ( currentDir.equals( f ) )
- {
+ if (currentDir.equals(f)) {
this.basedir = null;
- }
- else
- {
+ } else {
this.basedir = basedir;
}
this.files = files;
}
- public void run( RatReport report ) throws RatException
- {
+ @Override
+ public void run(RatReport report) throws RatException {
FileDocument document = new FileDocument();
for (String file : files) {
document.setFile(new File(basedir, file));
@@ -69,39 +62,40 @@ public void run( RatReport report ) throws RatException
}
}
- private class FileDocument implements Document
- {
+ private static class FileDocument implements Document {
private File file;
private final MetaData metaData = new MetaData();
-
- void setFile( File file )
- {
+
+ void setFile(File file) {
this.file = file;
}
+ @Override
public boolean isComposite() {
return DocumentImplUtils.isZip(file);
}
- public Reader reader() throws IOException
- {
- final InputStream in = new FileInputStream( file );
- return new InputStreamReader( in );
+ @Override
+ public Reader reader() throws IOException {
+ final InputStream in = Files.newInputStream(file.toPath());
+ return new InputStreamReader(in);
}
- public String getName()
- {
- return DocumentImplUtils.toName( file );
+ @Override
+ public String getName() {
+ return DocumentImplUtils.toName(file);
}
+ @Override
public MetaData getMetaData() {
return metaData;
}
-
+
+ @Override
public InputStream inputStream() throws IOException {
- return new FileInputStream(file);
+ return Files.newInputStream(file.toPath());
}
-
+
@Override
public String toString() {
return "File:" + file.getAbsolutePath();
diff --git a/apache-rat-plugin/src/main/java/org/apache/rat/mp/License.java b/apache-rat-plugin/src/main/java/org/apache/rat/mp/License.java
new file mode 100644
index 000000000..ac17c2b09
--- /dev/null
+++ b/apache-rat-plugin/src/main/java/org/apache/rat/mp/License.java
@@ -0,0 +1,65 @@
+/*
+ * 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.mp;
+
+import java.util.SortedSet;
+
+import org.apache.maven.plugins.annotations.Parameter;
+import org.apache.rat.analysis.IHeaderMatcher;
+import org.apache.rat.license.ILicense;
+import org.apache.rat.license.ILicenseFamily;
+
+public class License extends EnclosingMatcher {
+
+ private final ILicense.Builder builder = ILicense.builder();
+
+ @Parameter(required = false)
+ private String notes;
+
+ @Parameter(required = false)
+ private String derivedFrom;
+
+ @Parameter(required = true)
+ private String id;
+
+ @Parameter(required = true)
+ private String family;
+
+ @Parameter(required = true)
+ private String name;
+
+ public License() {
+ }
+
+ @Override
+ protected void setMatcher(IHeaderMatcher.Builder builder) {
+ this.builder.setMatcher(builder);
+ }
+
+ public ILicense build(SortedSet context) {
+ return builder.setDerivedFrom(derivedFrom).setLicenseFamilyCategory(family).setId(id)
+ .setName(name).setNotes(notes).build(context);
+ }
+
+ @Override
+ public String toString() {
+ return '{' + family + ':' + id + ':' + name + '}';
+ }
+
+}
diff --git a/apache-rat-plugin/src/main/java/org/apache/rat/mp/Not.java b/apache-rat-plugin/src/main/java/org/apache/rat/mp/Not.java
new file mode 100644
index 000000000..2ba51c8d8
--- /dev/null
+++ b/apache-rat-plugin/src/main/java/org/apache/rat/mp/Not.java
@@ -0,0 +1,41 @@
+/*
+ * 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.mp;
+
+import org.apache.rat.analysis.IHeaderMatcher;
+import org.apache.rat.analysis.IHeaderMatcher.Builder;
+import org.apache.rat.configuration.builders.NotBuilder;
+
+public class Not extends EnclosingMatcher implements IHeaderMatcher.Builder {
+
+ NotBuilder builder = Builder.not();
+
+ public Not() {
+ }
+
+ @Override
+ protected void setMatcher(IHeaderMatcher.Builder builder) {
+ this.builder.add(builder);
+ }
+
+ @Override
+ public IHeaderMatcher build() {
+ return builder.build();
+ }
+}
diff --git a/apache-rat-plugin/src/main/java/org/apache/rat/mp/RatCheckMojo.java b/apache-rat-plugin/src/main/java/org/apache/rat/mp/RatCheckMojo.java
index 3fa3f4e38..e2b9cb610 100644
--- a/apache-rat-plugin/src/main/java/org/apache/rat/mp/RatCheckMojo.java
+++ b/apache-rat-plugin/src/main/java/org/apache/rat/mp/RatCheckMojo.java
@@ -1,5 +1,3 @@
-package org.apache.rat.mp;
-
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
@@ -18,8 +16,14 @@
* specific language governing permissions and limitations
* under the License.
*/
+package org.apache.rat.mp;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Paths;
-import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.StringUtils;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
@@ -27,21 +31,11 @@
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.rat.Defaults;
import org.apache.rat.ReportConfiguration;
+import org.apache.rat.Reporter;
import org.apache.rat.config.AddLicenseHeaders;
-import org.apache.rat.config.ReportFormat;
+import org.apache.rat.license.LicenseSetFactory.LicenseFilter;
import org.apache.rat.report.claim.ClaimStatistic;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStreamWriter;
-import java.io.Writer;
-import java.nio.charset.Charset;
-import java.nio.charset.StandardCharsets;
-
/**
* Run Rat to perform a violation check.
*/
@@ -53,11 +47,14 @@ public class RatCheckMojo extends AbstractRatMojo {
@Parameter(property = "rat.outputFile", defaultValue = "${project.build.directory}/rat.txt")
private File reportFile;
+ @Parameter(property = "rat.scanHiddenDirectories", defaultValue = "false")
+ private boolean scanHiddenDirectories;
+
/**
- * Output style of the report. Use "plain" (the default) for a plain text
- * report or "xml" for the raw XML report. Alternatively you can give the
- * path of an XSL transformation that will be applied on the raw XML to
- * produce the report written to the output file.
+ * Output style of the report. Use "plain" (the default) for a plain text report
+ * or "xml" for the raw XML report. Alternatively you can give the path of an
+ * XSL transformation that will be applied on the raw XML to produce the report
+ * written to the output file.
*/
@Parameter(property = "rat.outputStyle", defaultValue = "plain")
private String reportStyle;
@@ -69,23 +66,22 @@ public class RatCheckMojo extends AbstractRatMojo {
private int numUnapprovedLicenses;
/**
- * Whether to add license headers; possible values are
- * {@code forced}, {@code true}, and {@code false} (default).
+ * Whether to add license headers; possible values are {@code forced},
+ * {@code true}, and {@code false} (default).
*/
@Parameter(property = "rat.addLicenseHeaders", defaultValue = "false")
private String addLicenseHeaders;
/**
- * Copyright message to add to license headers. This option is
- * ignored, unless {@code addLicenseHeaders} is set to {@code true},
- * or {@code forced}.
+ * Copyright message to add to license headers. This option is ignored, unless
+ * {@code addLicenseHeaders} is set to {@code true}, or {@code forced}.
*/
@Parameter(property = "rat.copyrightMessage")
private String copyrightMessage;
/**
- * Will ignore rat errors and display a log message if any.
- * Its use is NOT RECOMMENDED, but quite convenient on occasion.
+ * Will ignore rat errors and display a log message if any. Its use is NOT
+ * RECOMMENDED, but quite convenient on occasion.
*
* @since 0.9
*/
@@ -94,76 +90,46 @@ public class RatCheckMojo extends AbstractRatMojo {
/**
* Whether to output the names of files that have unapproved licenses to the
- * console. Defaults to {@code true} to ease builds in containers where you are unable to access rat.txt easily.
+ * console. Defaults to {@code true} to ease builds in containers where you are
+ * unable to access rat.txt easily.
*
* @since 0.12
*/
@Parameter(property = "rat.consoleOutput", defaultValue = "true")
private boolean consoleOutput;
- private ClaimStatistic getRawReport()
- throws MojoExecutionException, MojoFailureException {
- Writer fw = null;
- try {
- fw = new OutputStreamWriter(
- new FileOutputStream(reportFile),
- StandardCharsets.UTF_8);
- final ClaimStatistic statistic = createReport(fw, getStyleSheet());
- fw.close();
- fw = null;
- return statistic;
- } catch (IOException e) {
- throw new MojoExecutionException(e.getMessage(), e);
- } finally {
- IOUtils.closeQuietly(fw);
- }
- }
-
- /**
- * Returns the XSL stylesheet to be used for formatting the report.
- *
- * @return report stylesheet, or null
for raw XML
- * @throws MojoExecutionException if the stylesheet can not be found
- * @see #reportStyle
- */
- private InputStream getStyleSheet() throws MojoExecutionException {
- if (reportStyle == null || ReportFormat.PLAIN.is(reportStyle)) {
- return Defaults.getPlainStyleSheet();
- } else if (ReportFormat.XML.is(reportStyle)) {
- return null;
- } else {
- try {
- return new FileInputStream(reportStyle);
- } catch (FileNotFoundException e) {
- throw new MojoExecutionException(
- "Unable to find report stylesheet: " + reportStyle, e);
- }
- }
- }
-
/**
* Invoked by Maven to execute the Mojo.
*
- * @throws MojoFailureException An error in the plugin configuration was detected.
- * @throws MojoExecutionException Another error occurred while executing the plugin.
+ * @throws MojoFailureException An error in the plugin configuration was
+ * detected.
+ * @throws MojoExecutionException Another error occurred while executing the
+ * plugin.
*/
+ @Override
public void execute() throws MojoExecutionException, MojoFailureException {
if (skip) {
getLog().info("RAT will not execute since it is configured to be skipped via system property 'rat.skip'.");
return;
}
-
+ ReportConfiguration config = getConfiguration();
+ logLicenses(config.getLicenses(LicenseFilter.all));
final File parent = reportFile.getParentFile();
if (!parent.mkdirs() && !parent.isDirectory()) {
throw new MojoExecutionException("Could not create report parent directory " + parent);
}
- final ClaimStatistic report = getRawReport();
- check(report);
+ try {
+ final ClaimStatistic report = Reporter.report(config);
+ check(report, config);
+ } catch (MojoExecutionException | MojoFailureException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new MojoExecutionException(e.getMessage(), e);
+ }
}
- protected void check(ClaimStatistic statistics)
- throws MojoFailureException {
+ protected void check(ClaimStatistic statistics, ReportConfiguration config) throws MojoFailureException {
if (numUnapprovedLicenses > 0) {
getLog().info("You requested to accept " + numUnapprovedLicenses + " files with unapproved licenses.");
}
@@ -178,38 +144,53 @@ protected void check(ClaimStatistic statistics)
if (numUnapprovedLicenses < statistics.getNumUnApproved()) {
if (consoleOutput) {
try {
- getLog().warn(createReport(Defaults.getUnapprovedLicensesStyleSheet()).trim());
- } catch (MojoExecutionException e) {
+ config.setStyleSheet(Defaults.getUnapprovedLicensesStyleSheet());
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ config.setOut(()->baos);
+ Reporter.report(config);
+ getLog().warn(baos.toString());
+ } catch (Exception e) {
getLog().warn("Unable to print the files with unapproved licenses to the console.");
}
}
final String seeReport = " See RAT report in: " + reportFile;
if (!ignoreErrors) {
- throw new RatCheckException("Too many files with unapproved license: " + statistics.getNumUnApproved() + seeReport);
- } else {
- getLog().warn("Rat check: " + statistics.getNumUnApproved() + " files with unapproved licenses." + seeReport);
+ throw new RatCheckException(
+ "Too many files with unapproved license: " + statistics.getNumUnApproved() + seeReport);
}
+ getLog().warn(
+ "Rat check: " + statistics.getNumUnApproved() + " files with unapproved licenses." + seeReport);
}
}
@Override
- protected ReportConfiguration getConfiguration()
- throws MojoFailureException, MojoExecutionException {
+ protected ReportConfiguration getConfiguration() throws MojoExecutionException {
final ReportConfiguration configuration = super.getConfiguration();
-
- if (AddLicenseHeaders.FORCED.name().equalsIgnoreCase(addLicenseHeaders)) {
- configuration.setAddingLicenses(true);
- configuration.setAddingLicensesForced(true);
- configuration.setCopyrightMessage(copyrightMessage);
- } else if (AddLicenseHeaders.TRUE.name().equalsIgnoreCase(addLicenseHeaders)) {
- configuration.setAddingLicenses(true);
+ if (StringUtils.isNotBlank(addLicenseHeaders)) {
+ configuration.setAddLicenseHeaders(AddLicenseHeaders.valueOf(addLicenseHeaders.toUpperCase()));
+ }
+ if (StringUtils.isNotBlank(copyrightMessage)) {
configuration.setCopyrightMessage(copyrightMessage);
- } else if (AddLicenseHeaders.FALSE.name().equalsIgnoreCase(addLicenseHeaders)) {
- // Nothing to do
- } else {
- throw new MojoFailureException("Invalid value for addLicenseHeaders: Expected " + AddLicenseHeaders.getValuesForHelp() + ", got "
- + addLicenseHeaders);
+ }
+ if (scanHiddenDirectories) {
+ configuration.setDirectoryFilter(null);
+ }
+ if (reportFile != null) {
+ if (!reportFile.exists()) {
+ reportFile.getParentFile().mkdirs();
+ }
+ configuration.setOut(reportFile);
+ }
+ if (StringUtils.isNotBlank(reportStyle)) {
+ if ("xml".equalsIgnoreCase(reportStyle)) {
+ configuration.setStyleReport(false);
+ } else {
+ configuration.setStyleReport(true);
+ if (!"plain".equalsIgnoreCase(reportStyle)) {
+ configuration.setStyleSheet(() -> Files.newInputStream(Paths.get(reportStyle)));
+ }
+ }
}
return configuration;
}
diff --git a/apache-rat-plugin/src/main/java/org/apache/rat/mp/RatReportMojo.java b/apache-rat-plugin/src/main/java/org/apache/rat/mp/RatReportMojo.java
index 04d7d599b..7ea35af56 100644
--- a/apache-rat-plugin/src/main/java/org/apache/rat/mp/RatReportMojo.java
+++ b/apache-rat-plugin/src/main/java/org/apache/rat/mp/RatReportMojo.java
@@ -1,5 +1,3 @@
-package org.apache.rat.mp;
-
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
@@ -18,6 +16,22 @@
* specific language governing permissions and limitations
* under the License.
*/
+package org.apache.rat.mp;
+
+import static org.apache.maven.shared.utils.logging.MessageUtils.buffer;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.ResourceBundle;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.repository.ArtifactRepository;
@@ -32,25 +46,19 @@
import org.apache.maven.doxia.siterenderer.sink.SiteRendererSink;
import org.apache.maven.doxia.tools.SiteTool;
import org.apache.maven.doxia.tools.SiteToolException;
+import org.apache.maven.execution.MavenSession;
import org.apache.maven.plugin.MojoExecutionException;
-import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.plugins.annotations.ResolutionScope;
import org.apache.maven.reporting.MavenMultiPageReport;
import org.apache.maven.reporting.MavenReportException;
-import org.apache.maven.shared.utils.WriterFactory;
-import org.apache.rat.Defaults;
+import org.apache.rat.ReportConfiguration;
+import org.apache.rat.Reporter;
+import org.apache.rat.license.LicenseSetFactory.LicenseFilter;
import org.codehaus.plexus.util.ReaderFactory;
-import java.io.*;
-import java.nio.file.Files;
-import java.util.*;
-
-import static org.apache.maven.shared.utils.logging.MessageUtils.buffer;
-
-
/**
* Generates a report with Rat's output.
*/
@@ -58,9 +66,10 @@
public class RatReportMojo extends AbstractRatMojo implements MavenMultiPageReport {
/**
- * The output directory for the report. Note that this parameter is only evaluated if the goal is run directly from
- * the command line. If the goal is run indirectly as part of a site generation, the output directory configured in
- * the Maven Site Plugin is used instead.
+ * The output directory for the report. Note that this parameter is only
+ * evaluated if the goal is run directly from the command line. If the goal is
+ * run indirectly as part of a site generation, the output directory configured
+ * in the Maven Site Plugin is used instead.
*/
@Parameter(defaultValue = "${project.reporting.outputDirectory}", readonly = true, required = true)
protected File outputDirectory;
@@ -80,8 +89,8 @@ public class RatReportMojo extends AbstractRatMojo implements MavenMultiPageRepo
/**
* The local repository.
*/
- @Parameter(defaultValue = "${localRepository}", readonly = true, required = true)
- protected ArtifactRepository localRepository;
+ @Parameter(defaultValue = "${session}", readonly = true, required = true)
+ protected MavenSession session;
/**
* Remote repositories used for the project.
@@ -116,16 +125,15 @@ public class RatReportMojo extends AbstractRatMojo implements MavenMultiPageRepo
*/
private File reportOutputDirectory;
-
/**
- * This method is called when the report generation is invoked directly as a standalone Mojo.
+ * This method is called when the report generation is invoked directly as a
+ * standalone Mojo.
*
* @throws MojoExecutionException if an error occurs when generating the report
* @see org.apache.maven.plugin.Mojo#execute()
*/
@Override
- public void execute()
- throws MojoExecutionException {
+ public void execute() throws MojoExecutionException {
if (!canGenerateReport()) {
return;
}
@@ -153,9 +161,8 @@ public void execute()
if (!isExternalReport()) {
outputDirectory.mkdirs();
- try (Writer writer =
- new OutputStreamWriter(Files.newOutputStream(new File(outputDirectory, filename).toPath()),
- getOutputEncoding())) {
+ try (Writer writer = new OutputStreamWriter(
+ Files.newOutputStream(new File(outputDirectory, filename).toPath()), getOutputEncoding())) {
// render report
getSiteRenderer().mergeDocumentIntoSite(writer, sink, siteContext);
}
@@ -169,8 +176,7 @@ public void execute()
}
}
- private SiteRenderingContext createSiteRenderingContext(Locale locale)
- throws MavenReportException, IOException {
+ private SiteRenderingContext createSiteRenderingContext(Locale locale) throws MavenReportException, IOException {
DecorationModel decorationModel = new DecorationModel();
Map templateProperties = new HashMap<>();
@@ -186,11 +192,11 @@ private SiteRenderingContext createSiteRenderingContext(Locale locale)
SiteRenderingContext context;
try {
- Artifact skinArtifact =
- siteTool.getSkinArtifactFromRepository(localRepository, remoteRepositories, decorationModel);
+ Artifact skinArtifact = siteTool.getSkinArtifactFromRepository(session.getLocalRepository(),
+ remoteRepositories, decorationModel);
- getLog().info(buffer().a("Rendering content with ").strong(skinArtifact.getId()
- + " skin").a('.').toString());
+ getLog().debug(
+ buffer().a("Rendering content with ").strong(skinArtifact.getId() + " skin").a('.').build());
context = siteRenderer.createContextForSkin(skinArtifact, templateProperties, decorationModel,
project.getName(), locale);
@@ -209,43 +215,41 @@ private SiteRenderingContext createSiteRenderingContext(Locale locale)
/**
* Generate a report.
*
- * @param sink the sink to use for the generation.
+ * @param sink the sink to use for the generation.
* @param locale the wanted locale to generate the report, could be null.
* @throws MavenReportException if any
* @deprecated use {@link #generate(Sink, SinkFactory, Locale)} instead.
*/
@Deprecated
@Override
- public void generate(org.codehaus.doxia.sink.Sink sink, Locale locale)
- throws MavenReportException {
+ public void generate(org.codehaus.doxia.sink.Sink sink, Locale locale) throws MavenReportException {
generate(sink, null, locale);
}
/**
* Generate a report.
*
- * @param sink
- * @param locale
- * @throws MavenReportException
+ * @param sink the sink to use for the generation.
+ * @param locale the wanted locale to generate the report, could be null.
+ * @throws MavenReportException if any
* @deprecated use {@link #generate(Sink, SinkFactory, Locale)} instead.
*/
@Deprecated
- public void generate(Sink sink, Locale locale)
- throws MavenReportException {
+ public void generate(Sink sink, Locale locale) throws MavenReportException {
generate(sink, null, locale);
}
/**
- * This method is called when the report generation is invoked by maven-site-plugin.
+ * This method is called when the report generation is invoked by
+ * maven-site-plugin.
*
- * @param sink
- * @param sinkFactory
- * @param locale
- * @throws MavenReportException
+ * @param sink the sink to use for the generation.
+ * @param sinkFactory the sink factory to use for the generation.
+ * @param locale the wanted locale to generate the report, could be null.
+ * @throws MavenReportException if any
*/
@Override
- public void generate(Sink sink, SinkFactory sinkFactory, Locale locale)
- throws MavenReportException {
+ public void generate(Sink sink, SinkFactory sinkFactory, Locale locale) throws MavenReportException {
if (!canGenerateReport()) {
getLog().info("This report cannot be generated as part of the current build. "
+ "The report name should be referenced in this line of output.");
@@ -304,10 +308,11 @@ protected String getInputEncoding() {
/**
* Gets the effective reporting output files encoding.
*
- * @return The effective reporting output file encoding, never null
.
+ * @return The effective reporting output file encoding, never
+ * null
.
*/
protected String getOutputEncoding() {
- return (outputEncoding == null) ? WriterFactory.UTF_8 : outputEncoding;
+ return (outputEncoding == null) ? StandardCharsets.UTF_8.toString() : outputEncoding;
}
/**
@@ -350,10 +355,11 @@ public boolean canGenerateReport() {
*
* @return Version number, if found, or null.
*/
- // TODO The canonical way is to read the pom.properties for the artifact desired in META-INF/maven
+ // TODO The canonical way is to read the pom.properties for the artifact desired
+ // in META-INF/maven
private String getRatVersion() {
- //noinspection unchecked
- for (Artifact a : (Iterable) getProject().getDependencyArtifacts()) {
+ // noinspection unchecked
+ for (Artifact a : getProject().getDependencyArtifacts()) {
if ("rat-lib".equals(a.getArtifactId())) {
return a.getVersion();
}
@@ -398,8 +404,15 @@ protected void executeReport(Locale locale) throws MavenReportException {
sink.paragraph();
sink.verbatim(SinkEventAttributeSet.BOXED);
try {
- sink.text(createReport(Defaults.getDefaultStyleSheet()));
- } catch (MojoExecutionException | MojoFailureException e) {
+ ReportConfiguration config = getConfiguration();
+ config.setFrom(getDefaultsBuilder().build());
+ //config.setStyleSheet(Defaults.getUnapprovedLicensesStyleSheet());
+ logLicenses(config.getLicenses(LicenseFilter.all));
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ config.setOut(()->baos);
+ Reporter.report(config);
+ sink.text(baos.toString());
+ } catch (Exception e) {
throw new MavenReportException(e.getMessage(), e);
}
sink.verbatim_();
@@ -422,8 +435,10 @@ private ResourceBundle getBundle(Locale locale) {
* Returns the reports description.
*
* @param locale Requested locale of the bundle
- * @return Report description, as given by the key "report.rat.description" in the bundle.
+ * @return Report description, as given by the key "report.rat.description" in
+ * the bundle.
*/
+ @Override
public String getDescription(Locale locale) {
return getBundle(locale).getString("report.rat.description");
}
@@ -434,6 +449,7 @@ public String getDescription(Locale locale) {
* @param locale Requested locale of the bundle
* @return Report name, as given by the key "report.rat.name" in the bundle.
*/
+ @Override
public String getName(Locale locale) {
return getBundle(locale).getString("report.rat.name");
}
@@ -443,6 +459,7 @@ public String getName(Locale locale) {
*
* @return "rat-report"
*/
+ @Override
public String getOutputName() {
return "rat-report";
}
diff --git a/apache-rat-plugin/src/main/java/org/apache/rat/mp/Regex.java b/apache-rat-plugin/src/main/java/org/apache/rat/mp/Regex.java
new file mode 100644
index 000000000..e8fedaf4a
--- /dev/null
+++ b/apache-rat-plugin/src/main/java/org/apache/rat/mp/Regex.java
@@ -0,0 +1,37 @@
+/*
+ * 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.mp;
+
+import javax.inject.Named;
+
+import org.apache.rat.configuration.builders.RegexBuilder;
+
+public class Regex extends RegexBuilder {
+
+ @Named("expr")
+ public RegexBuilder setExpr(String exp) {
+ System.out.format("Calling setText() with %s\n", exp);
+ return super.setExpr(exp);
+ }
+ public void set(String exp) {
+ System.out.format("Calling set() with %s\n", exp);
+ setExpr(exp);
+ }
+
+}
diff --git a/apache-rat-plugin/src/main/java/org/apache/rat/mp/Spdx.java b/apache-rat-plugin/src/main/java/org/apache/rat/mp/Spdx.java
new file mode 100644
index 000000000..54620d78a
--- /dev/null
+++ b/apache-rat-plugin/src/main/java/org/apache/rat/mp/Spdx.java
@@ -0,0 +1,30 @@
+/*
+ * 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.mp;
+
+import org.apache.maven.plugins.annotations.Parameter;
+import org.apache.rat.configuration.builders.SpdxBuilder;
+
+public class Spdx extends SpdxBuilder {
+
+ @Parameter(name="name")
+ public void set(String name) {
+ super.setName(name);
+ }
+}
diff --git a/apache-rat-plugin/src/main/java/org/apache/rat/mp/Text.java b/apache-rat-plugin/src/main/java/org/apache/rat/mp/Text.java
new file mode 100644
index 000000000..1ecf0718a
--- /dev/null
+++ b/apache-rat-plugin/src/main/java/org/apache/rat/mp/Text.java
@@ -0,0 +1,27 @@
+/*
+ * 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.mp;
+
+import org.apache.rat.configuration.builders.TextBuilder;
+
+public class Text extends TextBuilder {
+ public void set(String text) {
+ super.setText(text);
+ }
+}
diff --git a/apache-rat-plugin/src/main/java/org/apache/rat/mp/util/ExclusionHelper.java b/apache-rat-plugin/src/main/java/org/apache/rat/mp/util/ExclusionHelper.java
index 9552cc513..0c7346473 100644
--- a/apache-rat-plugin/src/main/java/org/apache/rat/mp/util/ExclusionHelper.java
+++ b/apache-rat-plugin/src/main/java/org/apache/rat/mp/util/ExclusionHelper.java
@@ -2,13 +2,15 @@
import org.apache.maven.plugin.logging.Log;
import org.apache.rat.config.SourceCodeManagementSystems;
-import org.codehaus.plexus.util.DirectoryScanner;
import java.util.Arrays;
import java.util.Collections;
+import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import static org.codehaus.plexus.util.AbstractScanner.DEFAULTEXCLUDES;
+
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
@@ -40,10 +42,11 @@ public final class ExclusionHelper {
.unmodifiableList(Arrays.asList(//
"target/**/*", //
"cobertura.ser", //
+ "**/MANIFEST.MF", // a MANIFEST.MF file cannot contain comment lines. In other words: It is not possible, to include a license.
"release.properties", //
".repository", // Used by Jenkins when a Maven job uses a private repository that is "Local to the workspace"
"build.log", // RAT-160: until now maven-invoker-plugin runs create a build.log that is not part of a release
- ".mvn", // Project configuration since Maven 3.3.1 which contains maven.config, jvm.config, extensions.xml
+ ".mvn/**/*", // Project configuration since Maven 3.3.1 which contains maven.config, jvm.config, extensions.xml
"pom.xml.releaseBackup"));
/**
@@ -67,22 +70,22 @@ public final class ExclusionHelper {
"*.iws", //
".idea/**/*"));
- public static void addPlexusAndScmDefaults(Log log, final boolean useDefaultExcludes,
- final Set excludeList1) {
+ public static Set addPlexusAndScmDefaults(Log log, final boolean useDefaultExcludes) {
+ Set excludeList = new HashSet<>();
if (useDefaultExcludes) {
log.debug("Adding plexus default exclusions...");
- Collections.addAll(excludeList1, DirectoryScanner.DEFAULTEXCLUDES);
+ Collections.addAll(excludeList, DEFAULTEXCLUDES);
log.debug("Adding SCM default exclusions...");
- excludeList1.addAll(//
- SourceCodeManagementSystems.getPluginExclusions());
+ excludeList.addAll(SourceCodeManagementSystems.getPluginExclusions());
} else {
log.debug("rat.useDefaultExcludes set to false. "
+ "Plexus and SCM default exclusions will not be added");
}
+ return excludeList;
}
- public static void addMavenDefaults(Log log, boolean useMavenDefaultExcludes,
- final Set excludeList) {
+ public static Set addMavenDefaults(Log log, boolean useMavenDefaultExcludes) {
+ Set excludeList = new HashSet<>();
if (useMavenDefaultExcludes) {
log.debug("Adding exclusions often needed by Maven projects...");
excludeList.addAll(MAVEN_DEFAULT_EXCLUDES);
@@ -90,10 +93,11 @@ public static void addMavenDefaults(Log log, boolean useMavenDefaultExcludes,
log.debug("rat.useMavenDefaultExcludes set to false. "
+ "Exclusions often needed by Maven projects will not be added.");
}
+ return excludeList;
}
- public static void addEclipseDefaults(Log log, boolean useEclipseDefaultExcludes,
- final Set excludeList) {
+ public static Set addEclipseDefaults(Log log, boolean useEclipseDefaultExcludes) {
+ Set excludeList = new HashSet<>();
if (useEclipseDefaultExcludes) {
log.debug("Adding exclusions often needed by projects "
+ "developed in Eclipse...");
@@ -103,10 +107,11 @@ public static void addEclipseDefaults(Log log, boolean useEclipseDefaultExcludes
+ "Exclusions often needed by projects developed in "
+ "Eclipse will not be added.");
}
+ return excludeList;
}
- public static void addIdeaDefaults(Log log, boolean useIdeaDefaultExcludes,
- final Set excludeList) {
+ public static Set addIdeaDefaults(Log log, boolean useIdeaDefaultExcludes) {
+ Set excludeList = new HashSet<>();
if (useIdeaDefaultExcludes) {
log.debug("Adding exclusions often needed by projects "
+ "developed in IDEA...");
@@ -116,6 +121,7 @@ public static void addIdeaDefaults(Log log, boolean useIdeaDefaultExcludes,
+ "Exclusions often needed by projects developed in "
+ "IDEA will not be added.");
}
+ return excludeList;
}
}
diff --git a/apache-rat-plugin/src/main/java/org/apache/rat/mp/util/ScmIgnoreParser.java b/apache-rat-plugin/src/main/java/org/apache/rat/mp/util/ScmIgnoreParser.java
index 97b81c16f..675a3644c 100644
--- a/apache-rat-plugin/src/main/java/org/apache/rat/mp/util/ScmIgnoreParser.java
+++ b/apache-rat-plugin/src/main/java/org/apache/rat/mp/util/ScmIgnoreParser.java
@@ -20,16 +20,14 @@
*/
-import org.apache.commons.io.IOUtils;
import org.apache.maven.plugin.logging.Log;
import org.apache.rat.config.SourceCodeManagementSystems;
+import org.apache.rat.mp.util.ignore.GitIgnoreMatcher;
+import org.apache.rat.mp.util.ignore.GlobIgnoreMatcher;
+import org.apache.rat.mp.util.ignore.IgnoreMatcher;
-import java.io.BufferedReader;
import java.io.File;
-import java.io.FileReader;
-import java.io.IOException;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.List;
/**
@@ -41,41 +39,6 @@ private ScmIgnoreParser() {
// prevent instantiation of utility class
}
- private static final List COMMENT_PREFIXES = Arrays.asList("#", "##", "//", "/**", "/*");
-
- /**
- * Parses excludes from the given SCM ignore file.
- *
- * @param log Maven log to show output during RAT runs.
- * @param scmIgnore if null
or invalid an empty list of exclusions is returned.
- * @return all exclusions (=non-comment lines) from the SCM ignore file.
- */
- public static List getExcludesFromFile(final Log log, final File scmIgnore) {
-
- final List exclusionLines = new ArrayList<>();
-
- if (scmIgnore != null && scmIgnore.exists() && scmIgnore.isFile()) {
- log.info("Parsing exclusions from " + scmIgnore);
- BufferedReader reader = null;
- try {
- reader = new BufferedReader(new FileReader(scmIgnore));
- String line;
- while ((line = reader.readLine()) != null) {
- if (!isComment(line)) {
- exclusionLines.add(line);
- log.debug("Added " + line);
- }
- }
- } catch (final IOException e) {
- log.warn("Cannot parse " + scmIgnore + " for exclusions. Will skip this file.");
- log.debug("Skip parsing " + scmIgnore + " due to " + e.getMessage());
- } finally {
- IOUtils.closeQuietly(reader);
- }
- }
- return exclusionLines;
- }
-
/**
* Parse ignore files from all known SCMs that have ignore files.
*
@@ -83,36 +46,28 @@ public static List getExcludesFromFile(final Log log, final File scmIgno
* @param baseDir base directory from which to look for SCM ignores.
* @return Exclusions from the SCM ignore files.
*/
- public static List getExclusionsFromSCM(final Log log, final File baseDir) {
- List exclusions = new ArrayList<>();
+ public static List getExclusionsFromSCM(final Log log, final File baseDir) {
+ List ignoreMatchers = new ArrayList<>();
for (SourceCodeManagementSystems scm : SourceCodeManagementSystems.values()) {
- if (scm.hasIgnoreFile()) {
- exclusions.addAll(getExcludesFromFile(log, new File(baseDir, scm.getIgnoreFile())));
+ switch (scm) {
+ case GIT:
+ GitIgnoreMatcher gitIgnoreMatcher = new GitIgnoreMatcher(log, baseDir);
+ if (!gitIgnoreMatcher.isEmpty()) {
+ ignoreMatchers.add(gitIgnoreMatcher);
+ }
+ break;
+ default:
+ if (scm.hasIgnoreFile()) {
+ GlobIgnoreMatcher ignoreMatcher = new GlobIgnoreMatcher(log, new File(baseDir, scm.getIgnoreFile()));
+ if (!ignoreMatcher.isEmpty()) {
+ ignoreMatchers.add(ignoreMatcher);
+ }
+ }
+ break;
}
}
- return exclusions;
-
+ return ignoreMatchers;
}
- /**
- * Determines whether the given line is a comment or not based on scanning
- * for prefixes
- * {@see COMMENT_PREFIXES}.
- *
- * @param line line to verify.
- * @return true
if the given line is a commented out line.
- */
- static boolean isComment(final String line) {
- if (line == null || line.length() <= 0) {
- return false;
- }
- final String trimLine = line.trim();
- for (String prefix : COMMENT_PREFIXES) {
- if (trimLine.startsWith(prefix)) {
- return true;
- }
- }
- return false;
- }
}
diff --git a/apache-rat-plugin/src/main/java/org/apache/rat/mp/util/ignore/GitIgnoreMatcher.java b/apache-rat-plugin/src/main/java/org/apache/rat/mp/util/ignore/GitIgnoreMatcher.java
new file mode 100644
index 000000000..844ce90c6
--- /dev/null
+++ b/apache-rat-plugin/src/main/java/org/apache/rat/mp/util/ignore/GitIgnoreMatcher.java
@@ -0,0 +1,56 @@
+package org.apache.rat.mp.util.ignore;
+
+/*
+ * 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.
+ */
+
+import nl.basjes.gitignore.GitIgnoreFileSet;
+import org.apache.maven.plugin.logging.Log;
+
+import java.io.File;
+import java.util.Optional;
+
+public class GitIgnoreMatcher implements IgnoreMatcher {
+
+ private final GitIgnoreFileSet gitIgnoreFileSet;
+
+ public GitIgnoreMatcher(final Log log, final File projectBaseDir) {
+ log.debug("Recursively loading .gitignore files in " + projectBaseDir);
+ // This will walk the project tree and load all .gitignore files
+ gitIgnoreFileSet = new GitIgnoreFileSet(projectBaseDir);
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return gitIgnoreFileSet.isEmpty();
+ }
+
+ @Override
+ public Optional isIgnoredFile(String filename) {
+ Boolean isIgnoredFile = gitIgnoreFileSet.isIgnoredFile(filename);
+ if (isIgnoredFile == null) {
+ return Optional.empty();
+ }
+ return Optional.of(isIgnoredFile);
+ }
+
+ @Override
+ public String toString() {
+ return "Loaded .gitignore data:\n" + gitIgnoreFileSet;
+ }
+}
diff --git a/apache-rat-plugin/src/main/java/org/apache/rat/mp/util/ignore/GlobIgnoreMatcher.java b/apache-rat-plugin/src/main/java/org/apache/rat/mp/util/ignore/GlobIgnoreMatcher.java
new file mode 100644
index 000000000..de9061bd8
--- /dev/null
+++ b/apache-rat-plugin/src/main/java/org/apache/rat/mp/util/ignore/GlobIgnoreMatcher.java
@@ -0,0 +1,132 @@
+package org.apache.rat.mp.util.ignore;
+
+/*
+ * 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.
+ */
+
+import org.apache.maven.plugin.logging.Log;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Optional;
+
+public class GlobIgnoreMatcher implements IgnoreMatcher {
+
+ final List exclusionLines = new ArrayList<>();
+
+ private static final List COMMENT_PREFIXES = Arrays.asList("#", "##", "//", "/**", "/*");
+
+ public GlobIgnoreMatcher() {
+ // No rules to load
+ }
+
+ public GlobIgnoreMatcher(final Log log, final File scmIgnore) {
+ loadFile(log, scmIgnore);
+ }
+
+ /**
+ * Add a single rule to the set
+ * @param rule The line that matches some files
+ */
+ public void addRule(final String rule) {
+ if (!exclusionLines.contains(rule)) {
+ exclusionLines.add(rule);
+ }
+ }
+
+ /**
+ * Add a set of rules to the set
+ * @param rules The line that matches some files
+ */
+ public void addRules(final Collection rules) {
+ for (String rule : rules) {
+ if (!exclusionLines.contains(rule)) {
+ exclusionLines.add(rule);
+ }
+ }
+ }
+
+ /**
+ * Parses excludes from the given SCM ignore file.
+ *
+ * @param log Maven log to show output during RAT runs.
+ * @param scmIgnore if null
or invalid an empty list of exclusions is returned.
+ */
+ public void loadFile(final Log log, final File scmIgnore) {
+ if (scmIgnore != null && scmIgnore.exists() && scmIgnore.isFile()) {
+ log.debug("Parsing exclusions from " + scmIgnore);
+
+ try (BufferedReader reader = new BufferedReader(new FileReader(scmIgnore))) {
+ String line;
+ while ((line = reader.readLine()) != null) {
+ if (!isComment(line)) {
+ exclusionLines.add(line);
+ log.debug("Added " + line);
+ }
+ }
+ } catch (final IOException e) {
+ log.warn("Cannot parse " + scmIgnore + " for exclusions. Will skip this file.");
+ log.debug("Skip parsing " + scmIgnore + " due to " + e.getMessage());
+ }
+ }
+ }
+
+ /**
+ * Determines whether the given line is a comment or not based on scanning
+ * for prefixes
+ * @see #COMMENT_PREFIXES
+ *
+ * @param line line to verify.
+ * @return true
if the given line is a commented out line.
+ */
+ public static boolean isComment(final String line) {
+ if (line == null || line.length() <= 0) {
+ return false;
+ }
+
+ final String trimLine = line.trim();
+ for (String prefix : COMMENT_PREFIXES) {
+ if (trimLine.startsWith(prefix)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public List getExclusionLines() {
+ return exclusionLines;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return exclusionLines.isEmpty();
+ }
+
+ @Override
+ public Optional isIgnoredFile(String filename) {
+ // Not used for Glob Rules; using the DirectoryScanner instead
+ // It CAN be moved here if so desired.
+ return Optional.empty() ;
+ }
+}
diff --git a/apache-rat-plugin/src/main/java/org/apache/rat/mp/util/ignore/IgnoreMatcher.java b/apache-rat-plugin/src/main/java/org/apache/rat/mp/util/ignore/IgnoreMatcher.java
new file mode 100644
index 000000000..c1d1f49fd
--- /dev/null
+++ b/apache-rat-plugin/src/main/java/org/apache/rat/mp/util/ignore/IgnoreMatcher.java
@@ -0,0 +1,37 @@
+package org.apache.rat.mp.util.ignore;
+
+/*
+ * 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.
+ */
+
+import java.util.Optional;
+
+public interface IgnoreMatcher {
+ /**
+ * Checks if the file matches the stored expressions.
+ * @param filename The filename to be checked
+ * @return empty: not matched, True: must be ignored, False: it must be UNignored
+ */
+ Optional isIgnoredFile(String filename);
+
+ /**
+ * Returns {@code true} if this IgnoreMatcher contains no rules.
+ * @return {@code true} if this IgnoreMatcher contains no rules
+ */
+ boolean isEmpty();
+}
diff --git a/apache-rat-plugin/src/main/java/org/apache/rat/mp/util/ignore/IgnoringDirectoryScanner.java b/apache-rat-plugin/src/main/java/org/apache/rat/mp/util/ignore/IgnoringDirectoryScanner.java
new file mode 100644
index 000000000..d8e340a4a
--- /dev/null
+++ b/apache-rat-plugin/src/main/java/org/apache/rat/mp/util/ignore/IgnoringDirectoryScanner.java
@@ -0,0 +1,74 @@
+package org.apache.rat.mp.util.ignore;
+
+/*
+ * 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.
+ */
+
+import org.codehaus.plexus.util.DirectoryScanner;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static java.lang.Boolean.FALSE;
+import static java.lang.Boolean.TRUE;
+
+public class IgnoringDirectoryScanner extends DirectoryScanner {
+
+ public IgnoringDirectoryScanner() {
+ super();
+ }
+
+ List ignoreMatcherList = new ArrayList<>();
+
+ public void addIgnoreMatcher(IgnoreMatcher ignoreMatcher) {
+ ignoreMatcherList.add(ignoreMatcher);
+ }
+
+ private boolean matchesAnIgnoreMatcher(String name) {
+ for (IgnoreMatcher ignoreMatcher : ignoreMatcherList) {
+ if (ignoreMatcher.isIgnoredFile(name).orElse(FALSE) == TRUE) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ protected boolean isExcluded(String name) {
+ if (matchesAnIgnoreMatcher(name)) {
+ return true;
+ }
+ return super.isExcluded(name);
+ }
+
+ @Override
+ protected boolean isExcluded(String name, String[] tokenizedName) {
+ if (matchesAnIgnoreMatcher(name)) {
+ return true;
+ }
+ return super.isExcluded(name, tokenizedName);
+ }
+
+ @Override
+ protected boolean isExcluded(String name, char[][] tokenizedName) {
+ if (matchesAnIgnoreMatcher(name)) {
+ return true;
+ }
+ return super.isExcluded(name, tokenizedName);
+ }
+}
diff --git a/apache-rat-plugin/src/site/apt/examples/custom-license.apt.vm b/apache-rat-plugin/src/site/apt/examples/custom-license.apt.vm
index 21814ad25..44930de53 100644
--- a/apache-rat-plugin/src/site/apt/examples/custom-license.apt.vm
+++ b/apache-rat-plugin/src/site/apt/examples/custom-license.apt.vm
@@ -4,9 +4,9 @@
~~ 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.
@@ -20,12 +20,20 @@
Custom License Matchers
Rat comes with a set of predefined license matchers, that can be used
- some typical licenses. However, they will not always be sufficient.
- In such cases, you may use a custom license matcher.
+ on typical licenses. However, they will not always be sufficient.
+ In such cases, you may configure a custom license matcher.
- A custom license matcher is an implementation of
- <<>>. Suggest that your
- source files must contain a header like the following:
+ The simplest way to create a license check is to create an XML file describing
+ the new license and add it to the processing with the additionalLicenseFiles
+ option.
+
+ The second option is to define the custom license directly in the POM.
+ Unlike earlier version (before 0.16) no custom implementations are required to define
+ custom licenses.
+
+ There is a file that defines all of the standard licenses: {{{https://github.com/apache/creadur-rat/blob/master/apache-rat-core/src/main/resources/org/apache/rat/default.xml}default.xml}}
+
+ Please be aware that custom licenses need to have <>, otherwise a warning is issued and your custom definitions are ignored in favour of the standard license definitions.
------------------------------------------------------------------
/**
@@ -49,15 +57,18 @@ Custom License Matchers
${currentVersion}
-
- YASL1
- Yet Another Software License (YASL) 1.0
+
+ YASL1
-
- Yet Another Software License, 1.0
-
+ Yet Another Software License, 1.0
+
+
+ YASL1
+ Yet Another Software License
+
+
...
@@ -65,33 +76,18 @@ Custom License Matchers
------------------------------------------------------------------
- The following terms are used in the example:
+ This is very similar to the XML format for defining the configuration.
-*-----------------------+-----------+
-| licenseFamilyCategory | The license family category is a very short string (exactly 5 characters, preferrably no blanks),
-| | which identifies the license. For example, this could be <<>> to identify the
-| | Apache License, 2.0.
-*-----------------------+-----------+
-| licenseFamilyName | The license family name is a longer string, which gives the licenses full name. For example,
-| | this could be <<>>.
-*-----------------------+-----------+
-| notes | You might specify additional notes here, like "Dual licensed GPL/MPL".
-*-----------------------+-----------+
-| patterns | Specifies a set of patterns being searched. The source file is assumed to contain the
-| | license header, if at least one of these patterns is found.
-*-----------------------+-----------+
Approved License Families
- Detecting the license is not enough in many cases as the "new"
- license may not be considered approved by Rat. In order to make a
- license approved you provide a custom implementation of
- <<>>. Usually all you need
- to provide the name of the license, in which case the built-in
- <<>> will do.
+ By default all POM defined licenses are considered approved, this is a
+ change from pre 0.16 versions. If there are families that are defined in
+ the pom but that should not be considered approved then a list of approved
+ license families must be provided.
- To continue the example, in order to make the YASL1 license approved
- you'd use
+ In the following example, we define YASL1 and BAD1 and then indicate that
+ BAD1 is bad by specifying that YASL1 is good.
------------------------------------------------------------------
@@ -103,20 +99,25 @@ Approved License Families
${currentVersion}
-
- YASL1
- Yet Another Software License (YASL) 1.0
+
+ YASL1
-
- Yet Another Software License, 1.0
-
+ Yet Another Software License, 1.0
-
-
- Yet Another Software License (YASL) 1.0
-
-
+
+
+ YASL1
+ Yet Another Software License
+
+
+ BAD1
+ A Bad Sofware License
+
+
+
+ YASL1
+
...
@@ -124,10 +125,114 @@ Approved License Families
------------------------------------------------------------------
- The following terms are used in the example:
+Overview of configuration options
+
+ When defining custom licenses, remember the following architecture constraints:
+
+ * Each license is associated with a family. Multiple licenses can be associated with a family.
+
+ * Each license may have a notes element.
+
+ * Each license has one matcher.
+
+* Matcher details
+
+ <> - A collection of matchers in which all enclosed matchers have to be true for the matcher to report true.
+
+------------------------------------------------------------------
+
+ This text is required
+ as is this text, both have to trigger before 'all' will be true
+
+------------------------------------------------------------------
+
+ <> - A collection of matchers that will report true if any enclosed matcher is true.
+
+------------------------------------------------------------------
+
+ This text will trigger a match all by itself
+ So will this text.
+
+------------------------------------------------------------------
+
+ <> - A matcher that matches Copyright text.
+ This uses regular expressions and so should only be used when looking for copyrights with specific patterns that are not caught by a standard text matcher.
+ This matcher will match <<<"(C)">>>, <<<"copyright">>>, or <<<"©">>>. (text is not case sensitive).
+ It will also match things like <<>> as well as <<>> and <<>>.
+ Copyright has 3 child elements:
+
+ * <> - the starting date of the copyright or the only date.
+
+ * <> - the ending date of the copyright. Only valid if the starting date is provided.
+
+ * <> - the copyright owner.
+
+------------------------------------------------------------------
+
+
+ 1995
+ 1996
+ joe
+
-*-----------------------+-----------+
-| familyName | The name of the license family name that is approved.
-| | This should match <<>> of your <<>>
-*-----------------------+-----------+
+
+ 1995
+ joe
+
+
+
+ joe
+
+
+
+
+
+------------------------------------------------------------------
+
+ <> - A matcher that wraps one matcher and negates its value. Not matchers require that the entire header be read before it can report true or false. This may significantly slow processing.
+
+------------------------------------------------------------------
+
+ This text must not be present
+
+------------------------------------------------------------------
+
+ <> - A matcher that matches a regex string.
+
+------------------------------------------------------------------
+[H|h]ello\s[W|w]orld
+------------------------------------------------------------------
+
+
+ <> - A matcher that matches SPDX tags. SPDX tags have the form: <<>>, where short-name matches the regex pattern <<<"[A-Za-z0-9\.\-]+".>>> spdx takes the short name as an argument.
+
+------------------------------------------------------------------
+Apache-2.0
+------------------------------------------------------------------
+
+
+** Combining the examples together
+
+------------------------------------------------------------------
+
+
+
+ This text is required
+
+
+
+ joe
+
+
+ [H|h]ello\s[W|w]orld
+
+ Apache-2.0
+
+
+
+ This text must not be present
+
+
+------------------------------------------------------------------
+~~ https://maven.apache.org/doxia/references/apt-format.html
diff --git a/apache-rat-plugin/src/site/apt/usage.apt.vm b/apache-rat-plugin/src/site/apt/usage.apt.vm
index 710f9bbb7..497a6ccf4 100644
--- a/apache-rat-plugin/src/site/apt/usage.apt.vm
+++ b/apache-rat-plugin/src/site/apt/usage.apt.vm
@@ -21,7 +21,7 @@ Usage
To use the plugin, you've got two options: First of all, it can
create a simple text file, called <<>>, with the
- plugins output. This is done by invoking the <<>> goal.
+ plugin's output. This is done by invoking the <<>> goal.
You may also add a report to the generated site. This is your
second option.
diff --git a/apache-rat-plugin/src/test/java/org/apache/rat/mp/BetterAbstractMojoTestCase.java b/apache-rat-plugin/src/test/java/org/apache/rat/mp/BetterAbstractMojoTestCase.java
new file mode 100644
index 000000000..254da237e
--- /dev/null
+++ b/apache-rat-plugin/src/test/java/org/apache/rat/mp/BetterAbstractMojoTestCase.java
@@ -0,0 +1,118 @@
+
+/*
+ * 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.
+ *
+*
+ * This software is copyright (c) 2015 by Alex Heneveld and Cloudsoft Corporation.
+ *
+ * code lifted from https://github.com/ahgittin/license-audit-maven-plugin
+ */
+package org.apache.rat.mp;
+
+import java.io.File;
+import java.util.Arrays;
+
+import org.apache.maven.DefaultMaven;
+import org.apache.maven.Maven;
+import org.apache.maven.execution.DefaultMavenExecutionRequest;
+import org.apache.maven.execution.DefaultMavenExecutionResult;
+import org.apache.maven.execution.MavenExecutionRequest;
+import org.apache.maven.execution.MavenExecutionRequestPopulator;
+import org.apache.maven.execution.MavenExecutionResult;
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.plugin.Mojo;
+import org.apache.maven.plugin.testing.AbstractMojoTestCase;
+import org.apache.maven.project.MavenProject;
+import org.apache.maven.project.ProjectBuilder;
+import org.apache.maven.project.ProjectBuildingRequest;
+import org.eclipse.aether.DefaultRepositorySystemSession;
+import org.eclipse.aether.internal.impl.SimpleLocalRepositoryManagerFactory;
+import org.eclipse.aether.repository.LocalRepository;
+
+/** Use this as you would {@link AbstractMojoTestCase},
+ * where you want more of the standard maven defaults to be set
+ * (and where the {@link AbstractMojoTestCase} leaves them as null or empty).
+ * This includes:
+ * local repo, repo sessions and managers configured
+ * maven default remote repos installed (NB: this does not use your ~/.m2 local settings)
+ * system properties are copies
+ *
+ * No changes to subclass code is needed; this simply intercepts the {@link #newMavenSession(MavenProject)} method
+ * used by the various {@link #lookupMojo(String, File)} methods.
+ *
+ * This also provides new methods, {@link #newMavenSession()} to conveniently create a maven session,
+ * and {@link #lookupConfiguredMojo(File, String)} so you don't have to always build the project yourself.
+ */
+public abstract class BetterAbstractMojoTestCase extends AbstractMojoTestCase {
+
+ protected MavenSession newMavenSession() {
+ try {
+ MavenExecutionRequest request = new DefaultMavenExecutionRequest();
+ MavenExecutionResult result = new DefaultMavenExecutionResult();
+
+ // populate sensible defaults, including repository basedir and remote repos
+ MavenExecutionRequestPopulator populator;
+ populator = getContainer().lookup( MavenExecutionRequestPopulator.class );
+ populator.populateDefaults( request );
+
+ // this is needed to allow java profiles to get resolved; i.e. avoid during project builds:
+ // [ERROR] Failed to determine Java version for profile java-1.5-detected @ org.apache.commons:commons-parent:22, /Users/alex/.m2/repository/org/apache/commons/commons-parent/22/commons-parent-22.pom, line 909, column 14
+ request.setSystemProperties( System.getProperties() );
+
+ // and this is needed so that the repo session in the maven session
+ // has a repo manager, and it points at the local repo
+ // (cf MavenRepositorySystemUtils.newSession() which is what is otherwise done)
+ DefaultMaven maven = (DefaultMaven) getContainer().lookup( Maven.class );
+ DefaultRepositorySystemSession repoSession =
+ (DefaultRepositorySystemSession) maven.newRepositorySession( request );
+ repoSession.setLocalRepositoryManager(
+ new SimpleLocalRepositoryManagerFactory().newInstance(repoSession,
+ new LocalRepository( request.getLocalRepository().getBasedir() ) ));
+
+ MavenSession session = new MavenSession( getContainer(),
+ repoSession,
+ request, result );
+ return session;
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /** Extends the super to use the new {@link #newMavenSession()} introduced here
+ * which sets the defaults one expects from maven; the standard test case leaves a lot of things blank */
+ @Override
+ protected MavenSession newMavenSession(MavenProject project) {
+ MavenSession session = newMavenSession();
+ session.setCurrentProject( project );
+ session.setProjects( Arrays.asList( project ) );
+ return session;
+ }
+
+ /** As {@link #lookupConfiguredMojo(MavenProject, String)} but taking the pom file
+ * and creating the {@link MavenProject}. */
+ protected Mojo lookupConfiguredMojo(File pom, String goal) throws Exception {
+ assertNotNull( pom );
+ assertTrue( pom.exists() );
+
+ ProjectBuildingRequest buildingRequest = newMavenSession().getProjectBuildingRequest();
+ ProjectBuilder projectBuilder = lookup(ProjectBuilder.class);
+ MavenProject project = projectBuilder.build(pom, buildingRequest).getProject();
+
+ return lookupConfiguredMojo(project, goal);
+ }
+
+
+}
diff --git a/apache-rat-plugin/src/test/java/org/apache/rat/mp/RatCheckMojoTest.java b/apache-rat-plugin/src/test/java/org/apache/rat/mp/RatCheckMojoTest.java
index b12e114b0..b35982bb3 100644
--- a/apache-rat-plugin/src/test/java/org/apache/rat/mp/RatCheckMojoTest.java
+++ b/apache-rat-plugin/src/test/java/org/apache/rat/mp/RatCheckMojoTest.java
@@ -1,5 +1,3 @@
-package org.apache.rat.mp;
-
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
@@ -16,36 +14,32 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package org.apache.rat.mp;
-import org.apache.commons.io.IOUtils;
-import org.apache.maven.model.Build;
-import org.apache.maven.plugin.testing.AbstractMojoTestCase;
-import org.apache.maven.plugin.testing.stubs.MavenProjectStub;
-import org.apache.rat.config.AddLicenseHeaders;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.nio.charset.StandardCharsets;
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import org.junit.Assume;
-
+import static java.nio.charset.StandardCharsets.UTF_8;
import static org.apache.rat.mp.RatTestHelpers.ensureRatReportIsCorrect;
import static org.apache.rat.mp.RatTestHelpers.getSourceDirectory;
import static org.apache.rat.mp.RatTestHelpers.newArtifactFactory;
import static org.apache.rat.mp.RatTestHelpers.newArtifactRepository;
-import static org.apache.rat.mp.RatTestHelpers.newArtifactResolver;
import static org.apache.rat.mp.RatTestHelpers.newSiteRenderer;
-import org.w3c.dom.Document;
-import org.w3c.dom.NodeList;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.io.File;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.rat.ReportConfiguration;
+import org.apache.rat.ReportConfigurationTest;
+import org.apache.rat.license.ILicenseFamily;
+import org.apache.rat.license.LicenseFamilySetFactory;
+import org.apache.rat.license.LicenseSetFactory;
+import org.apache.rat.license.LicenseSetFactory.LicenseFilter;
+import org.apache.rat.testhelpers.TextUtils;
+import org.apache.rat.walker.NameBasedHiddenFileFilter;
/**
* Test case for the {@link RatCheckMojo} and {@link RatReportMojo}.
*/
-public class RatCheckMojoTest extends AbstractMojoTestCase {
+public class RatCheckMojoTest extends BetterAbstractMojoTestCase {
/**
* Creates a new instance of {@link RatCheckMojo}.
@@ -61,57 +55,31 @@ private RatCheckMojo newRatCheckMojo(String pDir) throws Exception {
/**
* Creates a new instance of {@link AbstractRatMojo}.
*
- * @param pDir The directory, where to look for a pom.xml file.
+ * @param pDir The directory, where to look for a pom.xml file.
* @param pGoal The goal, which the Mojo must implement.
+ * @param pCreateCopy if {@code true} copy the directory contents and return the
+ * copy location.
* @return The configured Mojo.
* @throws Exception An error occurred while creating the Mojo.
*/
- private AbstractRatMojo newRatMojo(String pDir, String pGoal,
- boolean pCreateCopy) throws Exception {
+ private AbstractRatMojo newRatMojo(String pDir, String pGoal, boolean pCreateCopy) throws Exception {
final File baseDir = new File(getBasedir());
- final File testBaseDir = getSourceDirectory(getBasedir(), pDir,
- pCreateCopy, baseDir);
- File testPom = new File(testBaseDir, "pom.xml");
- AbstractRatMojo mojo = (AbstractRatMojo) lookupMojo(pGoal, testPom);
+ final File testBaseDir = getSourceDirectory(getBasedir(), pDir, pCreateCopy, baseDir);
+ final File testPom = new File(testBaseDir, "pom.xml");
+ final File buildDirectory = new File(new File(baseDir, "target/test"), pDir);
+ AbstractRatMojo mojo = (AbstractRatMojo) lookupConfiguredMojo(testPom, pGoal);
assertNotNull(mojo);
- final File buildDirectory = new File(new File(baseDir, "target/test"),
- pDir);
- setVariableValueToObject(mojo, "basedir", testBaseDir);
- setVariableValueToObject(mojo, "addDefaultLicenseMatchers",
- Boolean.TRUE);
- setVariableValueToObject(mojo, "useDefaultExcludes", Boolean.TRUE);
- setVariableValueToObject(mojo, "useMavenDefaultExcludes", Boolean.TRUE);
- setVariableValueToObject(mojo, "useEclipseDefaultExcludes",
- Boolean.TRUE);
- setVariableValueToObject(mojo, "addLicenseHeaders", AddLicenseHeaders.FALSE.name());
- final Build build = new Build();
- build.setDirectory(buildDirectory.getPath());
- final MavenProjectStub project = new MavenProjectStub() {
- @Override
- public Build getBuild() {
- return build;
- }
- };
- setVariableValueToObject(mojo, "project", project);
- assertNotNull(
- "Problem in test setup - you are missing a project in your mojo.",
- project);
- assertNotNull(
- "The mojo is missing its MavenProject, which will result in an NPE during rat runs.",
+
+ assertNotNull("The mojo is missing its MavenProject, which will result in an NPE during rat runs.",
mojo.getProject());
- assertNotNull(
- "No artifactRepos found, which will result in an NPE during rat runs.",
- project.getRemoteArtifactRepositories());
if (mojo instanceof RatReportMojo) {
- setVariableValueToObject(mojo, "localRepository",
- newArtifactRepository(container));
- setVariableValueToObject(mojo, "resolver", newArtifactResolver());
+ setVariableValueToObject(mojo, "localRepository", newArtifactRepository(getContainer()));
setVariableValueToObject(mojo, "factory", newArtifactFactory());
- setVariableValueToObject(mojo, "siteRenderer",
- newSiteRenderer(container));
+ setVariableValueToObject(mojo, "siteRenderer", newSiteRenderer(getContainer()));
} else if (mojo instanceof RatCheckMojo) {
final File ratTxtFile = new File(buildDirectory, "rat.txt");
+ FileUtils.write(ratTxtFile, "", UTF_8); // Ensure the output file exists and is empty (rerunning the test will append)
setVariableValueToObject(mojo, "reportFile", ratTxtFile);
}
return mojo;
@@ -128,16 +96,26 @@ private File getRatTxtFile(RatCheckMojo pMojo) throws Exception {
return (File) getVariableValueFromObject(pMojo, "reportFile");
}
+ private String getDir(RatCheckMojo mojo) {
+ return mojo.getProject().getBasedir().getAbsolutePath().replace("\\","/") + "/";
+ }
/**
* Runs a check, which should expose no problems.
*
* @throws Exception The test failed.
*/
public void testIt1() throws Exception {
+
final RatCheckMojo mojo = newRatCheckMojo("it1");
final File ratTxtFile = getRatTxtFile(mojo);
+ final String[] expected = { " AL +\\Q" + getDir(mojo) + "pom.xml\\E", "Notes: 0", "Binaries: 0", "Archives: 0",
+ "Standards: 1$", "Apache Licensed: 1$", "Generated Documents: 0", "^0 Unknown Licenses" };
+
+ ReportConfiguration config = mojo.getConfiguration();
+ ReportConfigurationTest.validateDefault(config);
+
mojo.execute();
- ensureRatReportIsCorrect(ratTxtFile, 1, 0);
+ ensureRatReportIsCorrect(ratTxtFile, expected, TextUtils.EMPTY);
}
/**
@@ -146,39 +124,22 @@ public void testIt1() throws Exception {
* @throws Exception The test failed.
*/
public void testIt2() throws Exception {
+
final RatCheckMojo mojo = newRatCheckMojo("it2");
final File ratTxtFile = getRatTxtFile(mojo);
+ final String dir = getDir(mojo);
+ final String[] expected = { "^Files with unapproved licenses:\\s+\\Q" + dir + "src.txt\\E\\s+", "Notes: 0",
+ "Binaries: 0", "Archives: 0", "Standards: 2$", "Apache Licensed: 1$", "Generated Documents: 0",
+ "^1 Unknown Licenses", " AL +\\Q" + dir + "pom.xml\\E$", "\\Q!????? " + dir + "src.txt\\E$",
+ "^== File: \\Q" + dir + "src.txt\\E$" };
try {
mojo.execute();
fail("Expected RatCheckException");
} catch (RatCheckException e) {
final String msg = e.getMessage();
- // default value is "${project.build.directory}/rat.txt"
- final String REPORTFILE = "rat.txt";
-
- assertTrue("report filename was not contained in '" + msg + "'",
- msg.contains(REPORTFILE));
- assertFalse("no null allowed in '" + msg + "'", (msg.toUpperCase()
- .contains("NULL")));
- }
- ensureRatReportIsCorrect(ratTxtFile, 1, 1);
- }
-
- private String getFirstLine(File pFile) throws IOException {
- FileInputStream fis = null;
- InputStreamReader reader = null;
- BufferedReader breader = null;
- try {
- fis = new FileInputStream(pFile);
- reader = new InputStreamReader(fis, StandardCharsets.UTF_8);
- breader = new BufferedReader(reader);
- final String result = breader.readLine();
- breader.close();
- return result;
- } finally {
- IOUtils.closeQuietly(fis);
- IOUtils.closeQuietly(reader);
- IOUtils.closeQuietly(breader);
+ assertTrue("report filename was not contained in '" + msg + "'", msg.contains(ratTxtFile.getName()));
+ assertFalse("no null allowed in '" + msg + "'", (msg.toUpperCase().contains("NULL")));
+ ensureRatReportIsCorrect(ratTxtFile, expected, TextUtils.EMPTY);
}
}
@@ -186,70 +147,111 @@ private String getFirstLine(File pFile) throws IOException {
* Tests adding license headers.
*/
public void testIt3() throws Exception {
- final RatCheckMojo mojo = (RatCheckMojo) newRatMojo("it3", "check",
- true);
- setVariableValueToObject(mojo, "addLicenseHeaders", AddLicenseHeaders.TRUE.name());
- setVariableValueToObject(mojo, "numUnapprovedLicenses",
- 1);
- mojo.execute();
+ final RatCheckMojo mojo = (RatCheckMojo) newRatMojo("it3", "check", true);
final File ratTxtFile = getRatTxtFile(mojo);
- ensureRatReportIsCorrect(ratTxtFile, 1, 1);
+ final String dir = getDir(mojo);
+ final String[] expected = { "^Files with unapproved licenses:\\s+\\Q" + dir + "src.apt\\E\\s+", "Notes: 0",
+ "Binaries: 0", "Archives: 0", "Standards: 2$", "Apache Licensed: 1$", "Generated Documents: 0",
+ "^1 Unknown Licenses", " AL +\\Q" + dir + "pom.xml\\E$", "\\Q!????? " + dir + "src.apt\\E$",
+ "^== File: \\Q" + dir + "src.apt\\E$" };
- final File baseDir = new File(getBasedir());
- final File sourcesDir = new File(new File(baseDir, "target/it-source"),
- "it3");
- final String firstLineOrig = getFirstLine(new File(sourcesDir,
- "src.apt"));
- assertTrue(firstLineOrig.contains("--"));
- assertFalse(firstLineOrig.contains("~~"));
- final String firstLineModified = getFirstLine(new File(sourcesDir,
- "src.apt.new"));
- assertTrue(firstLineModified.contains("~~"));
- assertFalse(firstLineModified.contains("--"));
+ ReportConfiguration config = mojo.getConfiguration();
+ assertTrue("should be adding licenses", config.isAddingLicenses());
+
+ mojo.execute();
+
+ ensureRatReportIsCorrect(ratTxtFile, expected, TextUtils.EMPTY);
}
/**
- * Test correct generation of XML file if non-UTF8 file.encoding is set.
+ * Tests defining licenses in configuration
+ */
+ public void testIt5() throws Exception {
+ final RatCheckMojo mojo = (RatCheckMojo) newRatMojo("it5", "check", true);
+ final File ratTxtFile = getRatTxtFile(mojo);
+ final String[] expected = { "Notes: 0", "Binaries: 0", "Archives: 0", "Standards: 0$", "Apache Licensed: 0$",
+ "Generated Documents: 0", "^0 Unknown Licenses" };
+
+ ReportConfiguration config = mojo.getConfiguration();
+ assertFalse("Should not be adding licenses", config.isAddingLicenses());
+ assertFalse("Should not be forcing licenses", config.isAddingLicensesForced());
+ assertTrue("Should be styling report", config.isStyleReport());
+
+ ReportConfigurationTest.validateDefaultApprovedLicenses(config, 1);
+ assertTrue(config.getApprovedLicenseCategories().contains(ILicenseFamily.makeCategory("YAL")));
+ ReportConfigurationTest.validateDefaultLicenseFamilies(config, "YAL");
+ assertNotNull(LicenseFamilySetFactory.search("YAL", config.getLicenseFamilies(LicenseFilter.all)));
+ ReportConfigurationTest.validateDefaultLicenses(config, "MyLicense", "CpyrT", "RegxT", "SpdxT", "TextT",
+ "Not", "All", "Any");
+ assertNotNull(LicenseSetFactory.search("MyLicense", config.getLicenses(LicenseFilter.all)));
+ assertNull("Should not have inputFileFilter", config.getInputFileFilter());
+ mojo.execute();
+
+ ensureRatReportIsCorrect(ratTxtFile, expected, TextUtils.EMPTY);
+ }
+
+ /**
+ * Runs a check, which should expose no problems.
*
* @throws Exception The test failed.
*/
- public void testIt4() throws Exception {
- // In previous versions of the JDK, it used to be possible to
- // change the value of file.encoding at runtime. As of Java 16,
- // this is no longer possible. Instead, at this point, we check,
- // that file.encoding is actually ISO-8859-1. (Within Maven, this
- // is enforced by the configuration of the surefire plugin.) If not,
- // we skip this test.
- Assume.assumeTrue("Expected file.encoding=ISO-8859-1", "ISO-8859-1".equals(System.getProperty("file.encoding")));
- final RatCheckMojo mojo = newRatCheckMojo("it4");
+ public void testRAT_343() throws Exception {
+ final RatCheckMojo mojo = newRatCheckMojo("RAT-343");
final File ratTxtFile = getRatTxtFile(mojo);
+ // POM reports as BSD because it has the BSD string in and that gets found before AL match
+ final String[] expected = { " BSD +\\Q" + getDir(mojo) + "pom.xml\\E", "Notes: 0", "Binaries: 0", "Archives: 0",
+ "Standards: 1$", "Apache Licensed: 0$", "Generated Documents: 0", "^0 Unknown Licenses" };
+
+ ReportConfiguration config = mojo.getConfiguration();
+ // validate configuration
+ assertThat(config.isAddingLicenses()).isFalse();
+ assertThat(config.isAddingLicensesForced()).isFalse();
+ assertThat(config.getCopyrightMessage()).isNull();
+ assertThat(config.getInputFileFilter()).isNull();
+ assertThat(config.isStyleReport()).isTrue();
+ assertThat(config.getStyleSheet()).isNotNull().withFailMessage("Stylesheet should not be null");
+ assertThat(config.getDirectoryFilter()).isNotNull().withFailMessage("Directory filter should not be null");
+ assertThat(config.getDirectoryFilter()).isExactlyInstanceOf(NameBasedHiddenFileFilter.class);
+
+ ReportConfigurationTest.validateDefaultApprovedLicenses(config, 1);
+ ReportConfigurationTest.validateDefaultLicenseFamilies(config, "BSD", "CC BY");
+ ReportConfigurationTest.validateDefaultLicenses(config, "BSD", "CC BY");
+
+ mojo.execute();
+ ensureRatReportIsCorrect(ratTxtFile, expected, TextUtils.EMPTY);
+ }
+
+ /**
+ * Tests verifying gitignore parsing
+ */
+ public void testRAT335GitIgnore() throws Exception {
+ final RatCheckMojo mojo = newRatCheckMojo("RAT-335-GitIgnore");
+ final File ratTxtFile = getRatTxtFile(mojo);
+ final String dir = getDir(mojo);
+ final String[] expected = {
+ "Notes: 1",
+ "Binaries: 0",
+ "Archives: 0",
+ "Standards: 5$",
+ "Apache Licensed: 2$",
+ "Generated Documents: 0",
+ "^3 Unknown Licenses",
+ " AL +\\Q" + dir + "pom.xml\\E$",
+ "\\Q!????? " + dir + "dir1/dir1.md\\E$",
+ "\\Q!????? " + dir + "dir2/dir2.txt\\E$",
+ "\\Q!????? " + dir + "dir3/file3.log\\E$",
+ "^== File: \\Q" + dir + "dir1/dir1.md\\E$",
+ "^== File: \\Q" + dir + "dir2/dir2.txt\\E$",
+ "^== File: \\Q" + dir + "dir3/file3.log\\E$"
+ };
try {
- setVariableValueToObject(mojo, "reportStyle", "xml");
mojo.execute();
fail("Expected RatCheckException");
} catch (RatCheckException e) {
final String msg = e.getMessage();
- // default value is "${project.build.directory}/rat.txt"
- final String REPORTFILE = "rat.txt";
-
- assertTrue("report filename was not contained in '" + msg + "'",
- msg.contains(REPORTFILE));
- assertFalse("no null allowed in '" + msg + "'", (msg.toUpperCase()
- .contains("NULL")));
- }
- assertTrue(ratTxtFile.exists());
- DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
- try (FileInputStream fis = new FileInputStream(ratTxtFile)) {
- Document doc = db.parse(fis);
- NodeList headerSample = doc.getElementsByTagName("header-sample");
- String textContent = headerSample.item(0).getTextContent();
- if (textContent.length() == 0) { // can be the pom since this test will parse 2 files but the pom is "ok"
- textContent = headerSample.item(1).getTextContent();
- }
- boolean byteSequencePresent = textContent.contains("\u00E4\u00F6\u00FC\u00C4\u00D6\u00DC\u00DF");
- assertTrue("Report should contain test umlauts, got '" + textContent + "'", byteSequencePresent);
- } catch (Exception ex) {
- fail("Report file could not be parsed as XML: " + ex.getMessage());
+ assertTrue("report filename was not contained in '" + msg + "'", msg.contains(ratTxtFile.getName()));
+ assertFalse("no null allowed in '" + msg + "'", (msg.toUpperCase().contains("NULL")));
+ ensureRatReportIsCorrect(ratTxtFile, expected, TextUtils.EMPTY);
}
}
}
diff --git a/apache-rat-plugin/src/test/java/org/apache/rat/mp/RatTestHelpers.java b/apache-rat-plugin/src/test/java/org/apache/rat/mp/RatTestHelpers.java
index 5467f6e19..e12bafa53 100644
--- a/apache-rat-plugin/src/test/java/org/apache/rat/mp/RatTestHelpers.java
+++ b/apache-rat-plugin/src/test/java/org/apache/rat/mp/RatTestHelpers.java
@@ -1,5 +1,17 @@
package org.apache.rat.mp;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.List;
+
+import org.apache.commons.io.FileUtils;
+
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
@@ -21,26 +33,17 @@
import org.apache.maven.artifact.factory.ArtifactFactory;
import org.apache.maven.artifact.factory.DefaultArtifactFactory;
import org.apache.maven.artifact.repository.ArtifactRepository;
-import org.apache.maven.artifact.repository.DefaultArtifactRepository;
+import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy;
+import org.apache.maven.artifact.repository.MavenArtifactRepository;
import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout;
-import org.apache.maven.artifact.resolver.ArtifactResolver;
-import org.apache.maven.artifact.resolver.DefaultArtifactResolver;
import org.apache.maven.doxia.siterenderer.Renderer;
import org.apache.maven.settings.Settings;
import org.apache.maven.settings.io.xpp3.SettingsXpp3Reader;
+import org.apache.rat.testhelpers.TextUtils;
import org.codehaus.plexus.PlexusContainer;
import org.codehaus.plexus.util.DirectoryScanner;
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.FileReader;
-import java.io.IOException;
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
+import com.google.common.base.Charsets;
/**
* Test helpers used when verifying mojo interaction in RAT integration tests.
@@ -57,23 +60,15 @@ public static void remove(File pDir) throws IOException {
throw new IOException("Unable to delete file: " + pDir);
}
} else if (pDir.isDirectory()) {
- final File[] files = pDir.listFiles();
- if (files != null) {
- for (File file : files) {
- remove(file);
- }
- }
- if (!pDir.delete()) {
- throw new IOException("Unable to delete directory: " + pDir);
- }
+ FileUtils.deleteDirectory(pDir);
} else if (pDir.exists()) {
throw new IOException("Unable to delete unknown object " + pDir);
}
}
/**
- * Copies the given files recursively in order to get all integration test
- * files into a target directory.
+ * Copies the given files recursively in order to get all integration test files
+ * into a target directory.
*
* @param pSource source files.
* @param pTarget target directory
@@ -87,7 +82,7 @@ public static void copy(File pSource, File pTarget) throws IOException {
final DirectoryScanner scanner = new DirectoryScanner();
scanner.setBasedir(pSource);
scanner.addDefaultExcludes();
- scanner.setIncludes(new String[]{"*"});
+ scanner.setIncludes(new String[] { "*" });
scanner.scan();
final String[] dirs = scanner.getIncludedDirectories();
@@ -101,20 +96,19 @@ public static void copy(File pSource, File pTarget) throws IOException {
copy(new File(pSource, file), new File(pTarget, file));
}
} else if (pSource.isFile()) {
- final FileInputStream fis = new FileInputStream(pSource);
- final FileOutputStream fos = new FileOutputStream(pTarget);
- final byte[] buffer = new byte[8192];
- for (; ; ) {
- int res = fis.read(buffer);
- if (res == -1) {
- break;
- }
- if (res > 0) {
- fos.write(buffer, 0, res);
+ try (final FileInputStream fis = new FileInputStream(pSource);
+ final FileOutputStream fos = new FileOutputStream(pTarget);) {
+ final byte[] buffer = new byte[8192];
+ for (;;) {
+ int res = fis.read(buffer);
+ if (res == -1) {
+ break;
+ }
+ if (res > 0) {
+ fos.write(buffer, 0, res);
+ }
}
}
- fos.close();
- fis.close();
} else {
throw new IOException("Unable to copy unknown object " + pSource);
}
@@ -127,8 +121,7 @@ public static void copy(File pSource, File pTarget) throws IOException {
* @return A configured instance of a Default renderer.
* @throws Exception Creating the object failed.
*/
- public static Renderer newSiteRenderer(PlexusContainer container)
- throws Exception {
+ public static Renderer newSiteRenderer(PlexusContainer container) throws Exception {
return (Renderer) container.lookup(Renderer.ROLE, "default");
}
@@ -140,51 +133,29 @@ public static Renderer newSiteRenderer(PlexusContainer container)
*/
public static ArtifactFactory newArtifactFactory() throws Exception {
final InvocationHandler handler = new InvocationHandler() {
- public Object invoke(Object pProxy, Method pMethod, Object[] pArgs)
- throws Throwable {
- System.out.println("Invoking method " + pMethod);
- throw new IllegalStateException("Not implemented");
- }
- };
- return (ArtifactFactory) Proxy.newProxyInstance(Thread.currentThread()
- .getContextClassLoader(),
- new Class[]{ArtifactFactory.class}, handler);
- }
-
- /**
- * Creates a new instance of {@link ArtifactResolver}.
- *
- * @return A configured instance of {@link DefaultArtifactResolver}.
- * @throws Exception Creating the object failed.
- */
- public static ArtifactResolver newArtifactResolver() throws Exception {
- final InvocationHandler handler = new InvocationHandler() {
- public Object invoke(Object pProxy, Method pMethod, Object[] pArgs)
- throws Throwable {
+ @Override
+ public Object invoke(Object pProxy, Method pMethod, Object[] pArgs) throws Throwable {
System.out.println("Invoking method " + pMethod);
throw new IllegalStateException("Not implemented");
}
};
- return (ArtifactResolver) Proxy.newProxyInstance(Thread.currentThread()
- .getContextClassLoader(),
- new Class[]{ArtifactResolver.class}, handler);
+ return (ArtifactFactory) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
+ new Class[] { ArtifactFactory.class }, handler);
}
/**
* Creates an instance of {@link ArtifactRepository}.
*
* @param container current plexus container.
- * @return A configured instance of {@link DefaultArtifactRepository}.
+ * @return A configured instance of {@link MavenArtifactRepository}.
* @throws Exception Creating the object failed.
*/
- public static ArtifactRepository newArtifactRepository(
- PlexusContainer container) throws Exception {
+ public static ArtifactRepository newArtifactRepository(PlexusContainer container) throws Exception {
File m2Dir = new File(System.getProperty("user.home"), ".m2");
File settingsFile = new File(m2Dir, "settings.xml");
String localRepo = null;
if (settingsFile.exists()) {
- Settings settings = new SettingsXpp3Reader().read(new FileReader(
- settingsFile));
+ Settings settings = new SettingsXpp3Reader().read(new FileReader(settingsFile));
localRepo = settings.getLocalRepository();
}
if (localRepo == null) {
@@ -192,84 +163,49 @@ public static ArtifactRepository newArtifactRepository(
}
ArtifactRepositoryLayout repositoryLayout = (ArtifactRepositoryLayout) container
.lookup(ArtifactRepositoryLayout.ROLE, "default");
- return new DefaultArtifactRepository("local", "file://" + localRepo,
- repositoryLayout);
+ return new MavenArtifactRepository("local", "file://" + localRepo, repositoryLayout,
+ new ArtifactRepositoryPolicy(), new ArtifactRepositoryPolicy());
}
- public static File makeSourceDirectory(String mvnBaseDir, File pFile,
- String pDir, boolean pCreateCopy) throws IOException {
+ public static File makeSourceDirectory(String mvnBaseDir, File pFile, String pDir, boolean pCreateCopy)
+ throws IOException {
if (!pCreateCopy) {
return pFile;
}
- final File targetDir = new File(new File(new File(mvnBaseDir),
- "target/it-source"), pDir);
+ final File targetDir = new File(new File(new File(mvnBaseDir), "target/it-source"), pDir);
remove(targetDir);
copy(pFile, targetDir);
return targetDir;
}
- public static File getSourceDirectory(String mvnBaseDir, String pDir,
- boolean pCreateCopy, final File baseDir) throws IOException {
- return makeSourceDirectory(mvnBaseDir, new File(new File(baseDir,
- "src/test/resources/unit"), pDir), pDir, pCreateCopy);
+ public static File getSourceDirectory(String mvnBaseDir, String pDir, boolean pCreateCopy, final File baseDir)
+ throws IOException {
+ return makeSourceDirectory(mvnBaseDir, new File(new File(baseDir, "src/test/resources/unit"), pDir), pDir,
+ pCreateCopy);
}
/**
- * Reads the created report file and verifies, whether the detected numbers
- * are matching.
+ * Reads the created report file and verifies, whether the detected numbers are
+ * matching.
*
- * @param pRatTxtFile The file to read.
- * @param pNumALFiles The number of files with AL.
- * @param pNumNoLicenseFiles The number of files without license.
- * @throws IOException An error occurred while reading the file or the file does not
- * exist at all.
- * @throws IllegalArgumentException In case of mismatches in file numbers passed in as parameter.
+ * @param pRatTxtFile The file to read.
+ * @param in An array of regex expressions that must be in the file.
+ * @param notIn An array of regex expressions that must NOT be in the file.
+ * @throws IOException An error occurred while reading the file or the file does
+ * not exist at all.
+ * @throws IllegalArgumentException In case of mismatches in file numbers passed
+ * in as parameter.
*/
- public static void ensureRatReportIsCorrect(File pRatTxtFile,
- int pNumALFiles, int pNumNoLicenseFiles) throws IOException {
- if (!pRatTxtFile.exists()) {
- throw new FileNotFoundException("Could not find " + pRatTxtFile);
+ public static void ensureRatReportIsCorrect(File pRatTxtFile, String[] in, String[] notIn) throws IOException {
+ List lines = IOUtils.readLines(new FileInputStream(pRatTxtFile), Charsets.UTF_8);
+ String document = String.join("\n", lines);
+ for (String pattern : in) {
+ TextUtils.assertPatternInOutput(pattern, document);
}
- BufferedReader reader = null;
- try {
-
- reader = new BufferedReader(new FileReader(pRatTxtFile));
- Integer numALFiles = null;
- Integer numNoLicenseFiles = null;
- for (; ; ) {
- String line = reader.readLine();
- if (line == null) {
- break;
- }
- int offset = line.indexOf("Apache Licensed: ");
- if (offset >= 0) {
- numALFiles = Integer.valueOf(line.substring(
- offset + "Apache Licensed: ".length()).trim());
- }
- offset = line.indexOf("Unknown Licenses");
- if (offset >= 0) {
- numNoLicenseFiles = Integer.valueOf(line.substring(0, offset)
- .trim());
- }
- }
- reader.close();
- if (!Integer.valueOf(pNumALFiles).equals(numALFiles)) {
- throw new IllegalArgumentException(
- "Amount of licensed files does not match. Expected "
- + pNumALFiles + ", got " + numALFiles);
- }
-
- if (!Integer.valueOf(pNumNoLicenseFiles).equals(numNoLicenseFiles)) {
- throw new IllegalArgumentException(
- "Amount of licensed files does not match. Expected "
- + pNumALFiles + ", got " + numALFiles);
- }
- } finally {
- IOUtils.closeQuietly(reader);
+ for (String pattern : notIn) {
+ TextUtils.assertPatternInOutput(pattern, document);
}
-
}
-
}
diff --git a/apache-rat-plugin/src/test/java/org/apache/rat/mp/util/ExclusionHelperTest.java b/apache-rat-plugin/src/test/java/org/apache/rat/mp/util/ExclusionHelperTest.java
index e1fd9c5d0..c6dcb46d4 100644
--- a/apache-rat-plugin/src/test/java/org/apache/rat/mp/util/ExclusionHelperTest.java
+++ b/apache-rat-plugin/src/test/java/org/apache/rat/mp/util/ExclusionHelperTest.java
@@ -1,5 +1,18 @@
package org.apache.rat.mp.util;
+import static org.apache.rat.mp.util.ExclusionHelper.ECLIPSE_DEFAULT_EXCLUDES;
+import static org.apache.rat.mp.util.ExclusionHelper.IDEA_DEFAULT_EXCLUDES;
+import static org.apache.rat.mp.util.ExclusionHelper.MAVEN_DEFAULT_EXCLUDES;
+import static org.apache.rat.mp.util.ExclusionHelper.addEclipseDefaults;
+import static org.apache.rat.mp.util.ExclusionHelper.addIdeaDefaults;
+import static org.apache.rat.mp.util.ExclusionHelper.addMavenDefaults;
+import static org.apache.rat.mp.util.ExclusionHelper.addPlexusAndScmDefaults;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.HashSet;
+import java.util.Set;
+
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
@@ -19,71 +32,56 @@
import org.apache.maven.plugin.logging.Log;
import org.apache.rat.config.SourceCodeManagementSystems;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.junit.MockitoJUnitRunner;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
-import java.util.HashSet;
-import java.util.Set;
-
-import static org.apache.rat.mp.util.ExclusionHelper.ECLIPSE_DEFAULT_EXCLUDES;
-import static org.apache.rat.mp.util.ExclusionHelper.IDEA_DEFAULT_EXCLUDES;
-import static org.apache.rat.mp.util.ExclusionHelper.MAVEN_DEFAULT_EXCLUDES;
-import static org.apache.rat.mp.util.ExclusionHelper.addEclipseDefaults;
-import static org.apache.rat.mp.util.ExclusionHelper.addIdeaDefaults;
-import static org.apache.rat.mp.util.ExclusionHelper.addMavenDefaults;
-import static org.apache.rat.mp.util.ExclusionHelper.addPlexusAndScmDefaults;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-@RunWith(MockitoJUnitRunner.class)
public class ExclusionHelperTest {
- @Mock
- private Log log;
+
+ private Log log = Mockito.mock(Log.class);
@Test
public void testNumberOfExclusions() {
- assertEquals("Did you change the number of eclipse excludes?", 5,
- ECLIPSE_DEFAULT_EXCLUDES.size());
- assertEquals("Did you change the number of idea excludes?", 4,
- IDEA_DEFAULT_EXCLUDES.size());
- assertEquals("Did you change the number of mvn excludes?", 7,
- MAVEN_DEFAULT_EXCLUDES.size());
+ assertEquals(5,
+ ECLIPSE_DEFAULT_EXCLUDES.size(),"Did you change the number of eclipse excludes?");
+ assertEquals(4,
+ IDEA_DEFAULT_EXCLUDES.size(), "Did you change the number of idea excludes?");
+ assertEquals(8,
+ MAVEN_DEFAULT_EXCLUDES.size(), "Did you change the number of mvn excludes?");
}
@Test
public void testAddingEclipseExclusions() {
final Set exclusion = new HashSet<>();
- addEclipseDefaults(log, false, exclusion);
+ exclusion.addAll(addEclipseDefaults(log, false));
assertTrue(exclusion.isEmpty());
- addEclipseDefaults(log, true, exclusion);
+ exclusion.addAll(addEclipseDefaults(log, true));
assertEquals(5, exclusion.size());
- addEclipseDefaults(log, true, exclusion);
+ exclusion.addAll(addEclipseDefaults(log, true));
assertEquals(5, exclusion.size());
}
@Test
public void testAddingIdeaExclusions() {
final Set exclusion = new HashSet<>();
- addIdeaDefaults(log, false, exclusion);
+ exclusion.addAll(addIdeaDefaults(log, false));
assertTrue(exclusion.isEmpty());
- addIdeaDefaults(log, true, exclusion);
+ exclusion.addAll(addIdeaDefaults(log, true));
assertEquals(4, exclusion.size());
- addIdeaDefaults(log, true, exclusion);
+ exclusion.addAll(addIdeaDefaults(log, true));
assertEquals(4, exclusion.size());
}
@Test
public void testAddingMavenExclusions() {
final Set exclusion = new HashSet<>();
- addMavenDefaults(log, false, exclusion);
+ exclusion.addAll(addMavenDefaults(log, false));
assertTrue(exclusion.isEmpty());
- addMavenDefaults(log, true, exclusion);
- assertEquals(7, exclusion.size());
- addMavenDefaults(log, true, exclusion);
- assertEquals(7, exclusion.size());
+ exclusion.addAll(addMavenDefaults(log, true));
+ assertEquals(8, exclusion.size());
+ exclusion.addAll(addMavenDefaults(log, true));
+ assertEquals(8, exclusion.size());
}
@Test
@@ -91,18 +89,19 @@ public void testAddingPlexusAndScmExclusion() {
final int expectedSizeMergedFromPlexusDefaultsAndScm = (37 + SourceCodeManagementSystems.getPluginExclusions().size());
final Set exclusion = new HashSet<>();
- addPlexusAndScmDefaults(log, false, exclusion);
+ exclusion.addAll(addPlexusAndScmDefaults(log, false));
assertTrue(exclusion.isEmpty());
- addPlexusAndScmDefaults(log, true, exclusion);
+ exclusion.addAll(addPlexusAndScmDefaults(log, true));
assertEquals(
- "Did you upgrade plexus to get more default excludes?",//
expectedSizeMergedFromPlexusDefaultsAndScm,//
- exclusion.size());
- addPlexusAndScmDefaults(log, true, exclusion);
+ exclusion.size(), //
+ "Did you upgrade plexus to get more default excludes?");
+ exclusion.addAll(addPlexusAndScmDefaults(log, true));
assertEquals(
- "Did you upgrade plexus to get more default excludes?",//
expectedSizeMergedFromPlexusDefaultsAndScm,//
- exclusion.size());
+ exclusion.size(), //
+ "Did you upgrade plexus to get more default excludes?"
+ );
}
}
diff --git a/apache-rat-plugin/src/test/java/org/apache/rat/mp/util/ScmIgnoreParserTest.java b/apache-rat-plugin/src/test/java/org/apache/rat/mp/util/ScmIgnoreParserTest.java
index 67846108e..59f14f0f0 100644
--- a/apache-rat-plugin/src/test/java/org/apache/rat/mp/util/ScmIgnoreParserTest.java
+++ b/apache-rat-plugin/src/test/java/org/apache/rat/mp/util/ScmIgnoreParserTest.java
@@ -16,35 +16,32 @@
* limitations under the License.
*/
-import org.apache.commons.io.IOUtils;
-import org.apache.maven.plugin.logging.Log;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.junit.MockitoJUnitRunner;
+import static org.apache.rat.mp.util.ScmIgnoreParser.getExclusionsFromSCM;
+import static org.apache.rat.mp.util.ignore.GlobIgnoreMatcher.isComment;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
+import java.nio.file.Files;
import java.util.List;
-import static org.apache.rat.mp.util.ScmIgnoreParser.getExcludesFromFile;
-import static org.apache.rat.mp.util.ScmIgnoreParser.getExclusionsFromSCM;
-import static org.apache.rat.mp.util.ScmIgnoreParser.isComment;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
+import org.apache.commons.io.IOUtils;
+import org.apache.maven.plugin.logging.Log;
+import org.apache.rat.mp.util.ignore.GlobIgnoreMatcher;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+import org.mockito.Mockito;
-@RunWith(MockitoJUnitRunner.class)
public class ScmIgnoreParserTest {
- @Rule
- public final TemporaryFolder testFolder = new TemporaryFolder();
-
- @Mock
- private Log log;
+
+ @TempDir
+ private File tempDir;
+
+ private Log log = Mockito.mock(Log.class);
private static final String IGNORE_EXAMPLE = "**/*.java\r\n## Justus commentos\r\nignoredDirectory";
@@ -67,6 +64,9 @@ public void parseAsComments() {
assertTrue(isComment(" /* comment that is */ "));
}
+ public List getExcludesFromFile(final Log log, final File scmIgnore) {
+ return new GlobIgnoreMatcher(log, scmIgnore).getExclusionLines();
+ }
@Test
public void parseFromNonExistingFileOrDirectoryOrNull() {
@@ -77,18 +77,20 @@ public void parseFromNonExistingFileOrDirectoryOrNull() {
@Test
public void parseFromTargetDirectoryHopefullyWithoutSCMIgnores() {
- assertTrue(getExclusionsFromSCM(log, new File("./target")).isEmpty());
+ // The target directory contains ignore files from other tests
+ assertTrue(getExclusionsFromSCM(log, new File("./target/classes")).isEmpty());
}
@Test
public void parseFromEmptyIgnoreFile() throws IOException {
- File ignore = testFolder.newFile();
- assertTrue(ignore.exists());
- writeToFile(IGNORE_EXAMPLE, ignore);
+ File ignore = Files.createTempFile(tempDir.getName(), "sip").toFile();
+
+ assertTrue(ignore.exists());
+ writeToFile(IGNORE_EXAMPLE, ignore);
- final List excludes = getExcludesFromFile(log, ignore);
- assertFalse(excludes.isEmpty());
- assertEquals(2, excludes.size());
+ final List excludes = getExcludesFromFile(log, ignore);
+ assertFalse(excludes.isEmpty());
+ assertEquals(2, excludes.size());
}
private static void writeToFile(String contents, File file) throws IOException {
diff --git a/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/.gitignore b/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/.gitignore
new file mode 100644
index 000000000..8855fa805
--- /dev/null
+++ b/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/.gitignore
@@ -0,0 +1,7 @@
+*.md
+
+# This makes it ignore dir3/dir3.log and dir3/file3.log
+*.log
+
+# This makes it "unignore" dir3/file3.log
+!file*.log
diff --git a/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/README.txt b/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/README.txt
new file mode 100644
index 000000000..8681fb580
--- /dev/null
+++ b/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/README.txt
@@ -0,0 +1,12 @@
+Note the output when running in the real commandline version of git
+
+# Files that must be ignored (dropping the gitignore matches outside of this test tree)
+$ git check-ignore --no-index --verbose $(find . -type f|sort) | fgrep 'apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/'
+
+apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/dir1/.gitignore:2:!dir1.md ./dir1/dir1.md
+apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/dir1/.gitignore:1:*.txt ./dir1/dir1.txt
+apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/dir1/.gitignore:3:file1.log ./dir1/file1.log
+apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/.gitignore:1:*.md ./dir2/dir2.md
+apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/.gitignore:4:*.log ./dir3/dir3.log
+apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/.gitignore:7:!file*.log ./dir3/file3.log
+apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/.gitignore:1:*.md ./root.md
diff --git a/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/dir1/.gitignore b/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/dir1/.gitignore
new file mode 100644
index 000000000..26fd5c956
--- /dev/null
+++ b/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/dir1/.gitignore
@@ -0,0 +1,3 @@
+*.txt
+!dir1.md
+file1.log
\ No newline at end of file
diff --git a/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/dir1/dir1.md b/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/dir1/dir1.md
new file mode 100644
index 000000000..a31cbc897
--- /dev/null
+++ b/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/dir1/dir1.md
@@ -0,0 +1 @@
+File without a valid license
diff --git a/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/dir1/dir1.txt b/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/dir1/dir1.txt
new file mode 100644
index 000000000..a31cbc897
--- /dev/null
+++ b/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/dir1/dir1.txt
@@ -0,0 +1 @@
+File without a valid license
diff --git a/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/dir1/file1.log b/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/dir1/file1.log
new file mode 100644
index 000000000..a31cbc897
--- /dev/null
+++ b/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/dir1/file1.log
@@ -0,0 +1 @@
+File without a valid license
diff --git a/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/dir2/dir2.md b/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/dir2/dir2.md
new file mode 100644
index 000000000..a31cbc897
--- /dev/null
+++ b/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/dir2/dir2.md
@@ -0,0 +1 @@
+File without a valid license
diff --git a/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/dir2/dir2.txt b/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/dir2/dir2.txt
new file mode 100644
index 000000000..a31cbc897
--- /dev/null
+++ b/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/dir2/dir2.txt
@@ -0,0 +1 @@
+File without a valid license
diff --git a/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/dir3/dir3.log b/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/dir3/dir3.log
new file mode 100644
index 000000000..a31cbc897
--- /dev/null
+++ b/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/dir3/dir3.log
@@ -0,0 +1 @@
+File without a valid license
diff --git a/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/dir3/file3.log b/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/dir3/file3.log
new file mode 100644
index 000000000..a31cbc897
--- /dev/null
+++ b/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/dir3/file3.log
@@ -0,0 +1 @@
+File without a valid license
diff --git a/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/invoker.properties b/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/invoker.properties
new file mode 100644
index 000000000..6e8c3479e
--- /dev/null
+++ b/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/invoker.properties
@@ -0,0 +1,16 @@
+# 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.
+
+invoker.goals = clean apache-rat:check
diff --git a/apache-rat-api/pom.xml b/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/pom.xml
similarity index 51%
rename from apache-rat-api/pom.xml
rename to apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/pom.xml
index bdb30bf61..ac5104dfd 100644
--- a/apache-rat-api/pom.xml
+++ b/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/pom.xml
@@ -15,36 +15,29 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-
+
4.0.0
-
- org.apache.rat
- apache-rat-project
- 0.16-SNAPSHOT
-
- jar
-
- apache-rat-api
-
- Apache Creadur Rat::API
- Shared beans and services.
-
-
-
-
- junit
- junit
- test
-
-
- org.hamcrest
- hamcrest-library
- test
-
-
- org.mockito
- mockito-core
- test
-
-
+ org.apache.rat.test
+ RAT335
+ 1.0
+
+
+
+ org.apache.rat
+ apache-rat-plugin
+ @pom.version@
+
+
+
+ **/.gitignore
+
+ false
+ false
+ false
+ false
+ true
+
+
+
+
diff --git a/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/root.md b/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/root.md
new file mode 100644
index 000000000..a31cbc897
--- /dev/null
+++ b/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/root.md
@@ -0,0 +1 @@
+File without a valid license
diff --git a/apache-rat-plugin/src/test/resources/unit/RAT-343/pom.xml b/apache-rat-plugin/src/test/resources/unit/RAT-343/pom.xml
new file mode 100644
index 000000000..aa4b20c34
--- /dev/null
+++ b/apache-rat-plugin/src/test/resources/unit/RAT-343/pom.xml
@@ -0,0 +1,91 @@
+
+
+
+ 4.0.0
+ org.apache.rat.test
+ it2
+ 1.0
+
+
+
+ org.apache.rat
+ apache-rat-plugin
+ @pom.version@
+
+ true
+
+
+ MIT
+ MIT
+
+
+ Licensed MIT
+ Licensed under MIT
+ Licensed under the MIT license
+ MIT/GPL2 Licensed
+ licensed under the MIT and GPL
+ MIT license
+
+
+
+ BSD
+ BSD
+
+
+ BSD-style license
+
+
+
+ CC BY
+ Creative Commons Attribution
+
+
+ creativecommons.org/licenses/by/4.0
+
+
+
+
+
+ MIT
+
+
+ BSD
+
+
+ CC BY
+
+
+
+ BSD
+
+
+ **/*.mp3
+ **/localhost.jks
+ **/node_modules/**
+ **/package-lock.json
+ **/target/**
+ **/.project
+ **/.classpath
+ **/.settings/**
+ .gitattributes
+
+
+
+
+
+
diff --git a/apache-rat-plugin/src/test/resources/unit/it1/pom.xml b/apache-rat-plugin/src/test/resources/unit/it1/pom.xml
index 6c8e269cc..b6b71dc54 100644
--- a/apache-rat-plugin/src/test/resources/unit/it1/pom.xml
+++ b/apache-rat-plugin/src/test/resources/unit/it1/pom.xml
@@ -15,10 +15,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-
+
4.0.0
org.codehaus.mojo.rat.test
it1
diff --git a/apache-rat-plugin/src/test/resources/unit/it2/pom.xml b/apache-rat-plugin/src/test/resources/unit/it2/pom.xml
index d7aac5e34..bab0bea2f 100644
--- a/apache-rat-plugin/src/test/resources/unit/it2/pom.xml
+++ b/apache-rat-plugin/src/test/resources/unit/it2/pom.xml
@@ -15,10 +15,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-
+
4.0.0
org.apache.rat.test
it2
diff --git a/apache-rat-plugin/src/test/resources/unit/it3/pom.xml b/apache-rat-plugin/src/test/resources/unit/it3/pom.xml
index 8629f2876..f6982e399 100644
--- a/apache-rat-plugin/src/test/resources/unit/it3/pom.xml
+++ b/apache-rat-plugin/src/test/resources/unit/it3/pom.xml
@@ -15,10 +15,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-
+
4.0.0
org.apache.rat.test
it3
@@ -30,6 +27,8 @@
apache-rat-plugin
@pom.version@
+ 1
+ true
diff --git a/apache-rat-plugin/src/test/resources/unit/it4/pom.xml b/apache-rat-plugin/src/test/resources/unit/it4/pom.xml
index d24f14526..18145fdca 100644
--- a/apache-rat-plugin/src/test/resources/unit/it4/pom.xml
+++ b/apache-rat-plugin/src/test/resources/unit/it4/pom.xml
@@ -15,10 +15,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-
+
4.0.0
org.apache.rat.test
it4
diff --git a/apache-rat-plugin/src/test/resources/unit/it5/.bzrignore b/apache-rat-plugin/src/test/resources/unit/it5/.bzrignore
new file mode 100644
index 000000000..f59acc081
--- /dev/null
+++ b/apache-rat-plugin/src/test/resources/unit/it5/.bzrignore
@@ -0,0 +1,5 @@
+## RAT-171: Add rubbish and ensure that the plugin behaves properly
+DoesNotExistAtALL/**
+*\IllegalStuffNotExisting
+Lets-See*+?!OrWhat
+\\nDoesThatWorkAsWell\/
diff --git a/apache-rat-plugin/src/test/resources/unit/it5/pom.xml b/apache-rat-plugin/src/test/resources/unit/it5/pom.xml
new file mode 100644
index 000000000..ca62ab392
--- /dev/null
+++ b/apache-rat-plugin/src/test/resources/unit/it5/pom.xml
@@ -0,0 +1,114 @@
+
+
+
+ 4.0.0
+ org.codehaus.mojo.rat.test
+ it1
+ 1.0
+
+
+
+ org.apache.rat
+ apache-rat-plugin
+ @pom.version@
+
+
+
+ YAL
+ Yet another license
+
+
+
+ YAL
+
+
+
+ MyLicense
+ YAL
+ Yet Another License
+
+
+ GEN
+ CpyrT
+ Copyright with tags
+
+
+ 1990
+ 1991
+ foo
+
+
+
+ GEN
+ RegxT
+ Regex with tag
+
+ regex tag
+
+
+ GEN
+ SpdxT
+ Spdx with tag
+
+ spxd-tag
+
+
+ GEN
+ TextT
+ Text with tag
+
+ text-tag
+
+
+ GEN
+ Not
+ Not testing
+
+
+ not test text
+
+
+
+ GEN
+ All
+ All testing
+
+
+ all test text
+ all spdx text
+
+
+
+ GEN
+ Any
+ Any testing
+
+
+ any test text
+ any spdx text
+
+
+
+
+ src.apt
+
+
+
+
+
+
diff --git a/apache-rat-tasks/pom.xml b/apache-rat-tasks/pom.xml
index 84eb8b8ee..2777b270a 100644
--- a/apache-rat-tasks/pom.xml
+++ b/apache-rat-tasks/pom.xml
@@ -1,4 +1,4 @@
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
diff --git a/apache-rat-tasks/src/test/java/org/apache/rat/anttasks/AbstractRatAntTaskTest.java b/apache-rat-tasks/src/test/java/org/apache/rat/anttasks/AbstractRatAntTaskTest.java
index 3601240a1..1ac65c051 100644
--- a/apache-rat-tasks/src/test/java/org/apache/rat/anttasks/AbstractRatAntTaskTest.java
+++ b/apache-rat-tasks/src/test/java/org/apache/rat/anttasks/AbstractRatAntTaskTest.java
@@ -41,6 +41,8 @@ protected File getTempDir() {
@Before
public void setUp() {
buildRule.configureProject(getAntFile().getPath());
+ buildRule.getProject().setProperty("output.dir", tempDir.getAbsolutePath());
+ buildRule.getProject().setProperty("resource.dir", getAntFile().getParent());
}
protected void assertLogDoesNotMatch(String pPattern) {
diff --git a/apache-rat-tasks/src/test/java/org/apache/rat/anttasks/ReportTest.java b/apache-rat-tasks/src/test/java/org/apache/rat/anttasks/ReportTest.java
index ebed7f6c9..26a29838c 100644
--- a/apache-rat-tasks/src/test/java/org/apache/rat/anttasks/ReportTest.java
+++ b/apache-rat-tasks/src/test/java/org/apache/rat/anttasks/ReportTest.java
@@ -16,26 +16,35 @@
*/
package org.apache.rat.anttasks;
-import org.apache.commons.io.IOUtils;
-import org.apache.tools.ant.BuildException;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
-import java.lang.reflect.Field;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import java.util.Optional;
+
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
-import org.apache.rat.document.impl.guesser.BinaryGuesser;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.rat.ReportConfiguration;
+import org.apache.rat.ReportConfigurationTest;
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Target;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.UnknownElement;
import org.junit.Assume;
+import org.junit.Ignore;
import org.junit.Test;
import org.w3c.dom.Document;
-import static org.junit.Assert.*;
-
public class ReportTest extends AbstractRatAntTaskTest {
private static final File antFile = new File("src/test/resources/antunit/report-junit.xml").getAbsoluteFile();
@@ -53,10 +62,11 @@ public void testWithReportSentToAnt() throws Exception {
@Test
public void testWithReportSentToFile() throws Exception {
final File reportFile = new File(getTempDir(), "selftest.report");
+ final String alLine = "AL +\\Q" + getAntFileName() + "\\E";
+
if (!getTempDir().mkdirs() && !getTempDir().isDirectory()) {
throw new IOException("Could not create temporary directory " + getTempDir());
}
- final String alLine = "AL +\\Q" + getAntFileName() + "\\E";
if (reportFile.isFile() && !reportFile.delete()) {
throw new IOException("Unable to remove report file " + reportFile);
}
@@ -73,25 +83,74 @@ public void testWithALUnknown() throws Exception {
assertLogMatches("\\!\\?\\?\\?\\?\\? +\\Q" + getAntFileName() + "\\E");
}
+ @Test
+ public void testCustomLicense() throws Exception {
+ buildRule.executeTarget("testCustomLicense");
+ assertLogDoesNotMatch(" AS +\\Q" + getAntFileName() + "\\E");
+ assertLogMatches(" newFa +\\Q" + getAntFileName() + "\\E");
+ }
+
@Test
public void testCustomMatcher() throws Exception {
buildRule.executeTarget("testCustomMatcher");
- assertLogDoesNotMatch("AL +\\Q" + getAntFileName() + "\\E");
- assertLogMatches("EXMPL +\\Q" + getAntFileName() + "\\E");
+ assertLogDoesNotMatch(" AS +\\Q" + getAntFileName() + "\\E");
+ assertLogMatches(" YASL1 +\\Q" + getAntFileName() + "\\E");
+ }
+
+ @Test
+ public void testInlineCustomMatcher() throws Exception {
+ buildRule.executeTarget("testInlineCustomMatcher");
+ assertLogDoesNotMatch(" AS +\\Q" + getAntFileName() + "\\E");
+ assertLogMatches(" YASL1 +\\Q" + getAntFileName() + "\\E");
+ }
+
+ @Test
+ public void testCustomMatcherBuilder() throws Exception {
+ buildRule.executeTarget("testCustomMatcherBuilder");
+ assertLogDoesNotMatch(" AS +\\Q" + getAntFileName() + "\\E");
+ assertLogMatches(" YASL1 +\\Q" + getAntFileName() + "\\E");
}
@Test
public void testNoResources() throws Exception {
try {
buildRule.executeTarget("testNoResources");
- fail("Expected Exception");
+ fail("Expected Exceptoin");
+ } catch (BuildException e) {
+ final String expect = "You must specify at least one file";
+ assertTrue("Expected " + expect + ", got " + e.getMessage(), e.getMessage().contains(expect));
+ }
+ }
+
+ @Test
+ public void testCopyrightBuild() throws Exception {
+ try {
+ String fileName = new File(getAntFile().getParent(), "index.apt").getPath().replace('\\', '/');
+ buildRule.executeTarget("testCopyrightBuild");
+ assertLogMatches("YASL1 +\\Q" + fileName + "\\E");
+ assertLogDoesNotMatch("AL +\\Q" + fileName + "\\E");
} catch (BuildException e) {
final String expect = "You must specify at least one file";
- assertTrue("Expected " + expect + ", got " + e.getMessage(),
- e.getMessage().contains(expect));
+ assertTrue("Expected " + expect + ", got " + e.getMessage(), e.getMessage().contains(expect));
}
}
+ private Report getReport(String target) {
+ Target testDefault = buildRule.getProject().getTargets().get(target);
+ Optional optT = Arrays.stream(testDefault.getTasks()).filter(t -> t.getTaskName().equals("rat:report"))
+ .findFirst();
+ assertTrue(optT.isPresent());
+ optT.get().maybeConfigure();
+ return (Report) ((UnknownElement) optT.get()).getRealThing();
+ }
+
+ @Test
+ public void testDefault() {
+ Report report = getReport("testDefault");
+ ReportConfiguration config = report.getConfiguration();
+ ReportConfigurationTest.validateDefault(config);
+ }
+
@Test
public void testNoLicenseMatchers() throws Exception {
try {
@@ -99,8 +158,7 @@ public void testNoLicenseMatchers() throws Exception {
fail("Expected Exception");
} catch (BuildException e) {
final String expect = "at least one license";
- assertTrue("Expected " + expect + ", got " + e.getMessage(),
- e.getMessage().contains(expect));
+ assertTrue("Expected " + expect + ", got " + e.getMessage(), e.getMessage().contains(expect));
}
}
@@ -144,30 +202,35 @@ public void testAddLicenseHeaders() throws Exception {
* Test correct generation of string result if non-UTF8 file.encoding is set.
*/
@Test
+ @Ignore
public void testISO88591() throws Exception {
- // In previous versions of the JDK, it used to be possible to
- // change the value of file.encoding at runtime. As of Java 16,
- // this is no longer possible. Instead, at this point, we check,
- // that file.encoding is actually ISO-8859-1. (Within Maven, this
- // is enforced by the configuration of the surefire plugin.) If not,
- // we skip this test.
- Assume.assumeTrue("Expected file.encoding=ISO-8859-1", "ISO-8859-1".equals(System.getProperty("file.encoding")));
+ // In previous versions of the JDK, it used to be possible to
+ // change the value of file.encoding at runtime. As of Java 16,
+ // this is no longer possible. Instead, at this point, we check,
+ // that file.encoding is actually ISO-8859-1. (Within Maven, this
+ // is enforced by the configuration of the surefire plugin.) If not,
+ // we skip this test.
+ Assume.assumeTrue("Expected file.encoding=ISO-8859-1",
+ "ISO-8859-1".equals(System.getProperty("file.encoding")));
buildRule.executeTarget("testISO88591");
- assertTrue("Log should contain the test umlauts", buildRule.getLog().contains("\u00E4\u00F6\u00FC\u00C4\u00D6\u00DC\u00DF"));
+ assertTrue("Log should contain the test umlauts",
+ buildRule.getLog().contains("\u00E4\u00F6\u00FC\u00C4\u00D6\u00DC\u00DF"));
}
/**
* Test correct generation of XML file if non-UTF8 file.encoding is set.
*/
@Test
+ @Ignore
public void testISO88591WithFile() throws Exception {
- // In previous versions of the JDK, it used to be possible to
- // change the value of file.encoding at runtime. As of Java 16,
- // this is no longer possible. Instead, at this point, we check,
- // that file.encoding is actually ISO-8859-1. (Within Maven, this
- // is enforced by the configuration of the surefire plugin.) If not,
- // we skip this test.
- Assume.assumeTrue("Expected file.encoding=ISO-8859-1", "ISO-8859-1".equals(System.getProperty("file.encoding")));
+ // In previous versions of the JDK, it used to be possible to
+ // change the value of file.encoding at runtime. As of Java 16,
+ // this is no longer possible. Instead, at this point, we check,
+ // that file.encoding is actually ISO-8859-1. (Within Maven, this
+ // is enforced by the configuration of the surefire plugin.) If not,
+ // we skip this test.
+ Assume.assumeTrue("Expected file.encoding=ISO-8859-1",
+ "ISO-8859-1".equals(System.getProperty("file.encoding")));
Charset.defaultCharset();
String outputDir = System.getProperty("output.dir", "target/anttasks");
String selftestOutput = System.getProperty("report.file", outputDir + "/selftest.report");
@@ -176,9 +239,7 @@ public void testISO88591WithFile() throws Exception {
boolean documentParsed = false;
try (FileInputStream fis = new FileInputStream(selftestOutput)) {
Document doc = db.parse(fis);
- boolean byteSequencePresent = doc.getElementsByTagName("header-sample")
- .item(0)
- .getTextContent()
+ boolean byteSequencePresent = doc.getElementsByTagName("header-sample").item(0).getTextContent()
.contains("\u00E4\u00F6\u00FC\u00C4\u00D6\u00DC\u00DF");
assertTrue("Report should contain test umlauts", byteSequencePresent);
documentParsed = true;
diff --git a/apache-rat-tasks/src/test/java/org/example/Matcher.java b/apache-rat-tasks/src/test/java/org/example/Matcher.java
index bead7a78b..168f1e8f3 100644
--- a/apache-rat-tasks/src/test/java/org/example/Matcher.java
+++ b/apache-rat-tasks/src/test/java/org/example/Matcher.java
@@ -16,22 +16,16 @@
*/
package org.example;
-import org.apache.rat.analysis.IHeaderMatcher;
-import org.apache.rat.analysis.RatHeaderAnalysisException;
-import org.apache.rat.analysis.license.BaseLicense;
-import org.apache.rat.api.Document;
-import org.apache.rat.api.MetaData;
+import org.apache.rat.analysis.matchers.AbstractSimpleMatcher;
-
-public class Matcher extends BaseLicense implements IHeaderMatcher {
+public class Matcher extends AbstractSimpleMatcher {
public Matcher() {
- super(new MetaData.Datum(MetaData.RAT_URL_LICENSE_FAMILY_CATEGORY, "EXMPL"),
- new MetaData.Datum(MetaData.RAT_URL_LICENSE_FAMILY_NAME, "Example License"), "");
+ super("MyCustomMatcher");
}
- public void reset() {}
-
- public boolean match(Document subject, String line) throws RatHeaderAnalysisException {
- reportOnLicense(subject);
+
+ @Override
+ public boolean doMatch(String line) {
return true;
}
+
}
diff --git a/apache-rat-tasks/src/test/java/org/example/LicenseFamily.java b/apache-rat-tasks/src/test/java/org/example/MatcherBuilder.java
similarity index 78%
rename from apache-rat-tasks/src/test/java/org/example/LicenseFamily.java
rename to apache-rat-tasks/src/test/java/org/example/MatcherBuilder.java
index ef8527dc2..df5f55ca0 100644
--- a/apache-rat-tasks/src/test/java/org/example/LicenseFamily.java
+++ b/apache-rat-tasks/src/test/java/org/example/MatcherBuilder.java
@@ -16,11 +16,14 @@
*/
package org.example;
-import org.apache.rat.license.ILicenseFamily;
+import org.apache.rat.analysis.IHeaderMatcher;
+public class MatcherBuilder implements IHeaderMatcher.Builder {
+ public MatcherBuilder() {
+ }
-public class LicenseFamily implements ILicenseFamily {
- public String getFamilyName() {
- return "Example License";
+ @Override
+ public IHeaderMatcher build() {
+ return new Matcher();
}
}
diff --git a/apache-rat-tasks/src/test/resources/antunit/customLicense.xml b/apache-rat-tasks/src/test/resources/antunit/customLicense.xml
new file mode 100644
index 000000000..e7b4b0139
--- /dev/null
+++ b/apache-rat-tasks/src/test/resources/antunit/customLicense.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apache-rat-tasks/src/test/resources/antunit/index.apt b/apache-rat-tasks/src/test/resources/antunit/index.apt
index d4236b741..3cdabf12b 100644
--- a/apache-rat-tasks/src/test/resources/antunit/index.apt
+++ b/apache-rat-tasks/src/test/resources/antunit/index.apt
@@ -1,6 +1,10 @@
--------------
Some text file
--------------
+ Copyright 2023 - 2024, public domain.
+
+ The above statement is not a true copyright statement. It is here to test the Copyright pattern
+ matching.
Some text file
diff --git a/apache-rat-tasks/src/test/resources/antunit/report-bad-configurations.xml b/apache-rat-tasks/src/test/resources/antunit/report-bad-configurations.xml
index 7cf280556..1aee502d0 100644
--- a/apache-rat-tasks/src/test/resources/antunit/report-bad-configurations.xml
+++ b/apache-rat-tasks/src/test/resources/antunit/report-bad-configurations.xml
@@ -52,110 +52,81 @@
-
+
-
-
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
+
+ expectedMessage="License family YASL1 not found">
-
-
-
+ exmpl
+
-
+
+ expectedMessage="LicenseFamily Category must be specified">
-
-
-
+
+
-
+
+ expectedMessage="'regex' type matcher requires an expression">
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
+
+ expectedMessage="text value is required">
-
+
-
+
+
diff --git a/apache-rat-tasks/src/test/resources/antunit/report-junit.xml b/apache-rat-tasks/src/test/resources/antunit/report-junit.xml
index 54b0c9cad..76cefe572 100644
--- a/apache-rat-tasks/src/test/resources/antunit/report-junit.xml
+++ b/apache-rat-tasks/src/test/resources/antunit/report-junit.xml
@@ -21,89 +21,175 @@
-->
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ xmlns:au="antlib:org.apache.ant.antunit"
+ xmlns:rat="antlib:org.apache.rat.anttasks">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apache-rat-tasks/src/test/resources/antunit/report-normal-operation.xml b/apache-rat-tasks/src/test/resources/antunit/report-normal-operation.xml
index 88de39d91..fa7d1a1ec 100644
--- a/apache-rat-tasks/src/test/resources/antunit/report-normal-operation.xml
+++ b/apache-rat-tasks/src/test/resources/antunit/report-normal-operation.xml
@@ -18,325 +18,460 @@
specific language governing permissions and limitations *
under the License. *
+SPDX-License-Identifier: Apache-2.0
-->
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- License Family Name: Yet Another Software License (YASL) 1.0
-
-
-
-
-
-
-
-
-
-
- License Family Name: Yet Another Software License (YASL) 1.0
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-This text shouldn't exist in report-bad-configuration.xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- License Family Name: Yet Another Software License (YASL) ${test.version}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ the text
+
+
+
+
+
+
+
+
+
+
+
+
+ the text
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ regex\sregex
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Apache-2.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The text
+
+
+
+
+
+
+
+
+
+ License Family Name: Yet Another Software License
+ (YASL) 1.0
+
+
+
+
+
+
+
+
+
+
+
+
+ License Family Name: Yet Another Software License
+ (YASL) 1.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ name="Yet Another Software License (YASL)
+ ${test.version}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ output.dir is ${output.dir}
+
+
+
-
-
-
-
-
+
+
+
+
diff --git a/apache-rat-tools/pom.xml.new b/apache-rat-tools/pom.xml.new
new file mode 100644
index 000000000..73496c267
--- /dev/null
+++ b/apache-rat-tools/pom.xml.new
@@ -0,0 +1,104 @@
+
+
+
+ 4.0.0
+ org.apache.rat.test
+ it2
+ 1.0
+
+
+
+ org.apache.rat
+ apache-rat-plugin
+ @pom.version@
+
+ true
+
+ MIT
+
+
+
+
+ Licensed MIT
+ Licensed under MIT
+ Licensed under the MIT license
+ MIT/GPL2 Licensed
+ licensed under the MIT and GPL
+ MIT license
+
+
+ BSD
+
+
+
+
+
+BSD-style license
+
+ CC BY
+
+
+
+
+ creativecommons.org/licenses/by/4.0
+
+
+
+ MIT MIT
+ BSD BSD
+ CC BY CC BY
+
+
+
+ **/*.mp3
+ **/localhost.jks
+ **/node_modules/**
+ **/package-lock.json
+ **/target/**
+ **/.project
+ **/.classpath
+ **/.settings/**
+ .gitattributes
+
+
+
+
+
+
+
diff --git a/apache-rat/README-ANT.txt b/apache-rat/README-ANT.txt
index f47bd9798..658c7bc63 100644
--- a/apache-rat/README-ANT.txt
+++ b/apache-rat/README-ANT.txt
@@ -11,7 +11,6 @@ Requirements
------------
The Rat Ant Task Library requires Apache Ant 1.7.1 or higher (it works well with 1.8.x)
-It also requires at least Java 1.5.
Installation
------------
diff --git a/apache-rat/README-CLI.txt b/apache-rat/README-CLI.txt
index 0e629a8a8..225034e25 100644
--- a/apache-rat/README-CLI.txt
+++ b/apache-rat/README-CLI.txt
@@ -44,15 +44,17 @@ java -jar apache-rat-${project.version}.jar
Command Line Options
====================
-usage: java rat.report [options] [DIR|TARBALL]
-Options
- -A,--addLicense Add the default license header to any file
+usage: java -jar apache-rat/target/apache-rat-${project.version}.jar
+ [options] [DIR|TARBALL]
+
+Available options
+ -a,--addLicence 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.
- -a,--addlicense Add the default license header to any file
+ -A,--addLicense 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
@@ -63,19 +65,28 @@ Options
"Copyright 2008 Foo"
-d,--dir Used to indicate source when using
--exclude
- -E,--exclude-file Excludes files matching regular expression
- in Note that --dir is required when
- using this parameter.
-e,--exclude Excludes files matching wildcard
. Note that --dir is required
when using this parameter. Allows multiple
arguments.
+ -E,--exclude-file Excludes files matching regular expression
+ in Note that --dir is required when
+ using this parameter.
-f,--force Forces any changes in files to be written
directly to the source files (i.e. new
files are not created)
- -h,--help Print help for the Rat command line
+ -h,--help Print help for the RAT command line
interface and exit
+ --licenses File names or URLs for license definitions
+ --list-approved-families List all defined license families
+ --list-licenses List all active licenses
+ --no-default-licenses Ignore default configuration. By default
+ all approved default licenses are used
+ -o,--out Define the output file where to write
+ report (default is System.out)
-s,--stylesheet XSLT stylesheet to use when creating the
report. Not compatible with -x
+ --scan-hidden-directories Scan hidden directories
-x,--xml Output the report in raw XML format. Not
compatible with -s
+
diff --git a/apache-rat/pom.xml b/apache-rat/pom.xml
index 418ee9328..0aee0489c 100644
--- a/apache-rat/pom.xml
+++ b/apache-rat/pom.xml
@@ -1,4 +1,4 @@
-
+
- check-java-1.5-compat
+ check-java-1.8-compat
true
@@ -119,7 +118,6 @@
-
@@ -151,7 +149,7 @@
-
+
@@ -161,7 +159,6 @@
-
apache-release
@@ -177,10 +174,11 @@
make-assembly
- package
-
- single
-
+ package
+
+
+ single
+
diff --git a/apache-rat/src/site/apt/index.apt.vm b/apache-rat/src/site/apt/index.apt.vm
index 1e8dd8c3a..53348ab90 100644
--- a/apache-rat/src/site/apt/index.apt.vm
+++ b/apache-rat/src/site/apt/index.apt.vm
@@ -76,16 +76,16 @@ java -jar apache-rat/target/apache-rat-${project.version}.jar
+------------------------------------------+
usage: java -jar apache-rat/target/apache-rat-${project.version}.jar
- [options] [DIR|TARBALL]
+ [options] [DIR|TARBALL]
Available options
- -A,--addLicense Add the default license header to any file
+ -a,--addLicence 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.
- -a,--addlicense Add the default license header to any file
+ -A,--addLicense 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
@@ -96,20 +96,28 @@ Available options
"Copyright 2008 Foo"
-d,--dir Used to indicate source when using
--exclude
- -E,--exclude-file Excludes files matching regular expression
- in Note that --dir is required when
- using this parameter.
-e,--exclude Excludes files matching wildcard
. Note that --dir is required
when using this parameter. Allows multiple
arguments.
+ -E,--exclude-file Excludes files matching regular expression
+ in Note that --dir is required when
+ using this parameter.
-f,--force Forces any changes in files to be written
directly to the source files (i.e. new
files are not created)
- -h,--help Print help for the Rat command line
+ -h,--help Print help for the RAT command line
interface and exit
+ --licenses File names or URLs for license definitions
+ --list-approved-families List all defined license families
+ --list-licenses List all active licenses
+ --no-default-licenses Ignore default configuration. By default
+ all approved default licenses are used
+ -o,--out Define the output file where to write
+ report (default is System.out)
-s,--stylesheet XSLT stylesheet to use when creating the
report. Not compatible with -x
+ --scan-hidden-directories Scan hidden directories
-x,--xml Output the report in raw XML format. Not
compatible with -s
+------------------------------------------+
diff --git a/mvnw b/mvnw
new file mode 100755
index 000000000..8d937f4c1
--- /dev/null
+++ b/mvnw
@@ -0,0 +1,308 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# 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.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Apache Maven Wrapper startup batch script, version 3.2.0
+#
+# Required ENV vars:
+# ------------------
+# JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+# MAVEN_OPTS - parameters passed to the Java VM when running Maven
+# e.g. to debug Maven itself, use
+# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+# ----------------------------------------------------------------------------
+
+if [ -z "$MAVEN_SKIP_RC" ] ; then
+
+ if [ -f /usr/local/etc/mavenrc ] ; then
+ . /usr/local/etc/mavenrc
+ fi
+
+ if [ -f /etc/mavenrc ] ; then
+ . /etc/mavenrc
+ fi
+
+ if [ -f "$HOME/.mavenrc" ] ; then
+ . "$HOME/.mavenrc"
+ fi
+
+fi
+
+# OS specific support. $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "$(uname)" in
+ CYGWIN*) cygwin=true ;;
+ MINGW*) mingw=true;;
+ Darwin*) darwin=true
+ # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+ # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+ if [ -z "$JAVA_HOME" ]; then
+ if [ -x "/usr/libexec/java_home" ]; then
+ JAVA_HOME="$(/usr/libexec/java_home)"; export JAVA_HOME
+ else
+ JAVA_HOME="/Library/Java/Home"; export JAVA_HOME
+ fi
+ fi
+ ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+ if [ -r /etc/gentoo-release ] ; then
+ JAVA_HOME=$(java-config --jre-home)
+ fi
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=$(cygpath --unix "$JAVA_HOME")
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=$(cygpath --path --unix "$CLASSPATH")
+fi
+
+# For Mingw, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+ [ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] &&
+ JAVA_HOME="$(cd "$JAVA_HOME" || (echo "cannot cd into $JAVA_HOME."; exit 1); pwd)"
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+ javaExecutable="$(which javac)"
+ if [ -n "$javaExecutable" ] && ! [ "$(expr "\"$javaExecutable\"" : '\([^ ]*\)')" = "no" ]; then
+ # readlink(1) is not available as standard on Solaris 10.
+ readLink=$(which readlink)
+ if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then
+ if $darwin ; then
+ javaHome="$(dirname "\"$javaExecutable\"")"
+ javaExecutable="$(cd "\"$javaHome\"" && pwd -P)/javac"
+ else
+ javaExecutable="$(readlink -f "\"$javaExecutable\"")"
+ fi
+ javaHome="$(dirname "\"$javaExecutable\"")"
+ javaHome=$(expr "$javaHome" : '\(.*\)/bin')
+ JAVA_HOME="$javaHome"
+ export JAVA_HOME
+ fi
+ fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+ if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ else
+ JAVACMD="$(\unset -f command 2>/dev/null; \command -v java)"
+ fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+ echo "Error: JAVA_HOME is not defined correctly." >&2
+ echo " We cannot execute $JAVACMD" >&2
+ exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+ echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+ if [ -z "$1" ]
+ then
+ echo "Path not specified to find_maven_basedir"
+ return 1
+ fi
+
+ basedir="$1"
+ wdir="$1"
+ while [ "$wdir" != '/' ] ; do
+ if [ -d "$wdir"/.mvn ] ; then
+ basedir=$wdir
+ break
+ fi
+ # workaround for JBEAP-8937 (on Solaris 10/Sparc)
+ if [ -d "${wdir}" ]; then
+ wdir=$(cd "$wdir/.." || exit 1; pwd)
+ fi
+ # end of workaround
+ done
+ printf '%s' "$(cd "$basedir" || exit 1; pwd)"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+ if [ -f "$1" ]; then
+ # Remove \r in case we run on Windows within Git Bash
+ # and check out the repository with auto CRLF management
+ # enabled. Otherwise, we may read lines that are delimited with
+ # \r\n and produce $'-Xarg\r' rather than -Xarg due to word
+ # splitting rules.
+ tr -s '\r\n' ' ' < "$1"
+ fi
+}
+
+log() {
+ if [ "$MVNW_VERBOSE" = true ]; then
+ printf '%s\n' "$1"
+ fi
+}
+
+BASE_DIR=$(find_maven_basedir "$(dirname "$0")")
+if [ -z "$BASE_DIR" ]; then
+ exit 1;
+fi
+
+MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR
+log "$MAVEN_PROJECTBASEDIR"
+
+##########################################################################################
+# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+# This allows using the maven wrapper in projects that prohibit checking in binary data.
+##########################################################################################
+wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar"
+if [ -r "$wrapperJarPath" ]; then
+ log "Found $wrapperJarPath"
+else
+ log "Couldn't find $wrapperJarPath, downloading it ..."
+
+ if [ -n "$MVNW_REPOURL" ]; then
+ wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+ else
+ wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+ fi
+ while IFS="=" read -r key value; do
+ # Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' )
+ safeValue=$(echo "$value" | tr -d '\r')
+ case "$key" in (wrapperUrl) wrapperUrl="$safeValue"; break ;;
+ esac
+ done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
+ log "Downloading from: $wrapperUrl"
+
+ if $cygwin; then
+ wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath")
+ fi
+
+ if command -v wget > /dev/null; then
+ log "Found wget ... using wget"
+ [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet"
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
+ else
+ wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
+ fi
+ elif command -v curl > /dev/null; then
+ log "Found curl ... using curl"
+ [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent"
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
+ else
+ curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
+ fi
+ else
+ log "Falling back to using Java to download"
+ javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java"
+ javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class"
+ # For Cygwin, switch paths to Windows format before running javac
+ if $cygwin; then
+ javaSource=$(cygpath --path --windows "$javaSource")
+ javaClass=$(cygpath --path --windows "$javaClass")
+ fi
+ if [ -e "$javaSource" ]; then
+ if [ ! -e "$javaClass" ]; then
+ log " - Compiling MavenWrapperDownloader.java ..."
+ ("$JAVA_HOME/bin/javac" "$javaSource")
+ fi
+ if [ -e "$javaClass" ]; then
+ log " - Running MavenWrapperDownloader.java ..."
+ ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath"
+ fi
+ fi
+ fi
+fi
+##########################################################################################
+# End of extension
+##########################################################################################
+
+# If specified, validate the SHA-256 sum of the Maven wrapper jar file
+wrapperSha256Sum=""
+while IFS="=" read -r key value; do
+ case "$key" in (wrapperSha256Sum) wrapperSha256Sum=$value; break ;;
+ esac
+done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
+if [ -n "$wrapperSha256Sum" ]; then
+ wrapperSha256Result=false
+ if command -v sha256sum > /dev/null; then
+ if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c > /dev/null 2>&1; then
+ wrapperSha256Result=true
+ fi
+ elif command -v shasum > /dev/null; then
+ if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c > /dev/null 2>&1; then
+ wrapperSha256Result=true
+ fi
+ else
+ echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available."
+ echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties."
+ exit 1
+ fi
+ if [ $wrapperSha256Result = false ]; then
+ echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2
+ echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2
+ echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2
+ exit 1
+ fi
+fi
+
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME")
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=$(cygpath --path --windows "$CLASSPATH")
+ [ -n "$MAVEN_PROJECTBASEDIR" ] &&
+ MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR")
+fi
+
+# Provide a "standardized" way to retrieve the CLI args that will
+# work with both Windows and non-Windows executions.
+MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*"
+export MAVEN_CMD_LINE_ARGS
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+# shellcheck disable=SC2086 # safe args
+exec "$JAVACMD" \
+ $MAVEN_OPTS \
+ $MAVEN_DEBUG_OPTS \
+ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+ "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+ ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
diff --git a/mvnw.cmd b/mvnw.cmd
new file mode 100644
index 000000000..f80fbad3e
--- /dev/null
+++ b/mvnw.cmd
@@ -0,0 +1,205 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM http://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied. See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Apache Maven Wrapper startup batch script, version 3.2.0
+@REM
+@REM Required ENV vars:
+@REM JAVA_HOME - location of a JDK home dir
+@REM
+@REM Optional ENV vars
+@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
+@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
+@REM e.g. to debug Maven itself, use
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+@REM ----------------------------------------------------------------------------
+
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
+@echo off
+@REM set title of command window
+title %0
+@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
+@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
+
+@REM set %HOME% to equivalent of $HOME
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
+
+@REM Execute a user defined script before this one
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
+if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
+if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+
+FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+ IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B
+)
+
+@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
+if exist %WRAPPER_JAR% (
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Found %WRAPPER_JAR%
+ )
+) else (
+ if not "%MVNW_REPOURL%" == "" (
+ SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+ )
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Couldn't find %WRAPPER_JAR%, downloading it ...
+ echo Downloading from: %WRAPPER_URL%
+ )
+
+ powershell -Command "&{"^
+ "$webclient = new-object System.Net.WebClient;"^
+ "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
+ "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
+ "}"^
+ "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^
+ "}"
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Finished downloading %WRAPPER_JAR%
+ )
+)
+@REM End of extension
+
+@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file
+SET WRAPPER_SHA_256_SUM=""
+FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+ IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B
+)
+IF NOT %WRAPPER_SHA_256_SUM%=="" (
+ powershell -Command "&{"^
+ "$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^
+ "If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^
+ " Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^
+ " Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^
+ " Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^
+ " exit 1;"^
+ "}"^
+ "}"
+ if ERRORLEVEL 1 goto error
+)
+
+@REM Provide a "standardized" way to retrieve the CLI args that will
+@REM work with both Windows and non-Windows executions.
+set MAVEN_CMD_LINE_ARGS=%*
+
+%MAVEN_JAVA_EXE% ^
+ %JVM_CONFIG_MAVEN_PROPS% ^
+ %MAVEN_OPTS% ^
+ %MAVEN_DEBUG_OPTS% ^
+ -classpath %WRAPPER_JAR% ^
+ "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
+ %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
+if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%"=="on" pause
+
+if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
+
+cmd /C exit /B %ERROR_CODE%
diff --git a/pom.xml b/pom.xml
index 497779872..e7f4c8c8a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -20,11 +20,11 @@
org.apache
apache
- 27
+ 31
org.apache.rat
apache-rat-project
- 0.16-SNAPSHOT
+ 0.16.1-SNAPSHOT
pom
Apache Creadur Rat
https://creadur.apache.org/rat/
@@ -45,24 +45,30 @@ agnostic home for software distribution comprehension and audit tools.
apache
https://sonarcloud.io
+ UTF-8
- 10
- 1.10.12
- 4.7.0
+ 1703723704
+ 1.10.14
+ 4.11.0
1.8
${javaVersion}
${javaVersion}
- 2.2.1
+ 3.2.5
+ 3.9.6
RAT
- 3.6.4
+ 3.11.0
2.12.1
- 3.4.1
- 3.18.0
+ 3.6.3
+ 3.21.2
- 0.16
+
+ 0.16.1
0.17-SNAPSHOT
+
+ 5.10.1
+ 1.10.1
@@ -72,11 +78,6 @@ agnostic home for software distribution comprehension and audit tools.
-
- org.apache.rat
- apache-rat-api
- ${project.version}
-
org.apache.rat
apache-rat-core
@@ -90,32 +91,61 @@ agnostic home for software distribution comprehension and audit tools.
commons-cli
commons-cli
- 1.5.0
+ 1.6.0
org.apache.commons
commons-collections4
4.4
+
+ commons-beanutils
+ commons-beanutils
+ 1.9.4
+
commons-io
commons-io
- 2.11.0
+ 2.15.1
org.apache.commons
commons-lang3
- 3.12.0
+ 3.14.0
org.apache.commons
commons-compress
- 1.21
+ 1.25.0
+
+
+ org.junit.jupiter
+ junit-jupiter-api
+ ${junit.version}
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-engine
+ ${junit.version}
+ test
- junit
- junit
- 4.13.2
+ org.junit.jupiter
+ junit-jupiter-params
+ ${junit.version}
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-migrationsupport
+ ${junit.version}
+ test
+
+
+ org.junit.platform
+ junit-platform-runner
+ ${junit.platform.version}
test
@@ -148,6 +178,17 @@ agnostic home for software distribution comprehension and audit tools.
${ant.version}
test
+
+ org.apache.maven.plugin-tools
+ maven-plugin-annotations
+ ${mavenPluginPluginVersion}
+
+
+ org.assertj
+ assertj-core
+ 3.25.1
+ test
+
@@ -221,7 +262,7 @@ agnostic home for software distribution comprehension and audit tools.
org.apache.maven.plugins
maven-jxr-plugin
- 3.3.0
+ 3.3.2
@@ -246,7 +287,7 @@ agnostic home for software distribution comprehension and audit tools.
org.apache.maven.plugins
maven-project-info-reports-plugin
- 3.4.1
+ 3.5.0
@@ -268,8 +309,6 @@ agnostic home for software distribution comprehension and audit tools.
org.apache.rat
apache-rat-plugin
-
- 0.15
@@ -298,7 +337,7 @@ agnostic home for software distribution comprehension and audit tools.
org.apache.maven.plugins
maven-compiler-plugin
- 3.10.1
+ 3.12.1
org.apache.maven.plugins
@@ -308,7 +347,12 @@ agnostic home for software distribution comprehension and audit tools.
org.apache.maven.plugins
maven-dependency-plugin
- 3.3.0
+ 3.6.1
+
+
+ org.apache.maven.plugins
+ maven-invoker-plugin
+ 3.6.0
org.apache.maven.plugins
@@ -318,6 +362,11 @@ agnostic home for software distribution comprehension and audit tools.
${javaVersion}
+
+ org.apache.maven.plugins
+ maven-plugin-plugin
+ ${mavenPluginPluginVersion}
+
org.apache.maven.plugins
maven-site-plugin
@@ -330,11 +379,10 @@ agnostic home for software distribution comprehension and audit tools.
org.apache.rat
apache-rat-plugin
- 0.15
+ 0.16
-
- .travis.yml
+ .asf.yaml
BUILD.txt
apache-rat/README*.txt
@@ -348,16 +396,38 @@ agnostic home for software distribution comprehension and audit tools.
+
+ org.apache.maven.plugins
+ maven-remote-resources-plugin
+ 3.1.0
+
org.apache.maven.plugins
maven-release-plugin
- 2.5.3
+ 3.0.1
true
forked-path
+
+ org.apache.maven.plugins
+ maven-resources-plugin
+ 3.3.1
+
+ ISO-8859-1
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 3.2.5
+
+ 1
+ -Dfile.encoding=ISO-8859-1
+
+
org.eclipse.m2e
@@ -370,15 +440,15 @@ agnostic home for software distribution comprehension and audit tools.
org.apache.rat
- apache-rat-plugin
-
- [0.15,)
+ apache-rat-plugin
+
+ [0.16,)
check
-
+
@@ -400,7 +470,7 @@ agnostic home for software distribution comprehension and audit tools.
-
+
@@ -409,7 +479,6 @@ agnostic home for software distribution comprehension and audit tools.
org.apache.maven.plugins
maven-enforcer-plugin
- 3.1.0
@@ -423,7 +492,7 @@ agnostic home for software distribution comprehension and audit tools.
${javaVersion}
- 3.0.5
+ ${mavenMinVersion}
true
@@ -434,7 +503,7 @@ agnostic home for software distribution comprehension and audit tools.
org.codehaus.mojo
extra-enforcer-rules
- 1.6.1
+ 1.7.0
@@ -452,7 +521,7 @@ agnostic home for software distribution comprehension and audit tools.
org.codehaus.mojo
animal-sniffer-maven-plugin
- 1.22
+ 1.23
@@ -481,8 +550,7 @@ agnostic home for software distribution comprehension and audit tools.
org.apache.maven.wagon
wagon-ssh
-
- 3.5.2
+ 3.5.3
@@ -594,6 +662,14 @@ agnostic home for software distribution comprehension and audit tools.
Paul Merlin
paulmerlin@apache.org
+
+ Claude Warren
+ claude@apache.org
+
+
+ Niels Basjes
+ nielsbasjes@apache.org
+
scm:git:https://gitbox.apache.org/repos/asf/creadur-rat.git
@@ -602,7 +678,6 @@ agnostic home for software distribution comprehension and audit tools.
HEAD
- apache-rat-api
apache-rat-core
apache-rat-plugin
apache-rat-tasks
@@ -699,11 +774,11 @@ agnostic home for software distribution comprehension and audit tools.
-
-
-
- staged-releases-rat-015
- https://repository.apache.org/content/repositories/orgapachecreadur-1008/
-
-
+
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index e05c0db0b..e6853e568 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -21,12 +21,10 @@ This file is also used by the maven-changes-plugin to generate the release notes
Useful ways of finding items to add to this file are:
1. Add items when you fix a bug or add a feature (this makes the
-release process easy :-).
+release process easier :-).
2. Do a JIRA search for tickets closed since the previous release.
-
-3. Use the report generated by the maven-changelog-plugin to see all
-SVN commits. TBA how to use this with SVN.
+ https://issues.apache.org/jira/projects/RAT?selectedItem=com.atlassian.jira.jira-projects-plugin:release-page
To generate the release notes from this file:
@@ -43,6 +41,15 @@ The type attribute can be add,update,fix,remove.
the rest are optional; order not important
having the issue number first makes it easier to read the XML outline
+
+If you wonder which action types are available:
+https://maven.apache.org/plugins/maven-changes-plugin/xsd/changes-1.0.0.xsd
+
+ * add: added functionality to the project.
+ * fix: bug fix for the project
+ * update: updated some part of the project.
+ * remove: removed some functionality from the project.
+
-->
type attribute can be add,update,fix,remove.
-
-
+
+
+ Use Maven wrapper (with version 3.9.6) for reproducable local builds and on ASF Jenkins and Github Actions.
+
+
+ Reimplement old configuration elements for custom licenses in Maven plugin configurations (and updates to the webpage).
+
+
+ Add integration test to allow enhanced testing of custom licenses.
+
+
+ Update gitignore-reader library to 1.3.1 to get latest changes in gitignore parsing.
+
+
+ Fix NPE by falling back to default stylesheet if none was configured before.
+
+
+ Issue a warning if a user defined License family has the same name as an existing one.
+
+
+ Migrate to JUnit5 and fix minor issues in tests and javadoc.
+
+
+ Remove apache-rat-api module that contains misleading license-related classes.
+
+
+ To improve the performance during SPDX processing a check to skip expensive regex operations was added.
+
+
+ Internal logging feature enabled for license matching tests to avoid random test failures when manipulating System.out in test runs.
+
+
+ Set log level default for CLI runs to WARN. This applies to test runs as well, as other UIs configure their logging natively.
+
+
+ TODO: collect all dependabot updates for release 0.16.1
+
+
+
+
+ Update actions/setup-java from 3.4.1 to 4.0.0.
+
+
+ Update actions/cache from 3.0.11 to 3.3.2
+
+
+ Update actions/checkout from 3 to 4.
+
+
+ Update mockito-core from 4.7.0 to 4.11.0, newer versions 5.x cannot be applied due to our JDK8-compatibility restriction.
+
+
+ Update plexus-utils from 3.4.2 to 3.5.1, versions 4.x are for upcoming Maven4 and must not be applied here.
+
+
+ Update maven-plugin-version from 3.6.4 to 3.8.2.
+
+
+ Update wagon-ssh from 3.5.2 to 3.5.3.
+
+
+ Update Ant from 1.10.12 to 1.10.14.
+
+
+ Update ASF parent pom from 27 to 31 and update multiple maven plugin versions implicitly (surefire, release, project-info, enforcer, jxr).
+
+
+ Update doxiaVersion from 1.11.1 to 1.12.0.
+
+
+ Update maven-shared-utils from 3.3.4 to 3.4.2.
+
+
+ Update org.slf4j:slf4j-simple from 1.7.36 to 2.0.9.
+
+
+ Update commons-lang3 from 3.5 to 3.14.0.
+
+
+ Update commons-compress from 1.21 to 1.25.
+
+
+ Update commons-io from 2.11.0 to 2.15.1.
+
+
+ Update commons-cli from 1.5.0 to 1.6.0.
+
+
+ Update maven-pmd-plugin from 3.18.0 to 3.21.2.
+
+
+ Update maven-dependency-plugin from 3.3.0 to 3.6.1.
+
+
+ Update maven-compiler-plugin from 3.10.1 to 3.12.1.
+
+
+ Update maven-javadoc-plugin from 3.4.1 to 3.6.3.
+
+
+ Update maven-release-plugin from 2.5.3 to 3.0.1.
+
+
+ Update maven-enforcer-plugin from 3.1.0 to 3.4.1.
+
+
+ Update extra-enforcer-rules from 1.6.1 to 1.7.0
+
+
+ Update maven-release-plugin from 2.5.3 to 3.0.1.
+
- TODO: collect all dependabot updates for release 0.16.
+ Update animal-sniffer-maven-plugin from 1.22 to 1.23.
+
+
+ Update maven-project-info-reports-plugin from 3.4.1 to 3.5.0.
+
+
+ Update maven-surefire-plugin from 3.2.2 to 3.2.3.
+
+
+ Fix existing javadoc build errors and add javadoc generation to existing GithubActions to not introduce build errors via merge requests.
+
+
+ Update minimal build Maven version to 3.2.5 and maven dependencies to 3.9.6. Remove pre-JDK8 code constructs and minor refactorings.
+
+
+ Enhance .gitignore handling; support multiple .gitignore files and allow a more complete parsing of Git's ignore files.
+
+
+ Add configuration option to scan hidden directories: --scan-hidden-directories on the command line and scanHiddenDirectories as a Maven plugin parameter.
+
+
+ Add new command line option -o/--output to write RAT's output to a file.
+
+
+ Add markdown (MD) and yaml (YML/YAML) as a recognized extension for file and license processing.
+
+
+ Ensure that System.out does not get closed during report generation and updated javadocs.
+
+
+ Add default exclusion of MANIFEST.MF as it must not contain comment lines to include a license.
+
+
+ Allow text-based XML configuration of RAT.
+
+
+ Update commons-compress to 1.24.0 in order to circumvent CVE-2023-42503.
+
+
+ Added SPDX processing for default licenses.
+
+
+ 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.
+
+
+ Change log output level of SCM ignore parser from info to debug in order to produce less log output in RAT runs.
+
+
+ Add default recursive exclusion for maven-induced build artifacts in folder .mvn.
+
+
+ Remove Travis build as it is unreliable. Builds with ASF Jenkins and Github Actions remain as before.
@@ -314,7 +494,7 @@ The type attribute can be add,update,fix,remove.
Download section does not work if SNAPSHOT is deployed, add download of previous RAT release.
- Fixed example on webpage abozt usage of custom licenses.
+ Fixed example on webpage about usage of custom licenses.
Add support for Golang and Perl module files.
diff --git a/src/site/apt/index.apt.vm b/src/site/apt/index.apt.vm
index 52f9cc9c8..bf4513dbe 100644
--- a/src/site/apt/index.apt.vm
+++ b/src/site/apt/index.apt.vm
@@ -49,7 +49,7 @@ Apache Rat
Apache Rat ${project.version} ships with tooling for
- * {{{https://ant.apache.org/} Apache Ant}},
+ * {{{https://ant.apache.org/}Apache Ant}},
* {{{https://maven.apache.org}Apache Maven}} and
diff --git a/src/site/md/architecture.md b/src/site/md/architecture.md
new file mode 100644
index 000000000..987705387
--- /dev/null
+++ b/src/site/md/architecture.md
@@ -0,0 +1,97 @@
+
+
+# Overview
+
+The RAT architecture is build around a single engine that parses input files to build an XML based report. User interfaces (UIs) create and configure a `ReportConfiguration` which is passed to a `Reporter` instance which performs all the processing.
+
+```
+/------\ /------\ /------\
+| CLI | |Maven | | Ant |
+| UI | | UI | | UI |
+\--+---/ \--+---/ \--+---/
+ | | |
+ \-----------+-----------/ ReportConfiguration
+ | input to Reporter
+ /----+----\
+ | Reporter| <--- Multiple files and directories
+ \----+----/
+ |
+ V
+ Report
+
+```
+
+# Configuration
+
+The `ReportConfiguration` contains all the options for the Reporter class. User interfaces create a `ReportConfiguration` and pass it to the `Reporter` instance for execution. The configuraiton specifies the configuraiton for:
+
+* License Families -- An identifier for families of licenses that share the same constraints. The default list is defined in the `o.a.r.default.xml` file in the families section.
+* Licenses -- A the definition of a license that defines the matchers that comprise the test for the license. The defualt licenses are defined in the `o.a.r.default.xml` file in the licenses section.
+* Approved License Families -- A list of license families that are approved. Licenses of families not in this are unapproved. The defualt approved license families are defined in the `o.a.r.default.xml` file in the approved section.
+
+## License Families
+
+A license family comprises an ID and a name. New families may be added to the `o.a.r.default.xml` file or programattically from the UI. License family IDs must be unique. Later ID definitions override earlier definitions.
+
+## License
+
+A license definition comprises a family (identified by its ID), and a matcher. Licenses adopt the ID of their family which may be overridden with an id attribute. Licenses also adopt the name of their family unless it is overridden by a name attribute.
+
+## Approved Licenses
+
+The approved licenses are enumerated in a list. Licenses are selected by family and the family ID is specified in the list.
+
+## Matchers
+
+Matchers are classes that implement specific tests. They are created by builders. The default builders are specified in the `o.a.r.default.xml` file in the matchers section.
+
+### Matcher.Builder
+
+New matcher builders may be defined within the `o.a.r.default.xml` file and then used in the license definitions within the file.
+
+Matcher builder class names must be of the form `Builder` where `` becomes the name of the matcher and is used in identifying the matcher to use (e.g. as a tag in the License section of the `o.a.r.default.xml` file). They must also implement the `o.a.r.analysis.IHeaderMatcher.Builder` interface.
+
+## flags to add licenses and copyrights to files.
+
+The configuration has a set of options to add licenses and optionally copyright notices to files that do not have them. The `addLicenses` option adds the Apache2 license to files that do not have any license specified. If the `copyright` text is provided it is also added to the files. The `addLicensesForced` modifies the way the licenses are added, by default the licenses are added to new files with name of the old file but a `.new` extension added. If `addLicensesForced` is specified then the files are overwritten.
+
+## file name filter
+
+The file name filter specifies a filter to be used to filter out any files that should not be evaluated.
+
+## out
+
+The `out` parameter specifies an `OutputStream` IOSupplier that is used to create the output stream to write text to. By default this is the `System.out` stream.
+
+## stylesheet
+
+the `styleSheet` parameter specifies the `InputStream` IOSupplier that is used to read the stylesheet that styles the XML output.
+
+## IReportable
+
+The `IReportable` parameter identifies the objects that the report should run against. Implementations of `IReportable` generally do things like walk directory trees, or archives.
+
+# Reporter
+
+The reporter uses the `ReporterConfiguration` to configure the report. It then begins to read the files. Each file is a `Document` the reporter determines the Document type and if appropriate reads the header information (50 lines) from the document.
+
+The header information is passed to the licenses. The processing of the file stops when a license is triggered (found) or the end of the header is reached.
+
+The information retrieved is used to create an XML document that may be styled by the defined Stylesheet.
+
+The reporter utilizes the `RatReport` interface to determine what actions to take with the documents. Currently the `RatReport` interface is used to define license adding capabilities, report claim aggregation, and multiplexed reports. Additional capabilities can be implemented by implementing a `RatReport` and inserting it into the processing chain.
diff --git a/src/site/site.xml b/src/site/site.xml
index beda3f78b..002451f8d 100644
--- a/src/site/site.xml
+++ b/src/site/site.xml
@@ -89,7 +89,6 @@
-
@@ -99,7 +98,7 @@
- Copyright © 2016-2022 The Apache Software Foundation, Licensed under the Apache License, Version 2.0.
+ Copyright © 2016-2024 The Apache Software Foundation, Licensed under the Apache License, Version 2.0.
Apache Creadur, Creadur, Apache Rat, Apache Tentacles, Apache Whisker, Apache and the Apache feather logo are trademarks
of The Apache Software Foundation.
Oracle and Java are registered trademarks of Oracle and/or its affiliates.