From 161073aa6e66a5332aea8776a0393d0c8d2cedaf Mon Sep 17 00:00:00 2001 From: Jan-Hendrik Diederich Date: Thu, 14 Nov 2019 09:27:14 +0100 Subject: [PATCH 01/34] Line endings automatically updated conforming to settings --- mvnw.cmd | 322 +++++++++--------- .../src/files/properties/test.crlf.sh | 4 +- .../META-INF/licenses/epl_only_v2/header.txt | 8 +- .../META-INF/licenses/epl_v2/header.txt | 20 +- 4 files changed, 177 insertions(+), 177 deletions(-) diff --git a/mvnw.cmd b/mvnw.cmd index a110c4d0f..adaa3c2ad 100755 --- a/mvnw.cmd +++ b/mvnw.cmd @@ -1,161 +1,161 @@ -@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 Maven2 Start Up Batch script -@REM -@REM Required ENV vars: -@REM JAVA_HOME - location of a JDK home dir -@REM -@REM Optional ENV vars -@REM M2_HOME - location of maven2's installed home dir -@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 key stroke 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 my 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 "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" -if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\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 DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.0/maven-wrapper-0.4.0.jar" -FOR /F "tokens=1,2 delims==" %%A IN (%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties) DO ( - IF "%%A"=="wrapperUrl" SET DOWNLOAD_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% ( - echo Found %WRAPPER_JAR% -) else ( - echo Couldn't find %WRAPPER_JAR%, downloading it ... - echo Downloading from: %DOWNLOAD_URL% - powershell -Command "(New-Object Net.WebClient).DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')" - echo Finished downloading %WRAPPER_JAR% -) -@REM End of extension - -%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 "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" -if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\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% - -exit /B %ERROR_CODE% +@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 Maven2 Start Up Batch script +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM M2_HOME - location of maven2's installed home dir +@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 key stroke 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 my 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 "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" +if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\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 DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.0/maven-wrapper-0.4.0.jar" +FOR /F "tokens=1,2 delims==" %%A IN (%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties) DO ( + IF "%%A"=="wrapperUrl" SET DOWNLOAD_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% ( + echo Found %WRAPPER_JAR% +) else ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %DOWNLOAD_URL% + powershell -Command "(New-Object Net.WebClient).DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')" + echo Finished downloading %WRAPPER_JAR% +) +@REM End of extension + +%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 "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" +if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\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% + +exit /B %ERROR_CODE% diff --git a/src/it/update-file-header-test-mojo/src/files/properties/test.crlf.sh b/src/it/update-file-header-test-mojo/src/files/properties/test.crlf.sh index aefc77241..0711e4cb1 100644 --- a/src/it/update-file-header-test-mojo/src/files/properties/test.crlf.sh +++ b/src/it/update-file-header-test-mojo/src/files/properties/test.crlf.sh @@ -1,3 +1,3 @@ -#!/bin/sh - +#!/bin/sh + ls ~/* \ No newline at end of file diff --git a/src/main/resources/META-INF/licenses/epl_only_v2/header.txt b/src/main/resources/META-INF/licenses/epl_only_v2/header.txt index 7248abcf3..fe21c469e 100644 --- a/src/main/resources/META-INF/licenses/epl_only_v2/header.txt +++ b/src/main/resources/META-INF/licenses/epl_only_v2/header.txt @@ -1,5 +1,5 @@ -This program and the accompanying materials are made -available under the terms of the Eclipse Public License 2.0 -which is available at https://www.eclipse.org/legal/epl-2.0/ - +This program and the accompanying materials are made +available under the terms of the Eclipse Public License 2.0 +which is available at https://www.eclipse.org/legal/epl-2.0/ + SPDX-License-Identifier: EPL-2.0 \ No newline at end of file diff --git a/src/main/resources/META-INF/licenses/epl_v2/header.txt b/src/main/resources/META-INF/licenses/epl_v2/header.txt index 9f1b8cc7d..494345104 100644 --- a/src/main/resources/META-INF/licenses/epl_v2/header.txt +++ b/src/main/resources/META-INF/licenses/epl_v2/header.txt @@ -1,11 +1,11 @@ -This program and the accompanying materials are made available under the -terms of the Eclipse Public License 2.0 which is available at -http://www.eclipse.org/legal/epl-2.0. - -This Source Code may also be made available under the following Secondary -Licenses when the conditions for such availability set forth in the Eclipse -Public License, v. 2.0 are satisfied: GNU General Public License, version 2 -with the GNU Classpath Exception which is -available at https://www.gnu.org/software/classpath/license.html. - +This program and the accompanying materials are made available under the +terms of the Eclipse Public License 2.0 which is available at +http://www.eclipse.org/legal/epl-2.0. + +This Source Code may also be made available under the following Secondary +Licenses when the conditions for such availability set forth in the Eclipse +Public License, v. 2.0 are satisfied: GNU General Public License, version 2 +with the GNU Classpath Exception which is +available at https://www.gnu.org/software/classpath/license.html. + SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 \ No newline at end of file From 528becba604badab1b9fcfc55fedeb665942eeff Mon Sep 17 00:00:00 2001 From: Jan-Hendrik Diederich Date: Thu, 14 Nov 2019 09:32:51 +0100 Subject: [PATCH 02/34] Small code cleanups --- .../mojo/license/AbstractAddThirdPartyMojo.java | 12 ++++++------ .../license/AggregatorAddThirdPartyMojo.java | 17 +++++++++-------- .../license/api/DefaultThirdPartyHelper.java | 7 +++---- .../mojo/license/api/DefaultThirdPartyTool.java | 2 -- .../codehaus/mojo/license/model/LicenseMap.java | 10 +++++++--- 5 files changed, 25 insertions(+), 23 deletions(-) diff --git a/src/main/java/org/codehaus/mojo/license/AbstractAddThirdPartyMojo.java b/src/main/java/org/codehaus/mojo/license/AbstractAddThirdPartyMojo.java index 88a3d66a2..e35030423 100644 --- a/src/main/java/org/codehaus/mojo/license/AbstractAddThirdPartyMojo.java +++ b/src/main/java/org/codehaus/mojo/license/AbstractAddThirdPartyMojo.java @@ -35,6 +35,7 @@ import org.apache.maven.project.ProjectBuildingException; import org.codehaus.mojo.license.api.DefaultThirdPartyHelper; import org.codehaus.mojo.license.api.DependenciesTool; +import org.codehaus.mojo.license.api.DependenciesToolException; import org.codehaus.mojo.license.api.ThirdPartyHelper; import org.codehaus.mojo.license.api.ThirdPartyTool; import org.codehaus.mojo.license.api.ThirdPartyToolException; @@ -44,6 +45,10 @@ import org.codehaus.mojo.license.utils.SortedProperties; import org.codehaus.mojo.license.utils.StringToList; import org.codehaus.mojo.license.utils.UrlRequester; +import org.eclipse.aether.resolution.ArtifactResolutionException; +import org.eclipse.aether.transfer.ArtifactNotFoundException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.ByteArrayInputStream; import java.io.File; @@ -55,11 +60,6 @@ import java.util.Set; import java.util.SortedMap; import java.util.SortedSet; -import org.codehaus.mojo.license.api.DependenciesToolException; -import org.eclipse.aether.resolution.ArtifactResolutionException; -import org.eclipse.aether.transfer.ArtifactNotFoundException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** * Abstract mojo for all third-party mojos. @@ -354,7 +354,7 @@ public abstract class AbstractAddThirdPartyMojo /** * A URL prepared either our of {@link #overrideFile} or {@link #overrideUrl} or the default value. * - * @see LicenseMojoUtils#prepareThirdPartyOverrideUrl(URL, File, String, File) + * @see LicenseMojoUtils#prepareThirdPartyOverrideUrl(String, File, String, File) */ protected String resolvedOverrideUrl; diff --git a/src/main/java/org/codehaus/mojo/license/AggregatorAddThirdPartyMojo.java b/src/main/java/org/codehaus/mojo/license/AggregatorAddThirdPartyMojo.java index 2c5745e0c..8a82c5e2c 100644 --- a/src/main/java/org/codehaus/mojo/license/AggregatorAddThirdPartyMojo.java +++ b/src/main/java/org/codehaus/mojo/license/AggregatorAddThirdPartyMojo.java @@ -22,13 +22,6 @@ * #L% */ -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.SortedMap; -import java.util.SortedSet; import org.apache.commons.collections.CollectionUtils; import org.apache.maven.artifact.Artifact; import org.apache.maven.model.Plugin; @@ -45,6 +38,14 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.SortedMap; +import java.util.SortedSet; + /** * This goal forks executions of the add-third-party goal for all the leaf projects * of the tree of modules below the point where it is executed. Note that this @@ -274,7 +275,7 @@ protected void doAction() } // ---------------------------------------------------------------------- - // AbstractAddThirdPartyMojo Implementaton + // AbstractAddThirdPartyMojo Implementation // ---------------------------------------------------------------------- /** diff --git a/src/main/java/org/codehaus/mojo/license/api/DefaultThirdPartyHelper.java b/src/main/java/org/codehaus/mojo/license/api/DefaultThirdPartyHelper.java index a0c5ec70b..175ade6c0 100644 --- a/src/main/java/org/codehaus/mojo/license/api/DefaultThirdPartyHelper.java +++ b/src/main/java/org/codehaus/mojo/license/api/DefaultThirdPartyHelper.java @@ -31,6 +31,9 @@ import org.apache.maven.project.ProjectBuildingException; import org.codehaus.mojo.license.model.LicenseMap; import org.codehaus.mojo.license.utils.SortedProperties; +import org.eclipse.aether.repository.RemoteRepository; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.File; import java.io.IOException; @@ -44,9 +47,6 @@ import java.util.SortedMap; import java.util.SortedSet; import java.util.TreeMap; -import org.eclipse.aether.repository.RemoteRepository; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** * Default implementation of the {@link org.codehaus.mojo.license.api.ThirdPartyHelper}. @@ -338,5 +338,4 @@ public void mergeLicenses( List licenseMerges, LicenseMap licenseMap ) } } } - } diff --git a/src/main/java/org/codehaus/mojo/license/api/DefaultThirdPartyTool.java b/src/main/java/org/codehaus/mojo/license/api/DefaultThirdPartyTool.java index 966aa7ed1..d97086b90 100644 --- a/src/main/java/org/codehaus/mojo/license/api/DefaultThirdPartyTool.java +++ b/src/main/java/org/codehaus/mojo/license/api/DefaultThirdPartyTool.java @@ -361,14 +361,12 @@ public void addLicense( LicenseMap licenseMap, MavenProject project, List lic if ( Artifact.SCOPE_SYSTEM.equals( project.getArtifact().getScope() ) ) { - // do NOT treat system dependency return; } if ( CollectionUtils.isEmpty( licenses ) ) { - // no license found for the dependency licenseMap.put( LicenseMap.UNKNOWN_LICENSE_MESSAGE, project ); return; diff --git a/src/main/java/org/codehaus/mojo/license/model/LicenseMap.java b/src/main/java/org/codehaus/mojo/license/model/LicenseMap.java index 869b9556b..a78f136fa 100644 --- a/src/main/java/org/codehaus/mojo/license/model/LicenseMap.java +++ b/src/main/java/org/codehaus/mojo/license/model/LicenseMap.java @@ -40,6 +40,11 @@ /** * Map of artifacts (stub in mavenproject) group by their license. * + *
    + *
  • key is the license on which to associate the given project.
  • + *
  • value list of projects belonging to the license.
  • + *
+ * * @author tchemit dev@tchemit.fr * @since 1.0 */ @@ -54,7 +59,7 @@ public class LicenseMap private final Comparator projectComparator; /** - * Default contructor. + * Default constructor. */ public LicenseMap() { @@ -69,7 +74,7 @@ public LicenseMap( Comparator projectComparator ) /** * Store in the license map a project to a given license. * - * @param key the license on which to associate the gieven project + * @param key the license on which to associate the given project * @param value project to register in the license map * @return the set of projects using the given license */ @@ -80,7 +85,6 @@ public SortedSet put( String key, MavenProject value ) SortedSet valueList = get( key ); if ( valueList == null ) { - valueList = new TreeSet<>( projectComparator ); } From 3e151ca20bd0e0880cf037ec0b1b08d1bcd5d8c2 Mon Sep 17 00:00:00 2001 From: Jan-Hendrik Diederich Date: Thu, 14 Nov 2019 16:22:10 +0100 Subject: [PATCH 03/34] Option for aggregate-download-licenses for extended artifacts infos Extended information are fetched from JAR files contents. The option is a boolean called "extendedInfo" and a parameter for the aggregate-download-licenses goal. --- pom.xml | 19 +- .../license/AbstractDownloadLicensesMojo.java | 22 +- .../AggregateDownloadLicensesMojo.java | 13 +- .../mojo/license/DownloadLicensesMojo.java | 2 +- .../LicensesXmlInsertVersionsMojo.java | 2 +- .../download/LicenseSummaryWriter.java | 119 ++++++++- .../license/download/LicensedArtifact.java | 230 +++++++++++++++++- .../download/LicensedArtifactResolver.java | 21 +- .../license/download/ProjectLicenseInfo.java | 10 +- .../mojo/license/extended/ExtendedInfo.java | 149 ++++++++++++ .../mojo/license/extended/InfoFile.java | 96 ++++++++ .../license/download/LicenseMatchersTest.java | 6 +- .../license/download/LicenseSummaryTest.java | 4 +- 13 files changed, 647 insertions(+), 46 deletions(-) create mode 100644 src/main/java/org/codehaus/mojo/license/extended/ExtendedInfo.java create mode 100644 src/main/java/org/codehaus/mojo/license/extended/InfoFile.java diff --git a/pom.xml b/pom.xml index 5a25b5934..dca3458a5 100644 --- a/pom.xml +++ b/pom.xml @@ -32,7 +32,7 @@ license-maven-plugin - 2.0.1-SNAPSHOT + 2.1.0-SNAPSHOT maven-plugin License Maven Plugin @@ -112,7 +112,7 @@ 3.5.4 - 1.7 + 1.8 1.3 @@ -319,6 +319,11 @@ junit test + + org.osgi + org.osgi.core + 6.0.0 + @@ -423,7 +428,7 @@ org.codehaus.mojo.signature - java17 + java18 1.0 @@ -532,6 +537,14 @@ + + org.apache.maven.plugins + maven-compiler-plugin + + 8 + 8 + + diff --git a/src/main/java/org/codehaus/mojo/license/AbstractDownloadLicensesMojo.java b/src/main/java/org/codehaus/mojo/license/AbstractDownloadLicensesMojo.java index 5939e7306..de46ad117 100644 --- a/src/main/java/org/codehaus/mojo/license/AbstractDownloadLicensesMojo.java +++ b/src/main/java/org/codehaus/mojo/license/AbstractDownloadLicensesMojo.java @@ -40,6 +40,8 @@ import java.util.Set; import java.util.TreeMap; import java.util.regex.Pattern; + +import org.apache.commons.collections.CollectionUtils; import org.apache.commons.io.FileUtils; import org.apache.commons.lang.StringEscapeUtils; import org.apache.maven.artifact.repository.ArtifactRepository; @@ -810,7 +812,7 @@ public void execute() List depProjectLicensesWithErrors = filterErrors( depProjectLicenses ); writeLicenseSummary( depProjectLicenses, licensesOutputFile, writeVersions ); - if ( depProjectLicensesWithErrors != null && !depProjectLicensesWithErrors.isEmpty() ) + if ( !CollectionUtils.isEmpty( depProjectLicensesWithErrors ) ) { writeLicenseSummary( depProjectLicensesWithErrors, licensesErrorsFile, writeVersions ); } @@ -970,16 +972,10 @@ private static ErrorRemedy getEffectiveErrorRemedy( boolean quiet, ErrorRemedy e private void sortByGroupIdAndArtifactId( List depProjectLicenses ) { - Comparator comparator = new Comparator() - { - public int compare( ProjectLicenseInfo info1, ProjectLicenseInfo info2 ) - { + Comparator comparator = Comparator.comparing( info -> ( //ProjectLicenseInfo::getId() can not be used because . is before : thus a:b.c would be after a.b:c - return ( info1.getGroupId() + "+" + info1.getArtifactId() ).compareTo( info2.getGroupId() - + "+" + info2.getArtifactId() ); - } - }; - Collections.sort( depProjectLicenses, comparator ); + info.getGroupId() + "+" + info.getArtifactId() ) ); + depProjectLicenses.sort( comparator ); } // ---------------------------------------------------------------------- @@ -1084,7 +1080,7 @@ private ProjectLicenseInfo createDependencyProject( LicensedArtifact depMavenPro { final ProjectLicenseInfo dependencyProject = new ProjectLicenseInfo( depMavenProject.getGroupId(), depMavenProject.getArtifactId(), - depMavenProject.getVersion() ); + depMavenProject.getVersion(), depMavenProject.getExtendedInfos() ); final List licenses = depMavenProject.getLicenses(); for ( org.codehaus.mojo.license.download.License license : licenses ) { @@ -1106,9 +1102,9 @@ private ProjectLicenseInfo createDependencyProject( LicensedArtifact depMavenPro * license (if available) and the remote filename of the license. * * @param depProject the project containing the license - * @param licenseUrl the license url + * @param url the license url * @param licenseName the license name - * @param string + * @param licenseFileName License file name * @return A filename to be used for the downloaded license file * @throws URISyntaxException */ diff --git a/src/main/java/org/codehaus/mojo/license/AggregateDownloadLicensesMojo.java b/src/main/java/org/codehaus/mojo/license/AggregateDownloadLicensesMojo.java index fd44d576f..42476b4e2 100644 --- a/src/main/java/org/codehaus/mojo/license/AggregateDownloadLicensesMojo.java +++ b/src/main/java/org/codehaus/mojo/license/AggregateDownloadLicensesMojo.java @@ -93,6 +93,17 @@ public class AggregateDownloadLicensesMojo @Parameter( property = "reactorProjects", readonly = true, required = true ) private List reactorProjects; + /** + * Extract and use non maven data for license, copyright and vendor information, + * including the plugins archive file content. + *

+ * This means it will read infos from the JAR's MANIFEST.MF file, look for NOTICE.txt and similar files. + * + * @since 2.1 + */ + @Parameter( property = "license.extendedInfo", defaultValue = "false" ) + private boolean extendedInfo; + // ---------------------------------------------------------------------- // AbstractDownloadLicensesMojo Implementation // ---------------------------------------------------------------------- @@ -116,7 +127,7 @@ protected Map getDependencies() { licensedArtifactResolver.loadProjectDependencies( new ResolvedProjectDependencies( p.getArtifacts(), p.getDependencyArtifacts() ), - this, remoteRepositories, result ); + this, remoteRepositories, result, extendedInfo ); } return result; } diff --git a/src/main/java/org/codehaus/mojo/license/DownloadLicensesMojo.java b/src/main/java/org/codehaus/mojo/license/DownloadLicensesMojo.java index b0a6bebed..08d1bf153 100644 --- a/src/main/java/org/codehaus/mojo/license/DownloadLicensesMojo.java +++ b/src/main/java/org/codehaus/mojo/license/DownloadLicensesMojo.java @@ -87,7 +87,7 @@ protected Map getDependencies() final Map result = new TreeMap<>(); licensedArtifactResolver.loadProjectDependencies( new ResolvedProjectDependencies( project.getArtifacts(), project.getDependencyArtifacts() ), - this, remoteRepositories, result ); + this, remoteRepositories, result, false ); return result; } diff --git a/src/main/java/org/codehaus/mojo/license/LicensesXmlInsertVersionsMojo.java b/src/main/java/org/codehaus/mojo/license/LicensesXmlInsertVersionsMojo.java index fddcb50e9..beb993920 100644 --- a/src/main/java/org/codehaus/mojo/license/LicensesXmlInsertVersionsMojo.java +++ b/src/main/java/org/codehaus/mojo/license/LicensesXmlInsertVersionsMojo.java @@ -141,7 +141,7 @@ public ArtifactFilters getArtifactFilters() final Map resolvedDeps = new TreeMap(); licensedArtifactResolver.loadProjectDependencies( new ResolvedProjectDependencies( project.getArtifacts(), project.getDependencyArtifacts() ), - config, remoteRepositories, resolvedDeps ); + config, remoteRepositories, resolvedDeps, false ); final Map resolvedDepsMap = new HashMap<>( resolvedDeps.size() ); for ( LicensedArtifact dep : resolvedDeps.values() ) { diff --git a/src/main/java/org/codehaus/mojo/license/download/LicenseSummaryWriter.java b/src/main/java/org/codehaus/mojo/license/download/LicenseSummaryWriter.java index 6238ab3f9..af8c763ac 100644 --- a/src/main/java/org/codehaus/mojo/license/download/LicenseSummaryWriter.java +++ b/src/main/java/org/codehaus/mojo/license/download/LicenseSummaryWriter.java @@ -22,7 +22,12 @@ * #L% */ +import org.apache.commons.collections.CollectionUtils; +import org.apache.maven.model.Developer; +import org.apache.maven.model.Organization; import org.codehaus.mojo.license.Eol; +import org.codehaus.mojo.license.extended.ExtendedInfo; +import org.codehaus.mojo.license.extended.InfoFile; import org.w3c.dom.Document; import org.w3c.dom.Node; @@ -40,7 +45,9 @@ import java.io.StringWriter; import java.nio.charset.Charset; import java.nio.file.Files; +import java.util.Collection; import java.util.List; +import java.util.function.Supplier; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -130,9 +137,32 @@ else if ( hasDownloaderMessages ) depNode.appendChild( matchLicensesNode ); } + if ( dep.getExtendedInfo() != null ) + { + ExtendedInfo extendedInfo = dep.getExtendedInfo(); + addTextPropertyIfSet( doc, depNode, "bundleLicense", extendedInfo.getBundleLicense() ); + addCdataIfSet( doc, depNode, "bundleVendor", extendedInfo.getBundleVendor() ); + appendChildNodesIfSet( doc, depNode, "developers", extendedInfo.getDevelopers(), + ( doc1, developer ) -> createDeveloperNode( doc, developer ) ); + addCdataIfSet( doc, depNode, "implementationVendor", extendedInfo.getImplementationVendor() ); + appendChildNodesIfSet( doc, depNode, "infoFiles", extendedInfo.getInfoFiles(), + ( doc1, infoFile ) -> createInfoFileNode( doc, infoFile ) ); + if ( extendedInfo.getOrganization() != null + && ( extendedInfo.getOrganization().getName() != null + || extendedInfo.getOrganization().getUrl() != null ) ) + { + Node organizationNode = doc.createElement( "organization" ); + final Organization organization = extendedInfo.getOrganization(); + addTextPropertyIfSet( doc, organizationNode, "name", organization.getName() ); + addTextPropertyIfSet( doc, organizationNode, "url", organization.getUrl() ); + depNode.appendChild( organizationNode ); + } + addTextPropertyIfSet( doc, depNode, "scm", extendedInfo.getScm() ); + addTextPropertyIfSet( doc, depNode, "url", extendedInfo.getUrl() ); + } Node licensesNode = doc.createElement( "licenses" ); - if ( dep.getLicenses() == null || dep.getLicenses().size() == 0 ) + if ( CollectionUtils.isEmpty( dep.getLicenses() ) ) { final String comment = hasDownloaderMessages ? " Manually add license elements here: " : " No license information available. "; @@ -164,7 +194,30 @@ else if ( hasDownloaderMessages ) } return depNode; + } + /** + * Lambda interface for {@link #appendChildNodesIfSet(Document, Node, String, Collection, CreateSubNode)}. + * + * @param Type in collection to add as child node entries. + */ + interface CreateSubNode + { + Node createSubNode( Document doc, T t ); + } + + private static void appendChildNodesIfSet( Document doc, Node parentNode, String elementName, + Collection collection, CreateSubNode createSubNode ) + { + if ( !CollectionUtils.isEmpty( collection ) ) + { + Node developersNode = doc.createElement( elementName ); + for ( T t : collection ) + { + developersNode.appendChild( createSubNode.createSubNode( doc, t ) ); + } + parentNode.appendChild( developersNode ); + } } public static Node createLicenseNode( Document doc, ProjectLicense lic, boolean isMatcher ) @@ -209,6 +262,70 @@ public static Node createLicenseNode( Document doc, ProjectLicense lic, boolean return licenseNode; } + private static Node createDeveloperNode( Document doc, Developer developer ) + { + Node developerNode = doc.createElement( "developer" ); + + addTextPropertyIfSet( doc, developerNode, "email", developer.getEmail() ); + addTextPropertyIfSet( doc, developerNode, "name", developer.getName() ); + addTextPropertyIfSet( doc, developerNode, "organization", developer.getOrganization() ); + addTextPropertyIfSet( doc, developerNode, "organizationUrl", developer.getOrganizationUrl() ); + addTextPropertyIfSet( doc, developerNode, "url", developer.getUrl() ); + + return developerNode; + } + + private static Node createInfoFileNode( Document doc, InfoFile infoFile ) + { + Node infoFileNode = doc.createElement( "infoFile" ); + + addCdataIfSet( doc, infoFileNode, "content", infoFile.getContent() ); + appendChildNodesIfSet( doc, infoFileNode, "extractedCopyrightLines", infoFile.getExtractedCopyrightLines(), + ( doc1, line ) -> { + Node devNameNode = doc.createElement( "line" ); + devNameNode.appendChild( doc.createCDATASection( line ) ); + return devNameNode; + } ); + addCdataIfSet( doc, infoFileNode, "fileName", infoFile.getFileName() ); + addTextPropertyIfSet( doc, infoFileNode, "type", infoFile.getType().toString() ); + + return infoFileNode; + } + + private static void addTextPropertyIfSet( Document doc, Node parentNode, String elementName, String property ) + { + addPropertyIfSet( doc, parentNode, elementName, property, () -> doc.createTextNode( property ) ); + } + + private static void addCdataIfSet( Document doc, Node parentNode, String elementName, String property ) + { + addPropertyIfSet( doc, parentNode, elementName, property, + () -> doc.createCDATASection( prepareCdata( property ) ) ); + } + + /** + * Fix string to being written as CDATA under windows, also compatible with *nix systems.
+ * See https://bugs.openjdk.java.net/browse/JDK-8133452 + * + * @param property Property to prepare being written as XML CDATA + * @return The properly prepared string. + */ + private static String prepareCdata( String property ) + { + return property.replace( "\r\n", "\n" ); + } + + private static void addPropertyIfSet( Document doc, Node parentNode, String elementName, + String property, Supplier nodeSupplier ) + { + if ( property != null ) + { + Node devNameNode = doc.createElement( elementName ); + devNameNode.appendChild( nodeSupplier.get() ); + parentNode.appendChild( devNameNode ); + } + } + private static final Pattern WHITESPACE_PATTERN = Pattern.compile( "\\s{2,}" ); static String patternOrText( String value, boolean isMatcher ) diff --git a/src/main/java/org/codehaus/mojo/license/download/LicensedArtifact.java b/src/main/java/org/codehaus/mojo/license/download/LicensedArtifact.java index 6f17dc53c..84821744e 100644 --- a/src/main/java/org/codehaus/mojo/license/download/LicensedArtifact.java +++ b/src/main/java/org/codehaus/mojo/license/download/LicensedArtifact.java @@ -22,9 +22,34 @@ * #L% */ +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; +import org.apache.maven.artifact.Artifact; +import org.apache.maven.model.Developer; +import org.apache.maven.model.Organization; +import org.codehaus.mojo.license.spdx.SpdxLicenseInfo; +import org.codehaus.mojo.license.spdx.SpdxLicenseList; +import org.codehaus.mojo.license.extended.ExtendedInfo; +import org.codehaus.mojo.license.extended.InfoFile; +import org.osgi.framework.Constants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.io.InputStream; import java.util.ArrayList; import java.util.Collections; +import java.util.Enumeration; +import java.util.HashSet; import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.jar.Attributes; +import java.util.jar.Manifest; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; /** * @author Peter Palaga @@ -32,10 +57,11 @@ */ public class LicensedArtifact { + private static final Logger LOG = LoggerFactory.getLogger( LicensedArtifact.class ); - public static Builder builder( String groupId, String artifactId, String version ) + public static Builder builder( Artifact artifact, boolean useNonMavenData ) { - return new Builder( groupId, artifactId, version ); + return new Builder( artifact, useNonMavenData ); } private final String groupId; @@ -48,8 +74,10 @@ public static Builder builder( String groupId, String artifactId, String version private final List errorMessages; + private final ExtendedInfo extendedInfos; + LicensedArtifact( String groupId, String artifactId, String version, List licenses, - List errorMessages ) + List errorMessages, ExtendedInfo extendedInfos ) { super(); this.groupId = groupId; @@ -57,6 +85,7 @@ public static Builder builder( String groupId, String artifactId, String version this.version = version; this.licenses = licenses; this.errorMessages = errorMessages; + this.extendedInfos = extendedInfos; } @Override @@ -139,18 +168,24 @@ public List getErrorMessages() return errorMessages; } + public ExtendedInfo getExtendedInfos() + { + return extendedInfos; + } + /** * A {@link LicensedArtifact} builder. */ public static class Builder { - - public Builder( String groupId, String artifactId, String version ) + public Builder( Artifact artifact, boolean useNonMavenData ) { - super(); - this.groupId = groupId; - this.artifactId = artifactId; - this.version = version; + this.groupId = artifact.getGroupId(); + this.artifactId = artifact.getArtifactId(); + this.version = artifact.getVersion(); + this.extendedInfos = useNonMavenData + ? extraInfosFromArtifact( artifact ) + : null; } private final String groupId; @@ -163,6 +198,8 @@ public Builder( String groupId, String artifactId, String version ) private List errorMessages = new ArrayList<>(); + private final ExtendedInfo extendedInfos; + public Builder errorMessage( String errorMessage ) { this.errorMessages.add( errorMessage ); @@ -181,8 +218,177 @@ public LicensedArtifact build() licenses = null; final List msgs = Collections.unmodifiableList( errorMessages ); errorMessages = null; - return new LicensedArtifact( groupId, artifactId, version, lics, msgs ); + return new LicensedArtifact( groupId, artifactId, version, lics, msgs, extendedInfos ); + } + + private ExtendedInfo extraInfosFromArtifact( Artifact artifact ) + { + if ( artifact.getFile() == null ) + { + LOG.error( "Artifact " + artifact + " has no valid file set" ); + return null; + } + ExtendedInfo result = new ExtendedInfo(); + result.setArtifact( artifact ); + try ( ZipFile zipFile = new ZipFile( artifact.getFile() ) ) + { + Enumeration entries = zipFile.entries(); + while ( entries.hasMoreElements() ) + { + ZipEntry zipEntry = entries.nextElement(); + final String fileName = zipEntry.getName().toLowerCase(); + if ( textFileMatcher( fileName, "notice" ) ) + { + // Should match "NOTICE.txt", "NOTICES.txt"..., + // if someone decides to go slightly against convention. + final InfoFile infoFile = buildInfoFile( zipFile, zipEntry, InfoFile.Type.NOTICE ); + result.getInfoFiles().add( infoFile ); + } + else if ( textFileMatcher( fileName, "license", "licence" ) ) + { + // Match against british and american english writing type of "license" + final InfoFile infoFile = buildInfoFile( zipFile, zipEntry, InfoFile.Type.LICENSE ); + result.getInfoFiles().add( infoFile ); + } + else if ( fileMatchesSpdxId( fileName ) ) + { + final InfoFile infoFile = buildInfoFile( zipFile, zipEntry, InfoFile.Type.SPDX_LICENSE ); + result.getInfoFiles().add( infoFile ); + } + else if ( fileName.equals( "meta-inf/manifest.mf" ) ) + { + try ( InputStream inputStream = zipFile.getInputStream( zipEntry ) ) + { + Manifest manifest = new Manifest( inputStream ); + final Attributes mainAttributes = manifest.getMainAttributes(); + // Fetch Java standard JAR manifest attributes. + final Object implementationVendor = mainAttributes + .get( Attributes.Name.IMPLEMENTATION_VENDOR ); + if ( implementationVendor instanceof String ) + { + result.setImplementationVendor( (String) implementationVendor ); + } + // Fetch OSGI framework JAR manifest attributes. + final String bundleVendor = mainAttributes.getValue( Constants.BUNDLE_VENDOR ); + result.setBundleVendor( bundleVendor ); + final String bundleLicense = mainAttributes.getValue( Constants.BUNDLE_LICENSE ); + result.setBundleLicense( bundleLicense ); + } catch ( IOException e ) + { + LOG.warn( "Error at reading data from jar manifest", e ); + } + } + } + } catch ( IOException e ) + { + LOG.warn( "Can't open zip file", e ); + } + return result; + } + + private InfoFile buildInfoFile( ZipFile zipFile, ZipEntry zipEntry, InfoFile.Type type ) + { + InfoFile infoFile = new InfoFile(); + infoFile.setFileName( zipEntry.getName() ); + infoFile.setType( type ); + Pair contentWithLines = readZipEntryTextLines( zipFile, zipEntry ); + if ( contentWithLines != null ) + { + Set copyrights = scanForCopyrights( contentWithLines.getRight(), "(c)", "copyright" ); + if ( !CollectionUtils.isEmpty( copyrights ) ) + { + infoFile.getExtractedCopyrightLines().addAll( copyrights ); + } + infoFile.setContent( contentWithLines.getLeft() ); + } + return infoFile; + } + + private boolean fileMatchesSpdxId( String fileName ) + { + final SpdxLicenseList spdxList = SpdxLicenseList.getLatest(); + for ( Map.Entry entry : spdxList.getLicenses().entrySet() ) + { + if ( textFileMatcher( fileName, entry.getValue().getLicenseId().toLowerCase() ) ) + { + return true; + } + } + return false; + } + + private boolean textFileMatcher( String fileName, String... matchStrings ) + { + for ( String matchString : matchStrings ) + { + if ( fileName.matches( ".*" + matchString + ".*\\.txt" ) ) + { + return true; + } + } + return false; + } + + /** + * Scans for given copyright matchers in param copyrightMatchers. + * + * @param lines The lines to check + * @param copyrightMatchers Lines containing one of these strings are returned. Arguments must be all lowercase. + * @return The found lines containing copyright claims. + */ + private Set scanForCopyrights( String[] lines, String... copyrightMatchers ) + { + if ( lines == null ) + { + return null; + } + Set result = new HashSet<>(); + for ( String line : lines ) + { + for ( String copyrightMatcher : copyrightMatchers ) + { + final String trimmedLine = line.trim(); + if ( trimmedLine.toLowerCase().contains( copyrightMatcher ) ) + { + result.add( trimmedLine ); + } + } + } + return result; + } + + private Pair readZipEntryTextLines( ZipFile zipFile, ZipEntry zipEntry ) + { + try ( InputStream inputStream = zipFile.getInputStream( zipEntry ) ) + { + byte[] content = IOUtils.readFully( inputStream, (int) zipEntry.getSize() ); + String contentString = new String( content ); + return new ImmutablePair<>( contentString, contentString.split( "\\R+" ) ); + } catch ( IOException e ) + { + LOG.warn( "Can't read zip file entry " + zipEntry, e ); + return null; + } + } + + public void setInceptionYear( String inceptionYear ) + { + this.extendedInfos.setInceptionYear( inceptionYear ); + } + + public void setOrganization( Organization organization ) + { + this.extendedInfos.setOrganization( organization ); + } + + public void setDevelopers( List developers ) + { + this.extendedInfos.setDevelopers( developers ); } - } -} + public void setUrl( String url ) + { + this.extendedInfos.setUrl( url ); + } + } +} \ No newline at end of file diff --git a/src/main/java/org/codehaus/mojo/license/download/LicensedArtifactResolver.java b/src/main/java/org/codehaus/mojo/license/download/LicensedArtifactResolver.java index f5896f9aa..852f48c1c 100644 --- a/src/main/java/org/codehaus/mojo/license/download/LicensedArtifactResolver.java +++ b/src/main/java/org/codehaus/mojo/license/download/LicensedArtifactResolver.java @@ -77,20 +77,19 @@ public class LicensedArtifactResolver * For a given {@code project}, obtain the universe of its dependencies after applying transitivity and filtering * rules given in the {@code configuration} object. Result is given in a map where keys are unique artifact id * - * @param dependencies the project dependencies + * @param artifacts Dependencies * @param configuration the configuration - * @param localRepository local repository used to resolv dependencies - * @param remoteRepositories remote repositories used to resolv dependencies - * @param cache a optional cache where to keep resolved dependencies + * @param remoteRepositories remote repositories used to resolve dependencies + * @param result Map with Key/Value = PluginID/LicensedArtifact * @return the map of resolved dependencies indexed by their unique id. * @see MavenProjectDependenciesConfigurator */ public void loadProjectDependencies( ResolvedProjectDependencies artifacts, MavenProjectDependenciesConfigurator configuration, List remoteRepositories, - Map result ) + Map result, + boolean extendedInfo ) { - final ArtifactFilters artifactFilters = configuration.getArtifactFilters(); final boolean excludeTransitiveDependencies = configuration.isExcludeTransitiveDependencies(); @@ -158,13 +157,19 @@ public void loadProjectDependencies( ResolvedProjectDependencies artifacts, else { // build project - final Builder laBuilder = - LicensedArtifact.builder( artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion() ); + final Builder laBuilder = LicensedArtifact.builder( artifact, extendedInfo ); try { final MavenProject project = mavenProjectBuilder .build( artifact, true, projectBuildingRequest ) .getProject(); + if ( extendedInfo ) + { + laBuilder.setInceptionYear( project.getInceptionYear() ); + laBuilder.setOrganization( project.getOrganization() ); + laBuilder.setDevelopers( project.getDevelopers() ); + laBuilder.setUrl( project.getUrl() ); + } List lics = project.getLicenses(); if ( lics != null ) { diff --git a/src/main/java/org/codehaus/mojo/license/download/ProjectLicenseInfo.java b/src/main/java/org/codehaus/mojo/license/download/ProjectLicenseInfo.java index c66b686f3..49245fc68 100644 --- a/src/main/java/org/codehaus/mojo/license/download/ProjectLicenseInfo.java +++ b/src/main/java/org/codehaus/mojo/license/download/ProjectLicenseInfo.java @@ -23,6 +23,7 @@ */ import org.apache.maven.artifact.Artifact; +import org.codehaus.mojo.license.extended.ExtendedInfo; import java.util.ArrayList; import java.util.List; @@ -51,6 +52,8 @@ public class ProjectLicenseInfo private boolean approved; + private ExtendedInfo extendedInfo; + /** * Default constructor. */ @@ -59,11 +62,12 @@ public ProjectLicenseInfo() } - public ProjectLicenseInfo( String groupId, String artifactId, String version ) + public ProjectLicenseInfo( String groupId, String artifactId, String version, ExtendedInfo extendedInfo ) { this.groupId = groupId; this.artifactId = artifactId; this.version = version; + this.extendedInfo = extendedInfo; } public ProjectLicenseInfo( String groupId, String artifactId, String version, boolean hasMatchLicenses ) @@ -254,4 +258,8 @@ public boolean isApproved() return approved; } + public ExtendedInfo getExtendedInfo() + { + return extendedInfo; + } } diff --git a/src/main/java/org/codehaus/mojo/license/extended/ExtendedInfo.java b/src/main/java/org/codehaus/mojo/license/extended/ExtendedInfo.java new file mode 100644 index 000000000..d56da496e --- /dev/null +++ b/src/main/java/org/codehaus/mojo/license/extended/ExtendedInfo.java @@ -0,0 +1,149 @@ +package org.codehaus.mojo.license.extended; + +/* + * #%L + * License Maven Plugin + * %% + * Copyright (C) 2008 - 2011 Jan-Hendrik Diederich + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * . + * #L% + */ + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.model.Developer; +import org.apache.maven.model.Organization; + +import java.util.ArrayList; +import java.util.List; + +/** + * Class which contains extended licensing information which was found in other files in the JAR, + * not only Mavens pom.xml's. + */ +public class ExtendedInfo +{ + private Artifact artifact; + private List infoFiles = new ArrayList<>(); + private String implementationVendor; + private String bundleVendor; + private String bundleLicense; + + private String inceptionYear; + private Organization organization; + private List developers; + private String scm; + private String url; + + public Artifact getArtifact() + { + return artifact; + } + + public void setArtifact( Artifact artifact ) + { + this.artifact = artifact; + } + + public List getInfoFiles() + { + return infoFiles; + } + + public void setInfoFiles( List infoFiles ) + { + this.infoFiles = infoFiles; + } + + public String getImplementationVendor() + { + return implementationVendor; + } + + public void setImplementationVendor( String implementationVendor ) + { + this.implementationVendor = implementationVendor; + } + + public String getBundleVendor() + { + return bundleVendor; + } + + public void setBundleVendor( String bundleVendor ) + { + this.bundleVendor = bundleVendor; + } + + public String getBundleLicense() + { + return bundleLicense; + } + + public void setBundleLicense( String bundleLicense ) + { + this.bundleLicense = bundleLicense; + } + + public String getInceptionYear() + { + return inceptionYear; + } + + public void setInceptionYear( String inceptionYear ) + { + this.inceptionYear = inceptionYear; + } + + public Organization getOrganization() + { + return organization; + } + + public void setOrganization( Organization organization ) + { + this.organization = organization; + } + + public List getDevelopers() + { + return developers; + } + + public void setDevelopers( List developers ) + { + this.developers = developers; + } + + public String getScm() + { + return scm; + } + + public void setScm( String scm ) + { + this.scm = scm; + } + + public String getUrl() + { + return url; + } + + public void setUrl( String url ) + { + this.url = url; + } +} \ No newline at end of file diff --git a/src/main/java/org/codehaus/mojo/license/extended/InfoFile.java b/src/main/java/org/codehaus/mojo/license/extended/InfoFile.java new file mode 100644 index 000000000..c69765921 --- /dev/null +++ b/src/main/java/org/codehaus/mojo/license/extended/InfoFile.java @@ -0,0 +1,96 @@ +package org.codehaus.mojo.license.extended; + +/* + * #%L + * License Maven Plugin + * %% + * Copyright (C) 2008 - 2011 Jan-Hendrik Diederich + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * . + * #L% + */ + +import java.util.HashSet; +import java.util.Set; + +/** + * Information about a NOTICE or LICENSE file. + */ +public class InfoFile +{ + /** + * The type of the source for the info file. + */ + public enum Type + { + /** + * Generic ...NOTICE....txt file. + */ + NOTICE, + /** + * Generic ...LICENSE...txt file. + */ + LICENSE, + /** + * File name matches a SPDX license id. + */ + SPDX_LICENSE + } + + private String fileName; + private String content; + private Set extractedCopyrightLines = new HashSet<>( ); + private Type type; + + public String getFileName() + { + return fileName; + } + + public void setFileName( String fileName ) + { + this.fileName = fileName; + } + + public String getContent() + { + return content; + } + + public void setContent( String content ) + { + this.content = content; + } + + public Set getExtractedCopyrightLines() + { + return extractedCopyrightLines; + } + + public void setExtractedCopyrightLines( Set extractedCopyrightLines ) + { + this.extractedCopyrightLines = extractedCopyrightLines; + } + + public Type getType() + { + return type; + } + + public void setType( Type type ) + { + this.type = type; + } +} \ No newline at end of file diff --git a/src/test/java/org/codehaus/mojo/license/download/LicenseMatchersTest.java b/src/test/java/org/codehaus/mojo/license/download/LicenseMatchersTest.java index b08ad9d44..e0f38ac1d 100644 --- a/src/test/java/org/codehaus/mojo/license/download/LicenseMatchersTest.java +++ b/src/test/java/org/codehaus/mojo/license/download/LicenseMatchersTest.java @@ -76,7 +76,7 @@ public void licenseMatches() @Test public void replaceMatchesLegacy() { - final ProjectLicenseInfo dep = new ProjectLicenseInfo( "myGroup", "myArtifact", "1a2.3" ); + final ProjectLicenseInfo dep = new ProjectLicenseInfo( "myGroup", "myArtifact", "1a2.3", null ); final ProjectLicenseInfo pli1 = new ProjectLicenseInfo( "myGroup", "myArtifact", "1.2.3", false ); final ProjectLicense lic2 = new ProjectLicense("lic2", "http://other.org", null, "other comment", null); pli1.addLicense( lic2 ); @@ -98,7 +98,7 @@ public void replaceMatchesLegacy() public void replaceMatches() { - final ProjectLicenseInfo dep = new ProjectLicenseInfo( "myGroup", "myArtifact", "1.2.3" ); + final ProjectLicenseInfo dep = new ProjectLicenseInfo( "myGroup", "myArtifact", "1.2.3", null ); final DependencyMatcher m0 = DependencyMatcher.of( new ProjectLicenseInfo( "myGroup", "myArtifact", null, true ) ); Assert.assertTrue( m0.matches( dep ) ); @@ -134,7 +134,7 @@ public void replaceMatches() dep.addLicense( new ProjectLicense( "lic1", "http://some.org", null, "comment", null ) ); Assert.assertFalse( m1.matches( dep ) ); - final ProjectLicenseInfo dep11 = new ProjectLicenseInfo( "myGroup", "myArtifact", "1.2.3" ); + final ProjectLicenseInfo dep11 = new ProjectLicenseInfo( "myGroup", "myArtifact", "1.2.3", null ); dep11.addLicense( new ProjectLicense( "lic1", "http://some.org", null, "comment", null ) ); final List oldLics11 = dep.cloneLicenses(); final ProjectLicenseInfo pli11 = new ProjectLicenseInfo( "myGroup", "myArtifact", "1\\.2\\.3", true ); diff --git a/src/test/java/org/codehaus/mojo/license/download/LicenseSummaryTest.java b/src/test/java/org/codehaus/mojo/license/download/LicenseSummaryTest.java index 058e922f2..32a684849 100644 --- a/src/test/java/org/codehaus/mojo/license/download/LicenseSummaryTest.java +++ b/src/test/java/org/codehaus/mojo/license/download/LicenseSummaryTest.java @@ -70,8 +70,8 @@ public void testWriteReadLicenseSummary() TransformerException { List licSummary = new ArrayList<>(); - ProjectLicenseInfo dep1 = new ProjectLicenseInfo( "org.test", "test1", "1.0" ); - ProjectLicenseInfo dep2 = new ProjectLicenseInfo( "org.test", "test2", "2.0" ); + ProjectLicenseInfo dep1 = new ProjectLicenseInfo( "org.test", "test1", "1.0", null ); + ProjectLicenseInfo dep2 = new ProjectLicenseInfo( "org.test", "test2", "2.0", null ); ProjectLicense lic = new ProjectLicense(); lic.setName( "lgpl" ); From 5c78f01815752576457a6f97b04a28e4dacba364 Mon Sep 17 00:00:00 2001 From: Jan-Hendrik Diederich Date: Fri, 15 Nov 2019 17:40:34 +0100 Subject: [PATCH 04/34] Added output as Excel file in OOXML format. --- pom.xml | 9 + .../license/AbstractDownloadLicensesMojo.java | 26 + .../download/LicenseSummaryWriter.java | 9 +- .../license/download/LicensedArtifact.java | 6 + .../download/LicensedArtifactResolver.java | 1 + .../mojo/license/extended/ExtendedInfo.java | 9 +- .../mojo/license/extended/InfoFile.java | 4 +- .../extended/spreadsheet/ExcelFileWriter.java | 507 ++++++++++++++++++ 8 files changed, 564 insertions(+), 7 deletions(-) create mode 100644 src/main/java/org/codehaus/mojo/license/extended/spreadsheet/ExcelFileWriter.java diff --git a/pom.xml b/pom.xml index dca3458a5..3fe412674 100644 --- a/pom.xml +++ b/pom.xml @@ -319,11 +319,20 @@ junit test + + org.osgi org.osgi.core 6.0.0 + + + + org.apache.poi + poi-ooxml + 4.1.1 + diff --git a/src/main/java/org/codehaus/mojo/license/AbstractDownloadLicensesMojo.java b/src/main/java/org/codehaus/mojo/license/AbstractDownloadLicensesMojo.java index de46ad117..9e8ffd7a6 100644 --- a/src/main/java/org/codehaus/mojo/license/AbstractDownloadLicensesMojo.java +++ b/src/main/java/org/codehaus/mojo/license/AbstractDownloadLicensesMojo.java @@ -63,6 +63,7 @@ import org.codehaus.mojo.license.download.ProjectLicense; import org.codehaus.mojo.license.download.ProjectLicenseInfo; import org.codehaus.mojo.license.download.UrlReplacements; +import org.codehaus.mojo.license.extended.spreadsheet.ExcelFileWriter; import org.codehaus.mojo.license.spdx.SpdxLicenseList; import org.codehaus.mojo.license.spdx.SpdxLicenseList.Attachments.ContentSanitizer; import org.codehaus.mojo.license.utils.FileUtil; @@ -662,6 +663,27 @@ public abstract class AbstractDownloadLicensesMojo @Parameter( property = "license.useDefaultContentSanitizers", defaultValue = "false" ) private boolean useDefaultContentSanitizers; + /** + * Write Excel file (XLSX) for goal license:aggregate-download-licenses. + * + * @since 2.1 + */ + @Parameter( property = "license.writeExcelFile", defaultValue = "false" ) + private boolean writeExcelFile; + + /** + * The excel output file used if {@link #writeExcelFile} is true, + * containing a mapping between each dependency and it's license information. + * With extended information, if available. + * + * @see AbstractDownloadLicensesMojo#writeExcelFile + * @see AggregateDownloadLicensesMojo#extendedInfo + * @since 2.1 + */ + @Parameter( property = "licensesExcelOutputFile", + defaultValue = "${project.build.directory}/generated-resources/licenses.xlsx" ) + protected File licensesExcelOutputFile; + // ---------------------------------------------------------------------- // Plexus Components // ---------------------------------------------------------------------- @@ -812,6 +834,10 @@ public void execute() List depProjectLicensesWithErrors = filterErrors( depProjectLicenses ); writeLicenseSummary( depProjectLicenses, licensesOutputFile, writeVersions ); + if ( writeExcelFile ) + { + ExcelFileWriter.write( depProjectLicenses, licensesExcelOutputFile ); + } if ( !CollectionUtils.isEmpty( depProjectLicensesWithErrors ) ) { writeLicenseSummary( depProjectLicensesWithErrors, licensesErrorsFile, writeVersions ); diff --git a/src/main/java/org/codehaus/mojo/license/download/LicenseSummaryWriter.java b/src/main/java/org/codehaus/mojo/license/download/LicenseSummaryWriter.java index af8c763ac..01a4dc3f2 100644 --- a/src/main/java/org/codehaus/mojo/license/download/LicenseSummaryWriter.java +++ b/src/main/java/org/codehaus/mojo/license/download/LicenseSummaryWriter.java @@ -25,6 +25,7 @@ import org.apache.commons.collections.CollectionUtils; import org.apache.maven.model.Developer; import org.apache.maven.model.Organization; +import org.apache.maven.model.Scm; import org.codehaus.mojo.license.Eol; import org.codehaus.mojo.license.extended.ExtendedInfo; import org.codehaus.mojo.license.extended.InfoFile; @@ -47,6 +48,7 @@ import java.nio.file.Files; import java.util.Collection; import java.util.List; +import java.util.Optional; import java.util.function.Supplier; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -145,6 +147,7 @@ else if ( hasDownloaderMessages ) appendChildNodesIfSet( doc, depNode, "developers", extendedInfo.getDevelopers(), ( doc1, developer ) -> createDeveloperNode( doc, developer ) ); addCdataIfSet( doc, depNode, "implementationVendor", extendedInfo.getImplementationVendor() ); + addTextPropertyIfSet( doc, depNode, "inceptionYear", extendedInfo.getInceptionYear() ); appendChildNodesIfSet( doc, depNode, "infoFiles", extendedInfo.getInfoFiles(), ( doc1, infoFile ) -> createInfoFileNode( doc, infoFile ) ); if ( extendedInfo.getOrganization() != null @@ -157,7 +160,9 @@ else if ( hasDownloaderMessages ) addTextPropertyIfSet( doc, organizationNode, "url", organization.getUrl() ); depNode.appendChild( organizationNode ); } - addTextPropertyIfSet( doc, depNode, "scm", extendedInfo.getScm() ); + addTextPropertyIfSet( doc, depNode, "scm", Optional.ofNullable( extendedInfo.getScm() ) + .map( Scm::getUrl ) + .orElse( null ) ); addTextPropertyIfSet( doc, depNode, "url", extendedInfo.getUrl() ); } @@ -266,11 +271,13 @@ private static Node createDeveloperNode( Document doc, Developer developer ) { Node developerNode = doc.createElement( "developer" ); + addTextPropertyIfSet( doc, developerNode, "id", developer.getId() ); addTextPropertyIfSet( doc, developerNode, "email", developer.getEmail() ); addTextPropertyIfSet( doc, developerNode, "name", developer.getName() ); addTextPropertyIfSet( doc, developerNode, "organization", developer.getOrganization() ); addTextPropertyIfSet( doc, developerNode, "organizationUrl", developer.getOrganizationUrl() ); addTextPropertyIfSet( doc, developerNode, "url", developer.getUrl() ); + addTextPropertyIfSet( doc, developerNode, "timezone", developer.getTimezone() ); return developerNode; } diff --git a/src/main/java/org/codehaus/mojo/license/download/LicensedArtifact.java b/src/main/java/org/codehaus/mojo/license/download/LicensedArtifact.java index 84821744e..896868ac6 100644 --- a/src/main/java/org/codehaus/mojo/license/download/LicensedArtifact.java +++ b/src/main/java/org/codehaus/mojo/license/download/LicensedArtifact.java @@ -29,6 +29,7 @@ import org.apache.maven.artifact.Artifact; import org.apache.maven.model.Developer; import org.apache.maven.model.Organization; +import org.apache.maven.model.Scm; import org.codehaus.mojo.license.spdx.SpdxLicenseInfo; import org.codehaus.mojo.license.spdx.SpdxLicenseList; import org.codehaus.mojo.license.extended.ExtendedInfo; @@ -390,5 +391,10 @@ public void setUrl( String url ) { this.extendedInfos.setUrl( url ); } + + public void setScm( Scm scm ) + { + this.extendedInfos.setScm( scm ); + } } } \ No newline at end of file diff --git a/src/main/java/org/codehaus/mojo/license/download/LicensedArtifactResolver.java b/src/main/java/org/codehaus/mojo/license/download/LicensedArtifactResolver.java index 852f48c1c..66850bfd7 100644 --- a/src/main/java/org/codehaus/mojo/license/download/LicensedArtifactResolver.java +++ b/src/main/java/org/codehaus/mojo/license/download/LicensedArtifactResolver.java @@ -169,6 +169,7 @@ public void loadProjectDependencies( ResolvedProjectDependencies artifacts, laBuilder.setOrganization( project.getOrganization() ); laBuilder.setDevelopers( project.getDevelopers() ); laBuilder.setUrl( project.getUrl() ); + laBuilder.setScm( project.getScm() ); } List lics = project.getLicenses(); if ( lics != null ) diff --git a/src/main/java/org/codehaus/mojo/license/extended/ExtendedInfo.java b/src/main/java/org/codehaus/mojo/license/extended/ExtendedInfo.java index d56da496e..1349e5321 100644 --- a/src/main/java/org/codehaus/mojo/license/extended/ExtendedInfo.java +++ b/src/main/java/org/codehaus/mojo/license/extended/ExtendedInfo.java @@ -4,7 +4,7 @@ * #%L * License Maven Plugin * %% - * Copyright (C) 2008 - 2011 Jan-Hendrik Diederich + * Copyright (C) 2019 Jan-Hendrik Diederich * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as @@ -25,6 +25,7 @@ import org.apache.maven.artifact.Artifact; import org.apache.maven.model.Developer; import org.apache.maven.model.Organization; +import org.apache.maven.model.Scm; import java.util.ArrayList; import java.util.List; @@ -44,7 +45,7 @@ public class ExtendedInfo private String inceptionYear; private Organization organization; private List developers; - private String scm; + private Scm scm; private String url; public Artifact getArtifact() @@ -127,12 +128,12 @@ public void setDevelopers( List developers ) this.developers = developers; } - public String getScm() + public Scm getScm() { return scm; } - public void setScm( String scm ) + public void setScm( Scm scm ) { this.scm = scm; } diff --git a/src/main/java/org/codehaus/mojo/license/extended/InfoFile.java b/src/main/java/org/codehaus/mojo/license/extended/InfoFile.java index c69765921..4477948a6 100644 --- a/src/main/java/org/codehaus/mojo/license/extended/InfoFile.java +++ b/src/main/java/org/codehaus/mojo/license/extended/InfoFile.java @@ -4,7 +4,7 @@ * #%L * License Maven Plugin * %% - * Copyright (C) 2008 - 2011 Jan-Hendrik Diederich + * Copyright (C) 2019 Jan-Hendrik Diederich * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as @@ -51,7 +51,7 @@ public enum Type private String fileName; private String content; - private Set extractedCopyrightLines = new HashSet<>( ); + private Set extractedCopyrightLines = new HashSet<>(); private Type type; public String getFileName() diff --git a/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/ExcelFileWriter.java b/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/ExcelFileWriter.java new file mode 100644 index 000000000..c0f981fa0 --- /dev/null +++ b/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/ExcelFileWriter.java @@ -0,0 +1,507 @@ +package org.codehaus.mojo.license.extended.spreadsheet; + +/* + * #%L + * License Maven Plugin + * %% + * Copyright (C) 2019 Jan-Hendrik Diederich + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * . + * #L% + */ + +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; +import org.apache.maven.model.Developer; +import org.apache.maven.model.Organization; +import org.apache.maven.model.Scm; +import org.apache.poi.common.usermodel.HyperlinkType; +import org.apache.poi.ss.usermodel.BorderStyle; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.CellType; +import org.apache.poi.ss.usermodel.Font; +import org.apache.poi.ss.usermodel.Hyperlink; +import org.apache.poi.ss.usermodel.IndexedColors; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.ss.util.CellRangeAddress; +import org.apache.poi.ss.util.WorkbookUtil; +import org.apache.poi.xssf.usermodel.XSSFFont; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.codehaus.mojo.license.download.ProjectLicense; +import org.codehaus.mojo.license.download.ProjectLicenseInfo; +import org.codehaus.mojo.license.extended.ExtendedInfo; +import org.codehaus.mojo.license.extended.InfoFile; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.function.BiConsumer; + +/** + * Writes project license infos into Excel file. + */ +public class ExcelFileWriter +{ + private static final Logger LOG = LoggerFactory.getLogger( ExcelFileWriter.class ); + + // Columns values for Maven data, including separator gaps for data grouping. + private static final int PLUGIN_ID_COLUMNS = 3; + // "Start" column are the actual start columns, they are inclusive. + // "End" columns point just one column behind the last one, it's the exclusive column index. + private static final int LICENSES_START_COLUMN = PLUGIN_ID_COLUMNS + 1, LICENSES_COLUMNS = 5, + LICENSES_END_COLUMN = LICENSES_START_COLUMN + LICENSES_COLUMNS; + private static final int DEVELOPERS_START_COLUMN = LICENSES_END_COLUMN + 1, DEVELOPER_COLUMNS = 7, + DEVELOPERS_END_COLUMN = DEVELOPERS_START_COLUMN + DEVELOPER_COLUMNS; + private static final int MISC_START_COLUMN = DEVELOPERS_END_COLUMN + 1, MISC_COLUMNS = 4, + MISC_END_COLUMN = MISC_START_COLUMN + MISC_COLUMNS; + + private static final int MAVEN_DATA_COLUMNS = PLUGIN_ID_COLUMNS + LICENSES_COLUMNS + + DEVELOPER_COLUMNS + MISC_COLUMNS, + MAVEN_COLUMN_GROUPING_GAPS = 3; + private static final int MAVEN_COLUMNS = MAVEN_DATA_COLUMNS + MAVEN_COLUMN_GROUPING_GAPS; + + // Columns values for JAR data, including separator gaps for data grouping. + private static final int INFO_FILES_GAPS = 2, MANIFEST_GAPS = 1; + private static final int MANIFEST_START_COLUMN = MAVEN_COLUMNS + 1, MANIFEST_COLUMNS = 3, + MANIFEST_END_COLUMN = MANIFEST_START_COLUMN + MANIFEST_COLUMNS; + private static final int INFO_NOTICES_START_COLUMN = MANIFEST_END_COLUMN + 1, INFO_NOTICES_COLUMNS = 3, + INFO_NOTICES_END_COLUMN = INFO_NOTICES_START_COLUMN + INFO_NOTICES_COLUMNS; + private static final int INFO_LICENSES_START_COLUMN = INFO_NOTICES_END_COLUMN + 1, INFO_LICENSES_COLUMNS = 3, + INFO_LICENSES_END_COLUMN = INFO_LICENSES_START_COLUMN + INFO_LICENSES_COLUMNS; + private static final int INFO_SPDX_START_COLUMN = INFO_LICENSES_END_COLUMN + 1, INFO_SPDX_COLUMNS = 3, + INFO_SPDX_END_COLUMN = INFO_SPDX_START_COLUMN + INFO_SPDX_COLUMNS; + private static final int EXTENDED_INFO_COLUMNS = MANIFEST_COLUMNS + + INFO_NOTICES_COLUMNS + INFO_LICENSES_COLUMNS + INFO_SPDX_COLUMNS + + INFO_FILES_GAPS + MANIFEST_GAPS; + + // Width of gap columns + private static final int GAP_WIDTH = 20; + + /** + * Writes list of projects into excel file. + * + * @param projectLicenseInfos Project license infos to write. + * @param licensesExcelOutputFile Excel output file in latest format (OOXML). + */ + public static void write( List projectLicenseInfos, final File licensesExcelOutputFile ) + { + if ( CollectionUtils.isEmpty( projectLicenseInfos ) ) + { + LOG.debug( "Nothing to write to excel, no project data." ); + return; + } + + Workbook wb = new XSSFWorkbook(); + Sheet sheet = wb.createSheet( WorkbookUtil.createSafeSheetName( "License information" ) ); + + createHeader( projectLicenseInfos, wb, sheet ); + + writeData( projectLicenseInfos, wb, sheet ); + + try ( OutputStream fileOut = new FileOutputStream( licensesExcelOutputFile ) ) + { + wb.write( fileOut ); + } catch ( IOException e ) + { + LOG.error( "Error on storing Excel file with license and other information", e ); + } + } + + private static void writeData( List projectLicenseInfos, Workbook wb, Sheet sheet ) + { + final int firstRowIndex = 3; + int currentRowIndex = firstRowIndex; + final Map rows = new HashMap<>(); + boolean hasExtendedInfo = false; + for ( ProjectLicenseInfo projectInfo : projectLicenseInfos ) + { + int extraRows = 0; + Row currentRow = sheet.createRow( currentRowIndex ); + rows.put( currentRowIndex, currentRow ); + // Plugin ID + createCellsInRow( currentRow, 0, + projectInfo.getGroupId(), projectInfo.getArtifactId(), projectInfo.getVersion() ); + // Licenses + extraRows = addCollection( sheet, rows, currentRowIndex, extraRows, + projectInfo.getLicenses(), + ( Row licenseRow, ProjectLicense license ) -> { + Cell[] licenses = createCellsInRow( licenseRow, LICENSES_START_COLUMN, + license.getName(), license.getUrl(), + license.getDistribution(), license.getComments(), + license.getFile() ); + addHyperlinkIfExists( wb, licenses[ 1 ], HyperlinkType.URL ); + } ); + + final ExtendedInfo extendedInfo = projectInfo.getExtendedInfo(); + if ( extendedInfo != null ) + { + hasExtendedInfo = true; + // Developers + extraRows = addCollection( sheet, rows, currentRowIndex, extraRows, + extendedInfo.getDevelopers(), + ( Row developerRow, Developer developer ) -> { + Cell[] licenses = createCellsInRow( developerRow, DEVELOPERS_START_COLUMN, + developer.getId(), developer.getEmail(), + developer.getName(), + developer.getOrganization(), developer.getOrganizationUrl(), + developer.getUrl(), developer.getTimezone() ); + addHyperlinkIfExists( wb, licenses[ 1 ], HyperlinkType.EMAIL ); + addHyperlinkIfExists( wb, licenses[ 4 ], HyperlinkType.URL ); + addHyperlinkIfExists( wb, licenses[ 5 ], HyperlinkType.URL ); + } ); + // Miscellaneous + Cell[] miscCells = createCellsInRow( currentRow, MISC_START_COLUMN, + extendedInfo.getInceptionYear(), + Optional.ofNullable( extendedInfo.getOrganization() ) + .map( Organization::getName ) + .orElse( null ), + Optional.ofNullable( extendedInfo.getScm() ) + .map( Scm::getUrl ) + .orElse( null ), + extendedInfo.getUrl() ); + addHyperlinkIfExists( wb, miscCells[ 2 ], HyperlinkType.URL ); + addHyperlinkIfExists( wb, miscCells[ 3 ], HyperlinkType.URL ); + + // MANIFEST.MF + createCellsInRow( currentRow, MANIFEST_START_COLUMN, + extendedInfo.getBundleLicense(), extendedInfo.getBundleVendor(), + extendedInfo.getImplementationVendor() ); + + // Info files + if ( !CollectionUtils.isEmpty( extendedInfo.getInfoFiles() ) ) + { + // Sort all info files by type into 3 different lists, each list for each of the 3 types. + List notices = new ArrayList<>(); + List licenses = new ArrayList<>(); + List spdxs = new ArrayList<>(); + extendedInfo.getInfoFiles().forEach( infoFile -> { + switch ( infoFile.getType() ) + { + case LICENSE: + licenses.add( infoFile ); + break; + case NOTICE: + notices.add( infoFile ); + break; + case SPDX_LICENSE: + spdxs.add( infoFile ); + break; + default: + break; + } + } + ); + // InfoFile notices text file + extraRows = addInfoFileList( sheet, rows, currentRowIndex, extraRows, + INFO_NOTICES_START_COLUMN, notices ); + // InfoFile licenses text file + extraRows = addInfoFileList( sheet, rows, currentRowIndex, extraRows, + INFO_LICENSES_START_COLUMN, licenses ); + // InfoFile spdx licenses text file + extraRows = addInfoFileList( sheet, rows, currentRowIndex, extraRows, + INFO_SPDX_START_COLUMN, spdxs ); + } + } + currentRowIndex += extraRows + 1; + } + + autosizeColumns( sheet, hasExtendedInfo ); + } + + private static void createHeader( List projectLicenseInfos, Workbook wb, Sheet sheet ) + { + int columns = MAVEN_COLUMNS; + boolean hasExtendedInfo = false; + for ( ProjectLicenseInfo projectLicenseInfo : projectLicenseInfos ) + { + if ( projectLicenseInfo.getExtendedInfo() != null ) + { + columns += EXTENDED_INFO_COLUMNS; + hasExtendedInfo = true; + break; + } + } + + // Create header style + CellStyle headerCellStyle = wb.createCellStyle(); + headerCellStyle.setFillBackgroundColor( IndexedColors.GREY_25_PERCENT.getIndex() ); + Font headerFont = new XSSFFont(); + headerFont.setBold( true ); + headerCellStyle.setFont( headerFont ); + setBorderStyle( headerCellStyle, BorderStyle.MEDIUM ); + + // Create 1st header row. The Maven/JAR header row + Row mavenJarRow = sheet.createRow( 0 ); + + // Create Maven header cell + createMergedCellsInRow( sheet, 0, MAVEN_COLUMNS, headerCellStyle, mavenJarRow, "Maven information", 0 ); + + if ( hasExtendedInfo ) + { + // Create JAR header cell + Cell jarHeaderCell = mavenJarRow.createCell( 0 ); + jarHeaderCell.setCellValue( "JAR Content" ); + jarHeaderCell.setCellStyle( headerCellStyle ); + createCellsInRow( MAVEN_COLUMNS, columns, mavenJarRow ); + CellRangeAddress jarHeaderAddress = new CellRangeAddress( 0, 0, MAVEN_COLUMNS, columns - 1 ); + sheet.addMergedRegion( jarHeaderAddress ); + } + + // Create 2nd header row + Row secondHeaderRow = sheet.createRow( 1 ); + + // Create Maven "Plugin ID" header + createMergedCellsInRow( sheet, 0, PLUGIN_ID_COLUMNS, headerCellStyle, secondHeaderRow, "Plugin ID", 1 ); + + // Create Maven "Licenses" header + createMergedCellsInRow( sheet, LICENSES_START_COLUMN, LICENSES_END_COLUMN, headerCellStyle, secondHeaderRow, + "Licenses", 1 ); + + // Gap "Plugin ID" <-> "Licenses". + sheet.setColumnWidth( PLUGIN_ID_COLUMNS, GAP_WIDTH ); + + // Create Maven "Developers" header + createMergedCellsInRow( sheet, DEVELOPERS_START_COLUMN, DEVELOPERS_END_COLUMN, headerCellStyle, + secondHeaderRow, + "Developers", 1 ); + + // Gap "Licenses" <-> "Developers". + sheet.setColumnWidth( LICENSES_END_COLUMN, GAP_WIDTH ); + + // Create Maven "Miscellaneous" header + createMergedCellsInRow( sheet, MISC_START_COLUMN, MISC_END_COLUMN, headerCellStyle, + secondHeaderRow, + "Miscellaneous", 1 ); + + // Gap "Developers" <-> "Miscellaneous". + sheet.setColumnWidth( DEVELOPERS_END_COLUMN, GAP_WIDTH ); + + if ( hasExtendedInfo ) + { + createMergedCellsInRow( sheet, MANIFEST_START_COLUMN, MANIFEST_END_COLUMN, headerCellStyle, + secondHeaderRow, + "MANIFEST.MF", 1 ); + + // Gap "Miscellaneous" <-> "MANIFEST.MF". + sheet.setColumnWidth( DEVELOPERS_END_COLUMN, GAP_WIDTH ); + + createMergedCellsInRow( sheet, INFO_NOTICES_START_COLUMN, INFO_NOTICES_END_COLUMN, headerCellStyle, + secondHeaderRow, + "Notices text files", 1 ); + + // Gap "MANIFEST.MF" <-> "Notice text files". + sheet.setColumnWidth( MANIFEST_END_COLUMN, GAP_WIDTH ); + + createMergedCellsInRow( sheet, INFO_LICENSES_START_COLUMN, INFO_LICENSES_END_COLUMN, headerCellStyle, + secondHeaderRow, + "License text files", 1 ); + + // Gap "Notice text files" <-> "License text files". + sheet.setColumnWidth( INFO_LICENSES_END_COLUMN, GAP_WIDTH ); + + createMergedCellsInRow( sheet, INFO_SPDX_START_COLUMN, INFO_SPDX_END_COLUMN, headerCellStyle, + secondHeaderRow, + "SPDX license id matched", 1 ); + } +// sheet.setColumnGroupCollapsed(); + + // Create 3rd header row + Row thirdHeaderRow = sheet.createRow( 2 ); + + // Plugin ID + createCellsInRow( thirdHeaderRow, 0, headerCellStyle, "Group ID", "Artifact ID", "Version" ); + // Licenses + createCellsInRow( thirdHeaderRow, LICENSES_START_COLUMN, headerCellStyle, + "Name", "URL", "Distribution", "Comments", "File" ); + // Developers + createCellsInRow( thirdHeaderRow, DEVELOPERS_START_COLUMN, headerCellStyle, + "Id", "Email", "Name", "Organization", "Organization URL", "URL", "Timezone" ); + // Miscellaneous + createCellsInRow( thirdHeaderRow, MISC_START_COLUMN, headerCellStyle, + "Inception Year", "Organization", "SCM", "URL" ); + + if ( hasExtendedInfo ) + { + // MANIFEST.MF + createCellsInRow( thirdHeaderRow, MANIFEST_START_COLUMN, headerCellStyle, + "Bundle license", "Bundle vendor", "Implementation vendor" ); + // 3 InfoFile groups: Notices, Licenses and SPDX-Licenses. + createInfoFileCellsInRow( thirdHeaderRow, headerCellStyle, + INFO_NOTICES_START_COLUMN, INFO_LICENSES_START_COLUMN, INFO_SPDX_START_COLUMN ); + } + } + + private static void autosizeColumns( Sheet sheet, boolean hasExtendedInfo ) + { + autosizeColumns( sheet, + new ImmutablePair<>( 0, PLUGIN_ID_COLUMNS ), + new ImmutablePair<>( LICENSES_START_COLUMN, LICENSES_END_COLUMN ), + new ImmutablePair<>( DEVELOPERS_START_COLUMN, DEVELOPERS_END_COLUMN - 1 ), + new ImmutablePair<>( MISC_START_COLUMN + 1, MISC_END_COLUMN ) + ); + if ( hasExtendedInfo ) + { + autosizeColumns( sheet, + new ImmutablePair<>( MANIFEST_START_COLUMN, MANIFEST_END_COLUMN ), + new ImmutablePair<>( INFO_NOTICES_START_COLUMN + 2, INFO_NOTICES_END_COLUMN ), + new ImmutablePair<>( INFO_LICENSES_START_COLUMN + 2, INFO_LICENSES_END_COLUMN ), + new ImmutablePair<>( INFO_SPDX_START_COLUMN + 2, INFO_SPDX_END_COLUMN ) + ); + } + } + + private static void autosizeColumns( Sheet sheet, ImmutablePair... ranges ) + { + for ( ImmutablePair pair : ranges ) + { + for ( int i = pair.left; i < pair.right; i++ ) + { + sheet.autoSizeColumn( i ); + } + } + } + + private static int addInfoFileList( Sheet sheet, Map rows, int currentRowIndex, int extraRows, + int startColumn, List infoFiles ) + { + return addCollection( sheet, rows, currentRowIndex, extraRows, infoFiles, + ( Row infoFileRow, InfoFile infoFile ) -> { + final String copyrightLines = Optional + .ofNullable( infoFile.getExtractedCopyrightLines() ) + .map( strings -> String.join( "§", strings ) ) + .orElse( null ); + createCellsInRow( infoFileRow, startColumn, + infoFile.getContent(), copyrightLines, + infoFile.getFileName() ); + } ); + } + + private static int addCollection( Sheet sheet, Map rows, int currentRowIndex, int extraRows, + List list, BiConsumer biConsumer ) + { + if ( !CollectionUtils.isEmpty( list ) ) + { + for ( int i = 0; i < list.size(); i++ ) + { + T license = list.get( i ); + Integer index = currentRowIndex + i; + Row row = rows.get( index ); + if ( row == null ) + { + row = sheet.createRow( index ); + rows.put( index, row ); + extraRows++; + } + biConsumer.accept( row, license ); + } + } + return extraRows; + } + + private static void addHyperlinkIfExists( Workbook workbook, Cell cell, HyperlinkType hyperlinkType ) + { + if ( !StringUtils.isEmpty( cell.getStringCellValue() ) ) + { + Hyperlink hyperlink = workbook.getCreationHelper().createHyperlink( hyperlinkType ); + try + { + hyperlink.setAddress( cell.getStringCellValue() ); + cell.setHyperlink( hyperlink ); + } catch ( IllegalArgumentException e ) + { + LOG.debug( "Can't set Hyperlink for cell value " + cell.getStringCellValue() + + " it gets rejected as URI", e ); + } + } + } + + private static Cell[] createCellsInRow( Row row, int startColumn, String... names ) + { + Cell[] result = new Cell[ names.length ]; + for ( int i = 0; i < names.length; i++ ) + { + Cell cell = row.createCell( startColumn + i, CellType.STRING ); + cell.setCellValue( names[ i ] ); + result[ i ] = cell; + } + return result; + } + + /** + * Create cells for InfoFile content. + * + * @param row The row to insert cells into. + * @param cellStyle The cell style of the created cell. + * @param startPositions The start position of the 3 columns for an InfoFile. + */ + private static void createInfoFileCellsInRow( Row row, CellStyle cellStyle, int... startPositions ) + { + for ( int startPosition : startPositions ) + { + createCellsInRow( row, startPosition, cellStyle, "Content", "Extracted copyright lines", "File" ); + } + } + + private static void createCellsInRow( Row row, int startColumn, CellStyle cellStyle, String... names ) + { + for ( int i = 0; i < names.length; i++ ) + { + Cell cell = row.createCell( startColumn + i ); + cell.setCellStyle( cellStyle ); + cell.setCellValue( names[ i ] ); + } + } + + private static void createMergedCellsInRow( Sheet sheet, int startColumn, int endColumn, CellStyle cellStyle, + Row row, String cellValue, int rowIndex ) + { + Cell licensesCell = row.createCell( startColumn ); + licensesCell.setCellValue( cellValue ); + licensesCell.setCellStyle( cellStyle ); + createCellsInRow( startColumn + 1, endColumn, row ); + CellRangeAddress licensesHeaderAddress = new CellRangeAddress( rowIndex, rowIndex, startColumn, endColumn - 1 ); + sheet.addMergedRegion( licensesHeaderAddress ); + sheet.groupColumn( startColumn, endColumn - 1 ); + } + + private static void createCellsInRow( int startColumn, int exclusiveEndColumn, Row inRow ) + { + for ( int i = startColumn; i < exclusiveEndColumn; i++ ) + { + inRow.createCell( i ); + } + } + + private static void setBorderStyle( CellStyle cellStyle, BorderStyle borderStyle ) + { + cellStyle.setBorderLeft( borderStyle ); + cellStyle.setBorderTop( borderStyle ); + cellStyle.setBorderRight( borderStyle ); + cellStyle.setBorderBottom( borderStyle ); + } +} \ No newline at end of file From ff1f8f36a7c80540a272b4fe28a3272e1eb822b1 Mon Sep 17 00:00:00 2001 From: Jan-Hendrik Diederich Date: Sun, 17 Nov 2019 18:36:57 +0100 Subject: [PATCH 05/34] Cleaned up license aggregation report Excel file --- .../license/AbstractDownloadLicensesMojo.java | 105 +++-- .../codehaus/mojo/license/download/Cache.java | 27 +- .../license/download/LicenseDownloader.java | 88 ++++- .../download/LicenseSummaryWriter.java | 1 + .../license/download/LicensedArtifact.java | 50 ++- .../download/LicensedArtifactResolver.java | 1 + .../mojo/license/extended/ExtendedInfo.java | 11 + .../mojo/license/extended/InfoFile.java | 10 + .../extended/spreadsheet/ExcelFileWriter.java | 374 +++++++++++------- 9 files changed, 491 insertions(+), 176 deletions(-) diff --git a/src/main/java/org/codehaus/mojo/license/AbstractDownloadLicensesMojo.java b/src/main/java/org/codehaus/mojo/license/AbstractDownloadLicensesMojo.java index 9e8ffd7a6..575dabe1b 100644 --- a/src/main/java/org/codehaus/mojo/license/AbstractDownloadLicensesMojo.java +++ b/src/main/java/org/codehaus/mojo/license/AbstractDownloadLicensesMojo.java @@ -22,25 +22,6 @@ * #L% */ -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Set; -import java.util.TreeMap; -import java.util.regex.Pattern; - import org.apache.commons.collections.CollectionUtils; import org.apache.commons.io.FileUtils; import org.apache.commons.lang.StringEscapeUtils; @@ -63,6 +44,7 @@ import org.codehaus.mojo.license.download.ProjectLicense; import org.codehaus.mojo.license.download.ProjectLicenseInfo; import org.codehaus.mojo.license.download.UrlReplacements; +import org.codehaus.mojo.license.extended.InfoFile; import org.codehaus.mojo.license.extended.spreadsheet.ExcelFileWriter; import org.codehaus.mojo.license.spdx.SpdxLicenseList; import org.codehaus.mojo.license.spdx.SpdxLicenseList.Attachments.ContentSanitizer; @@ -70,6 +52,27 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.TransformerException; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.regex.Pattern; + /** * Created on 23/05/16. * @@ -236,6 +239,18 @@ public abstract class AbstractDownloadLicensesMojo defaultValue = "${project.build.directory}/generated-resources/licenses-errors.xml" ) private File licensesErrorsFile; + /** + * A file containing dependencies whose licenses could not be downloaded for some reason. The format is similar to + * {@link #licensesExcelOutputFile} but the entries in {@link #licensesExcelErrorFile} have + * {@code } elements attached to them. Those should explain what kind of error happened during + * the processing of the given dependency. + * + * @since 2.1 + */ + @Parameter( property = "license.licensesExcelErrorFile", + defaultValue = "${project.build.directory}/generated-resources/licenses-errors.xlsx" ) + private File licensesExcelErrorFile; + /** * A filter to exclude some scopes. * @@ -819,6 +834,8 @@ public void execute() downloadLicenses( licenseDownloader, depProject, false ); } } + + filterCopyrightLines( depProjectLicenses ); } catch ( IOException e ) { @@ -833,14 +850,11 @@ public void execute() } List depProjectLicensesWithErrors = filterErrors( depProjectLicenses ); - writeLicenseSummary( depProjectLicenses, licensesOutputFile, writeVersions ); - if ( writeExcelFile ) - { - ExcelFileWriter.write( depProjectLicenses, licensesExcelOutputFile ); - } + writeLicenseSummaries( depProjectLicenses, licensesOutputFile, licensesExcelOutputFile ); + if ( !CollectionUtils.isEmpty( depProjectLicensesWithErrors ) ) { - writeLicenseSummary( depProjectLicensesWithErrors, licensesErrorsFile, writeVersions ); + writeLicenseSummaries( depProjectLicensesWithErrors, licensesErrorsFile, licensesExcelErrorFile ); } removeOrphanFiles( depProjectLicenses ); @@ -872,6 +886,47 @@ public void execute() } } + private void writeLicenseSummaries( List depProjectLicenses, + File licensesOutputFile, + File licensesExcelOutputFile ) + throws ParserConfigurationException, TransformerException, IOException + { + writeLicenseSummary( depProjectLicenses, licensesOutputFile, writeVersions ); + if ( writeExcelFile ) + { + ExcelFileWriter.write( depProjectLicenses, licensesExcelOutputFile ); + } + } + + /** + * Removes all extracted copyright lines if the license is an unmodified original license.
+ * So no actual copyright lines are contained in the extracted copyright lines. + * + * @param depProjectLicenses Projects with extracted copyright lines. + */ + private void filterCopyrightLines( List depProjectLicenses ) + { + for ( ProjectLicenseInfo projectLicenseInfo : depProjectLicenses ) + { + if ( projectLicenseInfo.getExtendedInfo() == null + || CollectionUtils.isEmpty( projectLicenseInfo.getExtendedInfo().getInfoFiles() ) ) + { + continue; + } + List infoFiles = projectLicenseInfo.getExtendedInfo().getInfoFiles(); + for ( InfoFile infoFile : infoFiles ) + { + if ( cache.hasNormalizedContent( infoFile.getNormalizedContent() ) ) + { + LOG.debug( "Removed extracted copyright lines for " + + projectLicenseInfo.getExtendedInfo().getName() + + " (" + projectLicenseInfo.toGavString() + ")" ); + infoFile.setExtractedCopyrightLines( null ); + } + } + } + } + private UrlReplacements urlReplacements() { UrlReplacements.Builder b = UrlReplacements.builder().useDefaults( useDefaultUrlReplacements ); diff --git a/src/main/java/org/codehaus/mojo/license/download/Cache.java b/src/main/java/org/codehaus/mojo/license/download/Cache.java index 7bbe5b199..142dba653 100644 --- a/src/main/java/org/codehaus/mojo/license/download/Cache.java +++ b/src/main/java/org/codehaus/mojo/license/download/Cache.java @@ -28,6 +28,8 @@ import java.util.Map.Entry; import org.codehaus.mojo.license.download.LicenseDownloader.LicenseDownloadResult; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * A simple {@link HashMap} based in-memory cache for storing {@link LicenseDownloadResult}s. @@ -37,10 +39,14 @@ */ public class Cache { + private static final Logger LOG = LoggerFactory.getLogger( Cache.class ); + private final Map urlToFile = new HashMap<>(); private final Map sha1ToFile = new HashMap<>(); + private final Map normalizedContentToFile = new HashMap<>(); + private final boolean enforcingUniqueSha1s; public Cache( boolean enforcingUniqueSha1s ) @@ -59,6 +65,17 @@ public LicenseDownloadResult get( String url ) return urlToFile.get( url ); } + /** + * If this cache has a normalized version of a license file. + * + * @param normalizedContentChecksum Normalized file content. + * @return If the cache has a license file with the same normalized content. + */ + public boolean hasNormalizedContent( String normalizedContentChecksum ) + { + return normalizedContentToFile.get( normalizedContentChecksum ) != null; + } + /** * Binds the given {@code url} to the give {@link LicenseDownloadResult}. If both {@link #enforcingUniqueSha1s} and * {@link LicenseDownloadResult#isSuccess()} are {@code true} and an entry with the given @@ -98,8 +115,16 @@ else if ( enforcingUniqueSha1s && !existing.getFile().equals( entryFile ) ) + "' should belong to licenseUrlFileName having key '" + existingFile.getName() + "' together with URLs '" + sb.toString() + "'" ); } + final String normalizedContentChecksum = entry.getNormalizedContentChecksum(); + if ( normalizedContentChecksum != null ) + { + normalizedContentToFile.put( normalizedContentChecksum, entry ); + } + else + { + LOG.warn( "Couldn't find normalized content checksum for license download " + entry ); + } } urlToFile.put( url, entry ); } - } \ No newline at end of file diff --git a/src/main/java/org/codehaus/mojo/license/download/LicenseDownloader.java b/src/main/java/org/codehaus/mojo/license/download/LicenseDownloader.java index 3a29d9c0b..c010eed03 100644 --- a/src/main/java/org/codehaus/mojo/license/download/LicenseDownloader.java +++ b/src/main/java/org/codehaus/mojo/license/download/LicenseDownloader.java @@ -24,6 +24,7 @@ import java.io.BufferedReader; import java.io.File; +import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; @@ -43,6 +44,7 @@ import org.apache.commons.codec.binary.Hex; import org.apache.commons.codec.digest.DigestUtils; +import org.apache.commons.io.IOUtils; import org.apache.http.HttpEntity; import org.apache.http.HttpException; import org.apache.http.HttpHost; @@ -345,7 +347,10 @@ public static class LicenseDownloadResult { public static LicenseDownloadResult success( File file, String sha1, boolean preferredFileName ) { - return new LicenseDownloadResult( file, sha1, preferredFileName, null ); + final LicenseDownloadResult licenseDownloadResult + = new LicenseDownloadResult( file, sha1, preferredFileName, null ); + licenseDownloadResult.calculateFileChecksum(); + return licenseDownloadResult; } public static LicenseDownloadResult failure( String errorMessage ) @@ -366,8 +371,18 @@ private LicenseDownloadResult( File file, String sha1, boolean preferredFileName private final String errorMessage; + /** + * Checksum to file name. + */ private final String sha1; + /** + * Checksum to "normalized" content of the file. + *
+ * Normalized means: Removal of all newlines - in all formats, lines trimmed, all chars converted to lowercase. + */ + private String normalizedContentChecksum; + private final boolean preferredFileName; public File getFile() @@ -380,6 +395,11 @@ public String getErrorMessage() return errorMessage; } + /** + * Is true when no errorMessage is set. + * + * @return If errorMessage is set. + */ public boolean isSuccess() { return errorMessage == null; @@ -395,10 +415,76 @@ public String getSha1() return sha1; } + public String getNormalizedContentChecksum() + { + return normalizedContentChecksum; + } + public LicenseDownloadResult withFile( File otherFile ) { return new LicenseDownloadResult( otherFile, sha1, preferredFileName, errorMessage ); } + + public void calculateFileChecksum() + { + normalizedContentChecksum = LicenseDownloader.calculateFileChecksum( file ); + } + + @Override + public String toString() + { + return "LicenseDownloadResult{" + + "file=" + file + + ", errorMessage='" + errorMessage + '\'' + + ", sha1='" + sha1 + '\'' + + ", normalizedContentChecksum='" + normalizedContentChecksum + '\'' + + ", preferredFileName=" + preferredFileName + + '}'; + } + } + + private static String calculateFileChecksum( File file ) + { + try ( InputStream inputStream = new FileInputStream( file ) ) + { + byte[] content = IOUtils.readFully( inputStream, (int) file.length() ); + String contentString = new String( content ); + return calculateStringChecksum( contentString ); + } + catch ( IOException e ) + { + LOG.error( "Error reading license file and normalizing it ", e ); + return null; + } } + public static String calculateStringChecksum( String contentString ) + { + contentString = normalizeString( contentString ); + try + { + final MessageDigest md = MessageDigest.getInstance( "SHA-1" ); + return Hex.encodeHexString( md.digest( contentString.getBytes() ) ); + } + catch ( NoSuchAlgorithmException e ) + { + LOG.error( "Error fetching SHA-1 hashsum generator ", e ); + return null; + } + } + + private static String normalizeString( String contentString ) + { + return contentString + // Windows + .replace( "\r\n", " " ) + // Classic MacOS + .replace( "\r", " " ) + // *nix + .replace( "\n", " " ) + // Set all spaces, tabs, etc. to one space width + .replaceAll( "\\s\\s+", " " ) + // All to lowercase + .toLowerCase(); + } } diff --git a/src/main/java/org/codehaus/mojo/license/download/LicenseSummaryWriter.java b/src/main/java/org/codehaus/mojo/license/download/LicenseSummaryWriter.java index 01a4dc3f2..60069a2ae 100644 --- a/src/main/java/org/codehaus/mojo/license/download/LicenseSummaryWriter.java +++ b/src/main/java/org/codehaus/mojo/license/download/LicenseSummaryWriter.java @@ -142,6 +142,7 @@ else if ( hasDownloaderMessages ) if ( dep.getExtendedInfo() != null ) { ExtendedInfo extendedInfo = dep.getExtendedInfo(); + addTextPropertyIfSet( doc, depNode, "name", extendedInfo.getName() ); addTextPropertyIfSet( doc, depNode, "bundleLicense", extendedInfo.getBundleLicense() ); addCdataIfSet( doc, depNode, "bundleVendor", extendedInfo.getBundleVendor() ); appendChildNodesIfSet( doc, depNode, "developers", extendedInfo.getDevelopers(), diff --git a/src/main/java/org/codehaus/mojo/license/download/LicensedArtifact.java b/src/main/java/org/codehaus/mojo/license/download/LicensedArtifact.java index 896868ac6..cacc5664c 100644 --- a/src/main/java/org/codehaus/mojo/license/download/LicensedArtifact.java +++ b/src/main/java/org/codehaus/mojo/license/download/LicensedArtifact.java @@ -53,7 +53,7 @@ import java.util.zip.ZipFile; /** - * @author Peter Palaga + * @author Peter Palaga, Jan-Hendrik Diederich (for the extended information) * @since 1.20 */ public class LicensedArtifact @@ -169,6 +169,12 @@ public List getErrorMessages() return errorMessages; } + /** + * Gets the extended information. + * + * @return Extended information. + * @since 2.1.0 + */ public ExtendedInfo getExtendedInfos() { return extendedInfos; @@ -274,13 +280,15 @@ else if ( fileName.equals( "meta-inf/manifest.mf" ) ) result.setBundleVendor( bundleVendor ); final String bundleLicense = mainAttributes.getValue( Constants.BUNDLE_LICENSE ); result.setBundleLicense( bundleLicense ); - } catch ( IOException e ) + } + catch ( IOException e ) { LOG.warn( "Error at reading data from jar manifest", e ); } } } - } catch ( IOException e ) + } + catch ( IOException e ) { LOG.warn( "Can't open zip file", e ); } @@ -365,7 +373,8 @@ private Pair readZipEntryTextLines( ZipFile zipFile, ZipEntry byte[] content = IOUtils.readFully( inputStream, (int) zipEntry.getSize() ); String contentString = new String( content ); return new ImmutablePair<>( contentString, contentString.split( "\\R+" ) ); - } catch ( IOException e ) + } + catch ( IOException e ) { LOG.warn( "Can't read zip file entry " + zipEntry, e ); return null; @@ -374,27 +383,50 @@ private Pair readZipEntryTextLines( ZipFile zipFile, ZipEntry public void setInceptionYear( String inceptionYear ) { - this.extendedInfos.setInceptionYear( inceptionYear ); + if ( extendedInfos != null ) + { + this.extendedInfos.setInceptionYear( inceptionYear ); + } } public void setOrganization( Organization organization ) { - this.extendedInfos.setOrganization( organization ); + if ( extendedInfos != null ) + { + this.extendedInfos.setOrganization( organization ); + } } public void setDevelopers( List developers ) { - this.extendedInfos.setDevelopers( developers ); + if ( extendedInfos != null ) + { + this.extendedInfos.setDevelopers( developers ); + } } public void setUrl( String url ) { - this.extendedInfos.setUrl( url ); + if ( extendedInfos != null ) + { + this.extendedInfos.setUrl( url ); + } } public void setScm( Scm scm ) { - this.extendedInfos.setScm( scm ); + if ( extendedInfos != null ) + { + this.extendedInfos.setScm( scm ); + } + } + + public void setName( String name ) + { + if ( extendedInfos != null ) + { + this.extendedInfos.setName( name ); + } } } } \ No newline at end of file diff --git a/src/main/java/org/codehaus/mojo/license/download/LicensedArtifactResolver.java b/src/main/java/org/codehaus/mojo/license/download/LicensedArtifactResolver.java index 66850bfd7..90db9d731 100644 --- a/src/main/java/org/codehaus/mojo/license/download/LicensedArtifactResolver.java +++ b/src/main/java/org/codehaus/mojo/license/download/LicensedArtifactResolver.java @@ -165,6 +165,7 @@ public void loadProjectDependencies( ResolvedProjectDependencies artifacts, .getProject(); if ( extendedInfo ) { + laBuilder.setName( project.getName() ); laBuilder.setInceptionYear( project.getInceptionYear() ); laBuilder.setOrganization( project.getOrganization() ); laBuilder.setDevelopers( project.getDevelopers() ); diff --git a/src/main/java/org/codehaus/mojo/license/extended/ExtendedInfo.java b/src/main/java/org/codehaus/mojo/license/extended/ExtendedInfo.java index 1349e5321..05cf69bc0 100644 --- a/src/main/java/org/codehaus/mojo/license/extended/ExtendedInfo.java +++ b/src/main/java/org/codehaus/mojo/license/extended/ExtendedInfo.java @@ -36,6 +36,7 @@ */ public class ExtendedInfo { + private String name; private Artifact artifact; private List infoFiles = new ArrayList<>(); private String implementationVendor; @@ -147,4 +148,14 @@ public void setUrl( String url ) { this.url = url; } + + public String getName() + { + return name; + } + + public void setName( String name ) + { + this.name = name; + } } \ No newline at end of file diff --git a/src/main/java/org/codehaus/mojo/license/extended/InfoFile.java b/src/main/java/org/codehaus/mojo/license/extended/InfoFile.java index 4477948a6..0834bd09d 100644 --- a/src/main/java/org/codehaus/mojo/license/extended/InfoFile.java +++ b/src/main/java/org/codehaus/mojo/license/extended/InfoFile.java @@ -22,6 +22,8 @@ * #L% */ +import org.codehaus.mojo.license.download.LicenseDownloader; + import java.util.HashSet; import java.util.Set; @@ -54,6 +56,8 @@ public enum Type private Set extractedCopyrightLines = new HashSet<>(); private Type type; + private String normalizedContent; + public String getFileName() { return fileName; @@ -72,6 +76,7 @@ public String getContent() public void setContent( String content ) { this.content = content; + this.normalizedContent = LicenseDownloader.calculateStringChecksum( content ); } public Set getExtractedCopyrightLines() @@ -93,4 +98,9 @@ public void setType( Type type ) { this.type = type; } + + public String getNormalizedContent() + { + return normalizedContent; + } } \ No newline at end of file diff --git a/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/ExcelFileWriter.java b/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/ExcelFileWriter.java index c0f981fa0..5cbe6fe74 100644 --- a/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/ExcelFileWriter.java +++ b/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/ExcelFileWriter.java @@ -35,12 +35,14 @@ import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.usermodel.CellType; import org.apache.poi.ss.usermodel.Font; +import org.apache.poi.ss.usermodel.HorizontalAlignment; import org.apache.poi.ss.usermodel.Hyperlink; import org.apache.poi.ss.usermodel.IndexedColors; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.util.CellRangeAddress; +import org.apache.poi.ss.util.RegionUtil; import org.apache.poi.ss.util.WorkbookUtil; import org.apache.poi.xssf.usermodel.XSSFFont; import org.apache.poi.xssf.usermodel.XSSFWorkbook; @@ -70,20 +72,25 @@ public class ExcelFileWriter private static final Logger LOG = LoggerFactory.getLogger( ExcelFileWriter.class ); // Columns values for Maven data, including separator gaps for data grouping. - private static final int PLUGIN_ID_COLUMNS = 3; + private static final int GENERAL_START_COLUMN = 0, GENERAL_COLUMNS = 1, + GENERAL_END_COLUMN = GENERAL_START_COLUMN + GENERAL_COLUMNS; + private static final int PLUGIN_ID_START_COLUMN = GENERAL_END_COLUMN + 1, PLUGIN_ID_COLUMNS = 3, + PLUGIN_ID_END_COLUMN = PLUGIN_ID_START_COLUMN + PLUGIN_ID_COLUMNS; // "Start" column are the actual start columns, they are inclusive. // "End" columns point just one column behind the last one, it's the exclusive column index. - private static final int LICENSES_START_COLUMN = PLUGIN_ID_COLUMNS + 1, LICENSES_COLUMNS = 5, + private static final int LICENSES_START_COLUMN = PLUGIN_ID_END_COLUMN + 1, LICENSES_COLUMNS = 5, LICENSES_END_COLUMN = LICENSES_START_COLUMN + LICENSES_COLUMNS; private static final int DEVELOPERS_START_COLUMN = LICENSES_END_COLUMN + 1, DEVELOPER_COLUMNS = 7, DEVELOPERS_END_COLUMN = DEVELOPERS_START_COLUMN + DEVELOPER_COLUMNS; private static final int MISC_START_COLUMN = DEVELOPERS_END_COLUMN + 1, MISC_COLUMNS = 4, MISC_END_COLUMN = MISC_START_COLUMN + MISC_COLUMNS; - private static final int MAVEN_DATA_COLUMNS = PLUGIN_ID_COLUMNS + LICENSES_COLUMNS + private static final int MAVEN_DATA_COLUMNS = GENERAL_COLUMNS + PLUGIN_ID_COLUMNS + LICENSES_COLUMNS + DEVELOPER_COLUMNS + MISC_COLUMNS, - MAVEN_COLUMN_GROUPING_GAPS = 3; - private static final int MAVEN_COLUMNS = MAVEN_DATA_COLUMNS + MAVEN_COLUMN_GROUPING_GAPS; + MAVEN_COLUMN_GROUPING_GAPS = 4; + private static final int MAVEN_START_COLUMN = 0, + MAVEN_COLUMNS = MAVEN_DATA_COLUMNS + MAVEN_COLUMN_GROUPING_GAPS, + MAVEN_END_COLUMN = MAVEN_START_COLUMN + MAVEN_COLUMNS; // Columns values for JAR data, including separator gaps for data grouping. private static final int INFO_FILES_GAPS = 2, MANIFEST_GAPS = 1; @@ -95,12 +102,18 @@ public class ExcelFileWriter INFO_LICENSES_END_COLUMN = INFO_LICENSES_START_COLUMN + INFO_LICENSES_COLUMNS; private static final int INFO_SPDX_START_COLUMN = INFO_LICENSES_END_COLUMN + 1, INFO_SPDX_COLUMNS = 3, INFO_SPDX_END_COLUMN = INFO_SPDX_START_COLUMN + INFO_SPDX_COLUMNS; - private static final int EXTENDED_INFO_COLUMNS = MANIFEST_COLUMNS + private static final int EXTENDED_INFO_START_COLUMN = MAVEN_END_COLUMN + 1, + EXTENDED_INFO_COLUMNS = MANIFEST_COLUMNS + INFO_NOTICES_COLUMNS + INFO_LICENSES_COLUMNS + INFO_SPDX_COLUMNS - + INFO_FILES_GAPS + MANIFEST_GAPS; + + INFO_FILES_GAPS + MANIFEST_GAPS, + EXTENDED_INFO_END_COLUMN = EXTENDED_INFO_START_COLUMN + EXTENDED_INFO_COLUMNS; // Width of gap columns - private static final int GAP_WIDTH = 20; + private static final int EXCEL_WIDTH_SCALE = 256; + private static final int GAP_WIDTH = 3 * EXCEL_WIDTH_SCALE; + private static final BorderStyle HEADER_CELLS_BORDER_STYLE = BorderStyle.MEDIUM; + private static final int TIMEZONE_WIDTH = " Timezone ".length() * EXCEL_WIDTH_SCALE, + INCEPTION_YEAR_WIDTH = " Inception Year ".length() * EXCEL_WIDTH_SCALE; /** * Writes list of projects into excel file. @@ -132,116 +145,13 @@ public static void write( List projectLicenseInfos, final Fi } } - private static void writeData( List projectLicenseInfos, Workbook wb, Sheet sheet ) - { - final int firstRowIndex = 3; - int currentRowIndex = firstRowIndex; - final Map rows = new HashMap<>(); - boolean hasExtendedInfo = false; - for ( ProjectLicenseInfo projectInfo : projectLicenseInfos ) - { - int extraRows = 0; - Row currentRow = sheet.createRow( currentRowIndex ); - rows.put( currentRowIndex, currentRow ); - // Plugin ID - createCellsInRow( currentRow, 0, - projectInfo.getGroupId(), projectInfo.getArtifactId(), projectInfo.getVersion() ); - // Licenses - extraRows = addCollection( sheet, rows, currentRowIndex, extraRows, - projectInfo.getLicenses(), - ( Row licenseRow, ProjectLicense license ) -> { - Cell[] licenses = createCellsInRow( licenseRow, LICENSES_START_COLUMN, - license.getName(), license.getUrl(), - license.getDistribution(), license.getComments(), - license.getFile() ); - addHyperlinkIfExists( wb, licenses[ 1 ], HyperlinkType.URL ); - } ); - - final ExtendedInfo extendedInfo = projectInfo.getExtendedInfo(); - if ( extendedInfo != null ) - { - hasExtendedInfo = true; - // Developers - extraRows = addCollection( sheet, rows, currentRowIndex, extraRows, - extendedInfo.getDevelopers(), - ( Row developerRow, Developer developer ) -> { - Cell[] licenses = createCellsInRow( developerRow, DEVELOPERS_START_COLUMN, - developer.getId(), developer.getEmail(), - developer.getName(), - developer.getOrganization(), developer.getOrganizationUrl(), - developer.getUrl(), developer.getTimezone() ); - addHyperlinkIfExists( wb, licenses[ 1 ], HyperlinkType.EMAIL ); - addHyperlinkIfExists( wb, licenses[ 4 ], HyperlinkType.URL ); - addHyperlinkIfExists( wb, licenses[ 5 ], HyperlinkType.URL ); - } ); - // Miscellaneous - Cell[] miscCells = createCellsInRow( currentRow, MISC_START_COLUMN, - extendedInfo.getInceptionYear(), - Optional.ofNullable( extendedInfo.getOrganization() ) - .map( Organization::getName ) - .orElse( null ), - Optional.ofNullable( extendedInfo.getScm() ) - .map( Scm::getUrl ) - .orElse( null ), - extendedInfo.getUrl() ); - addHyperlinkIfExists( wb, miscCells[ 2 ], HyperlinkType.URL ); - addHyperlinkIfExists( wb, miscCells[ 3 ], HyperlinkType.URL ); - - // MANIFEST.MF - createCellsInRow( currentRow, MANIFEST_START_COLUMN, - extendedInfo.getBundleLicense(), extendedInfo.getBundleVendor(), - extendedInfo.getImplementationVendor() ); - - // Info files - if ( !CollectionUtils.isEmpty( extendedInfo.getInfoFiles() ) ) - { - // Sort all info files by type into 3 different lists, each list for each of the 3 types. - List notices = new ArrayList<>(); - List licenses = new ArrayList<>(); - List spdxs = new ArrayList<>(); - extendedInfo.getInfoFiles().forEach( infoFile -> { - switch ( infoFile.getType() ) - { - case LICENSE: - licenses.add( infoFile ); - break; - case NOTICE: - notices.add( infoFile ); - break; - case SPDX_LICENSE: - spdxs.add( infoFile ); - break; - default: - break; - } - } - ); - // InfoFile notices text file - extraRows = addInfoFileList( sheet, rows, currentRowIndex, extraRows, - INFO_NOTICES_START_COLUMN, notices ); - // InfoFile licenses text file - extraRows = addInfoFileList( sheet, rows, currentRowIndex, extraRows, - INFO_LICENSES_START_COLUMN, licenses ); - // InfoFile spdx licenses text file - extraRows = addInfoFileList( sheet, rows, currentRowIndex, extraRows, - INFO_SPDX_START_COLUMN, spdxs ); - } - } - currentRowIndex += extraRows + 1; - } - - autosizeColumns( sheet, hasExtendedInfo ); - } - private static void createHeader( List projectLicenseInfos, Workbook wb, Sheet sheet ) { - int columns = MAVEN_COLUMNS; boolean hasExtendedInfo = false; for ( ProjectLicenseInfo projectLicenseInfo : projectLicenseInfos ) { if ( projectLicenseInfo.getExtendedInfo() != null ) { - columns += EXTENDED_INFO_COLUMNS; hasExtendedInfo = true; break; } @@ -253,37 +163,44 @@ private static void createHeader( List projectLicenseInfos, Font headerFont = new XSSFFont(); headerFont.setBold( true ); headerCellStyle.setFont( headerFont ); - setBorderStyle( headerCellStyle, BorderStyle.MEDIUM ); + headerCellStyle.setAlignment( HorizontalAlignment.CENTER ); + setBorderStyle( headerCellStyle, HEADER_CELLS_BORDER_STYLE ); // Create 1st header row. The Maven/JAR header row Row mavenJarRow = sheet.createRow( 0 ); // Create Maven header cell - createMergedCellsInRow( sheet, 0, MAVEN_COLUMNS, headerCellStyle, mavenJarRow, "Maven information", 0 ); + createMergedCellsInRow( sheet, MAVEN_START_COLUMN, MAVEN_END_COLUMN, headerCellStyle, mavenJarRow, + "Maven information", 0 ); if ( hasExtendedInfo ) { // Create JAR header cell - Cell jarHeaderCell = mavenJarRow.createCell( 0 ); - jarHeaderCell.setCellValue( "JAR Content" ); - jarHeaderCell.setCellStyle( headerCellStyle ); - createCellsInRow( MAVEN_COLUMNS, columns, mavenJarRow ); - CellRangeAddress jarHeaderAddress = new CellRangeAddress( 0, 0, MAVEN_COLUMNS, columns - 1 ); - sheet.addMergedRegion( jarHeaderAddress ); + createMergedCellsInRow( sheet, EXTENDED_INFO_START_COLUMN, EXTENDED_INFO_END_COLUMN, + headerCellStyle, mavenJarRow, + "JAR Content", 0 ); } // Create 2nd header row Row secondHeaderRow = sheet.createRow( 1 ); + // Create Maven "General" header + createMergedCellsInRow( sheet, GENERAL_START_COLUMN, GENERAL_END_COLUMN, headerCellStyle, secondHeaderRow, + "General", 1 ); + // Create Maven "Plugin ID" header - createMergedCellsInRow( sheet, 0, PLUGIN_ID_COLUMNS, headerCellStyle, secondHeaderRow, "Plugin ID", 1 ); + createMergedCellsInRow( sheet, PLUGIN_ID_START_COLUMN, PLUGIN_ID_END_COLUMN, headerCellStyle, secondHeaderRow, + "Plugin ID", 1 ); + + // Gap "General" <-> "Plugin ID". + sheet.setColumnWidth( GENERAL_END_COLUMN, GAP_WIDTH ); // Create Maven "Licenses" header createMergedCellsInRow( sheet, LICENSES_START_COLUMN, LICENSES_END_COLUMN, headerCellStyle, secondHeaderRow, "Licenses", 1 ); // Gap "Plugin ID" <-> "Licenses". - sheet.setColumnWidth( PLUGIN_ID_COLUMNS, GAP_WIDTH ); + sheet.setColumnWidth( PLUGIN_ID_END_COLUMN, GAP_WIDTH ); // Create Maven "Developers" header createMergedCellsInRow( sheet, DEVELOPERS_START_COLUMN, DEVELOPERS_END_COLUMN, headerCellStyle, @@ -322,19 +239,25 @@ private static void createHeader( List projectLicenseInfos, "License text files", 1 ); // Gap "Notice text files" <-> "License text files". - sheet.setColumnWidth( INFO_LICENSES_END_COLUMN, GAP_WIDTH ); + sheet.setColumnWidth( INFO_NOTICES_END_COLUMN, GAP_WIDTH ); createMergedCellsInRow( sheet, INFO_SPDX_START_COLUMN, INFO_SPDX_END_COLUMN, headerCellStyle, secondHeaderRow, "SPDX license id matched", 1 ); + + // Gap "License text files" <-> "SPDX license matches". + sheet.setColumnWidth( INFO_LICENSES_END_COLUMN, GAP_WIDTH ); } // sheet.setColumnGroupCollapsed(); // Create 3rd header row Row thirdHeaderRow = sheet.createRow( 2 ); + // General + createCellsInRow( thirdHeaderRow, GENERAL_START_COLUMN, headerCellStyle, "Name" ); // Plugin ID - createCellsInRow( thirdHeaderRow, 0, headerCellStyle, "Group ID", "Artifact ID", "Version" ); + createCellsInRow( thirdHeaderRow, PLUGIN_ID_START_COLUMN, headerCellStyle, + "Group ID", "Artifact ID", "Version" ); // Licenses createCellsInRow( thirdHeaderRow, LICENSES_START_COLUMN, headerCellStyle, "Name", "URL", "Distribution", "Comments", "File" ); @@ -345,6 +268,8 @@ private static void createHeader( List projectLicenseInfos, createCellsInRow( thirdHeaderRow, MISC_START_COLUMN, headerCellStyle, "Inception Year", "Organization", "SCM", "URL" ); + int headerLineCount = 3; + if ( hasExtendedInfo ) { // MANIFEST.MF @@ -353,17 +278,146 @@ private static void createHeader( List projectLicenseInfos, // 3 InfoFile groups: Notices, Licenses and SPDX-Licenses. createInfoFileCellsInRow( thirdHeaderRow, headerCellStyle, INFO_NOTICES_START_COLUMN, INFO_LICENSES_START_COLUMN, INFO_SPDX_START_COLUMN ); + + sheet.createFreezePane( EXTENDED_INFO_END_COLUMN, headerLineCount ); + } + else + { + sheet.createFreezePane( MAVEN_END_COLUMN, headerLineCount ); + } + + sheet.createFreezePane( GENERAL_END_COLUMN, headerLineCount ); + } + + + private static void writeData( List projectLicenseInfos, Workbook wb, Sheet sheet ) + { + final int firstRowIndex = 3; + int currentRowIndex = firstRowIndex; + final Map rows = new HashMap<>(); + boolean hasExtendedInfo = false; + + final CellStyle hyperlinkStyle = createHyperlinkStyle( wb ); + + for ( ProjectLicenseInfo projectInfo : projectLicenseInfos ) + { + int extraRows = 0; + Row currentRow = sheet.createRow( currentRowIndex ); + rows.put( currentRowIndex, currentRow ); + // Plugin ID + createCellsInRow( currentRow, PLUGIN_ID_START_COLUMN, + projectInfo.getGroupId(), projectInfo.getArtifactId(), projectInfo.getVersion() ); + // Licenses + extraRows = addCollection( sheet, rows, currentRowIndex, extraRows, + projectInfo.getLicenses(), + ( Row licenseRow, ProjectLicense license ) -> { + Cell[] licenses = createCellsInRow( licenseRow, LICENSES_START_COLUMN, + license.getName(), license.getUrl(), + license.getDistribution(), license.getComments(), + license.getFile() ); + addHyperlinkIfExists( wb, licenses[ 1 ], hyperlinkStyle, HyperlinkType.URL ); + } ); + + final ExtendedInfo extendedInfo = projectInfo.getExtendedInfo(); + if ( extendedInfo != null ) + { + hasExtendedInfo = true; + // General + createCellsInRow( currentRow, GENERAL_START_COLUMN, + extendedInfo.getName() ); + // Developers + extraRows = addCollection( sheet, rows, currentRowIndex, extraRows, + extendedInfo.getDevelopers(), + ( Row developerRow, Developer developer ) -> { + Cell[] licenses = createCellsInRow( developerRow, DEVELOPERS_START_COLUMN, + developer.getId(), developer.getEmail(), + developer.getName(), + developer.getOrganization(), developer.getOrganizationUrl(), + developer.getUrl(), developer.getTimezone() ); + addHyperlinkIfExists( wb, licenses[ 1 ], hyperlinkStyle, HyperlinkType.EMAIL ); + addHyperlinkIfExists( wb, licenses[ 4 ], hyperlinkStyle, HyperlinkType.URL ); + addHyperlinkIfExists( wb, licenses[ 5 ], hyperlinkStyle, HyperlinkType.URL ); + } ); + // Miscellaneous + Cell[] miscCells = createCellsInRow( currentRow, MISC_START_COLUMN, + extendedInfo.getInceptionYear(), + Optional.ofNullable( extendedInfo.getOrganization() ) + .map( Organization::getName ) + .orElse( null ), + Optional.ofNullable( extendedInfo.getScm() ) + .map( Scm::getUrl ) + .orElse( null ), + extendedInfo.getUrl() ); + addHyperlinkIfExists( wb, miscCells[ 2 ], hyperlinkStyle, HyperlinkType.URL ); + addHyperlinkIfExists( wb, miscCells[ 3 ], hyperlinkStyle, HyperlinkType.URL ); + + // MANIFEST.MF + createCellsInRow( currentRow, MANIFEST_START_COLUMN, + extendedInfo.getBundleLicense(), extendedInfo.getBundleVendor(), + extendedInfo.getImplementationVendor() ); + + // Info files + if ( !CollectionUtils.isEmpty( extendedInfo.getInfoFiles() ) ) + { + // Sort all info files by type into 3 different lists, each list for each of the 3 types. + List notices = new ArrayList<>(); + List licenses = new ArrayList<>(); + List spdxs = new ArrayList<>(); + extendedInfo.getInfoFiles().forEach( infoFile -> { + switch ( infoFile.getType() ) + { + case LICENSE: + licenses.add( infoFile ); + break; + case NOTICE: + notices.add( infoFile ); + break; + case SPDX_LICENSE: + spdxs.add( infoFile ); + break; + default: + break; + } + } + ); + // InfoFile notices text file + extraRows = addInfoFileList( sheet, rows, currentRowIndex, extraRows, + INFO_NOTICES_START_COLUMN, notices ); + // InfoFile licenses text file + extraRows = addInfoFileList( sheet, rows, currentRowIndex, extraRows, + INFO_LICENSES_START_COLUMN, licenses ); + // InfoFile spdx licenses text file + extraRows = addInfoFileList( sheet, rows, currentRowIndex, extraRows, + INFO_SPDX_START_COLUMN, spdxs ); + } + } + currentRowIndex += extraRows + 1; } + + autosizeColumns( sheet, hasExtendedInfo ); + } + + private static CellStyle createHyperlinkStyle( Workbook wb ) + { + Font hyperlinkFont = wb.createFont(); + hyperlinkFont.setUnderline( XSSFFont.U_SINGLE ); + hyperlinkFont.setColor( IndexedColors.BLUE.getIndex() ); + CellStyle hyperlinkStyle = wb.createCellStyle(); + hyperlinkStyle.setFont( hyperlinkFont ); + return hyperlinkStyle; } private static void autosizeColumns( Sheet sheet, boolean hasExtendedInfo ) { autosizeColumns( sheet, - new ImmutablePair<>( 0, PLUGIN_ID_COLUMNS ), + new ImmutablePair<>( GENERAL_START_COLUMN, GENERAL_END_COLUMN ), + new ImmutablePair<>( PLUGIN_ID_START_COLUMN, PLUGIN_ID_END_COLUMN ), new ImmutablePair<>( LICENSES_START_COLUMN, LICENSES_END_COLUMN ), new ImmutablePair<>( DEVELOPERS_START_COLUMN, DEVELOPERS_END_COLUMN - 1 ), new ImmutablePair<>( MISC_START_COLUMN + 1, MISC_END_COLUMN ) ); + sheet.setColumnWidth( DEVELOPERS_END_COLUMN - 1, TIMEZONE_WIDTH ); + sheet.setColumnWidth( MISC_START_COLUMN, INCEPTION_YEAR_WIDTH ); if ( hasExtendedInfo ) { autosizeColumns( sheet, @@ -375,11 +429,11 @@ private static void autosizeColumns( Sheet sheet, boolean hasExtendedInfo ) } } - private static void autosizeColumns( Sheet sheet, ImmutablePair... ranges ) + private static void autosizeColumns( Sheet sheet, Pair... ranges ) { - for ( ImmutablePair pair : ranges ) + for ( Pair range : ranges ) { - for ( int i = pair.left; i < pair.right; i++ ) + for ( int i = range.getLeft(); i < range.getRight(); i++ ) { sheet.autoSizeColumn( i ); } @@ -423,7 +477,8 @@ private static int addCollection( Sheet sheet, Map rows, int c return extraRows; } - private static void addHyperlinkIfExists( Workbook workbook, Cell cell, HyperlinkType hyperlinkType ) + private static void addHyperlinkIfExists( Workbook workbook, Cell cell, CellStyle hyperlinkStyle, + HyperlinkType hyperlinkType ) { if ( !StringUtils.isEmpty( cell.getStringCellValue() ) ) { @@ -432,7 +487,9 @@ private static void addHyperlinkIfExists( Workbook workbook, Cell cell, Hyperlin { hyperlink.setAddress( cell.getStringCellValue() ); cell.setHyperlink( hyperlink ); - } catch ( IllegalArgumentException e ) + cell.setCellStyle( hyperlinkStyle ); + } + catch ( IllegalArgumentException e ) { LOG.debug( "Can't set Hyperlink for cell value " + cell.getStringCellValue() + " it gets rejected as URI", e ); @@ -446,7 +503,20 @@ private static Cell[] createCellsInRow( Row row, int startColumn, String... name for ( int i = 0; i < names.length; i++ ) { Cell cell = row.createCell( startColumn + i, CellType.STRING ); - cell.setCellValue( names[ i ] ); + if ( !StringUtils.isEmpty( names[ i ] ) ) + { + final String value; + final int maxCellStringLength = Short.MAX_VALUE; + if ( names[ i ].length() > maxCellStringLength ) + { + value = names[ i ].substring( 0, maxCellStringLength - 3 ) + "..."; + } + else + { + value = names[ i ]; + } + cell.setCellValue( value ); + } result[ i ] = cell; } return result; @@ -471,7 +541,7 @@ private static void createCellsInRow( Row row, int startColumn, CellStyle cellSt { for ( int i = 0; i < names.length; i++ ) { - Cell cell = row.createCell( startColumn + i ); + Cell cell = row.createCell( startColumn + i, CellType.STRING ); cell.setCellStyle( cellStyle ); cell.setCellValue( names[ i ] ); } @@ -480,21 +550,45 @@ private static void createCellsInRow( Row row, int startColumn, CellStyle cellSt private static void createMergedCellsInRow( Sheet sheet, int startColumn, int endColumn, CellStyle cellStyle, Row row, String cellValue, int rowIndex ) { - Cell licensesCell = row.createCell( startColumn ); - licensesCell.setCellValue( cellValue ); - licensesCell.setCellStyle( cellStyle ); - createCellsInRow( startColumn + 1, endColumn, row ); - CellRangeAddress licensesHeaderAddress = new CellRangeAddress( rowIndex, rowIndex, startColumn, endColumn - 1 ); - sheet.addMergedRegion( licensesHeaderAddress ); - sheet.groupColumn( startColumn, endColumn - 1 ); + Cell cell = createCellsInRow( startColumn, endColumn, row ); + final boolean merge = endColumn - 1 > startColumn; + CellRangeAddress mergeAddress = null; + if ( merge ) + { + mergeAddress = new CellRangeAddress( rowIndex, rowIndex, startColumn, endColumn - 1 ); + sheet.addMergedRegion( mergeAddress ); + } + // Set value and style only after merge + cell.setCellValue( cellValue ); + cell.setCellStyle( cellStyle ); + if ( merge ) + { + setBorderAroundRegion( sheet, mergeAddress, HEADER_CELLS_BORDER_STYLE ); + sheet.groupColumn( startColumn, endColumn - 1 ); + } + } + + private static void setBorderAroundRegion( Sheet sheet, CellRangeAddress licensesHeaderAddress, + BorderStyle borderStyle ) + { + RegionUtil.setBorderLeft( borderStyle, licensesHeaderAddress, sheet ); + RegionUtil.setBorderTop( borderStyle, licensesHeaderAddress, sheet ); + RegionUtil.setBorderRight( borderStyle, licensesHeaderAddress, sheet ); + RegionUtil.setBorderBottom( borderStyle, licensesHeaderAddress, sheet ); } - private static void createCellsInRow( int startColumn, int exclusiveEndColumn, Row inRow ) + private static Cell createCellsInRow( int startColumn, int exclusiveEndColumn, Row inRow ) { + Cell firstCell = null; for ( int i = startColumn; i < exclusiveEndColumn; i++ ) { - inRow.createCell( i ); + Cell cell = inRow.createCell( i ); + if ( i == startColumn ) + { + firstCell = cell; + } } + return firstCell; } private static void setBorderStyle( CellStyle cellStyle, BorderStyle borderStyle ) From 441c6e059a50c9dedafc36fe17d6d380926e237d Mon Sep 17 00:00:00 2001 From: Jan-Hendrik Diederich Date: Mon, 18 Nov 2019 15:50:20 +0100 Subject: [PATCH 06/34] Excel report cleaner formatting - Header font bold - Header light green background - Alternating white / light gray background --> To group all lines belonging to one plugin/dependency together. --- .../extended/spreadsheet/ExcelFileWriter.java | 304 ++++++++++++++---- 1 file changed, 245 insertions(+), 59 deletions(-) diff --git a/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/ExcelFileWriter.java b/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/ExcelFileWriter.java index 5cbe6fe74..faf0bb307 100644 --- a/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/ExcelFileWriter.java +++ b/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/ExcelFileWriter.java @@ -34,6 +34,7 @@ import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.usermodel.CellType; +import org.apache.poi.ss.usermodel.FillPatternType; import org.apache.poi.ss.usermodel.Font; import org.apache.poi.ss.usermodel.HorizontalAlignment; import org.apache.poi.ss.usermodel.Hyperlink; @@ -44,6 +45,9 @@ import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.ss.util.RegionUtil; import org.apache.poi.ss.util.WorkbookUtil; +import org.apache.poi.xssf.usermodel.IndexedColorMap; +import org.apache.poi.xssf.usermodel.XSSFCellStyle; +import org.apache.poi.xssf.usermodel.XSSFColor; import org.apache.poi.xssf.usermodel.XSSFFont; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.codehaus.mojo.license.download.ProjectLicense; @@ -53,6 +57,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.awt.Color; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; @@ -80,17 +85,17 @@ public class ExcelFileWriter // "End" columns point just one column behind the last one, it's the exclusive column index. private static final int LICENSES_START_COLUMN = PLUGIN_ID_END_COLUMN + 1, LICENSES_COLUMNS = 5, LICENSES_END_COLUMN = LICENSES_START_COLUMN + LICENSES_COLUMNS; - private static final int DEVELOPERS_START_COLUMN = LICENSES_END_COLUMN + 1, DEVELOPER_COLUMNS = 7, - DEVELOPERS_END_COLUMN = DEVELOPERS_START_COLUMN + DEVELOPER_COLUMNS; + private static final int DEVELOPERS_START_COLUMN = LICENSES_END_COLUMN + 1, DEVELOPERS_COLUMNS = 7, + DEVELOPERS_END_COLUMN = DEVELOPERS_START_COLUMN + DEVELOPERS_COLUMNS; private static final int MISC_START_COLUMN = DEVELOPERS_END_COLUMN + 1, MISC_COLUMNS = 4, MISC_END_COLUMN = MISC_START_COLUMN + MISC_COLUMNS; private static final int MAVEN_DATA_COLUMNS = GENERAL_COLUMNS + PLUGIN_ID_COLUMNS + LICENSES_COLUMNS - + DEVELOPER_COLUMNS + MISC_COLUMNS, + + DEVELOPERS_COLUMNS + MISC_COLUMNS, MAVEN_COLUMN_GROUPING_GAPS = 4; private static final int MAVEN_START_COLUMN = 0, MAVEN_COLUMNS = MAVEN_DATA_COLUMNS + MAVEN_COLUMN_GROUPING_GAPS, - MAVEN_END_COLUMN = MAVEN_START_COLUMN + MAVEN_COLUMNS; + MAVEN_END_COLUMN = MAVEN_START_COLUMN + MAVEN_COLUMNS; // Columns values for JAR data, including separator gaps for data grouping. private static final int INFO_FILES_GAPS = 2, MANIFEST_GAPS = 1; @@ -104,8 +109,8 @@ public class ExcelFileWriter INFO_SPDX_END_COLUMN = INFO_SPDX_START_COLUMN + INFO_SPDX_COLUMNS; private static final int EXTENDED_INFO_START_COLUMN = MAVEN_END_COLUMN + 1, EXTENDED_INFO_COLUMNS = MANIFEST_COLUMNS - + INFO_NOTICES_COLUMNS + INFO_LICENSES_COLUMNS + INFO_SPDX_COLUMNS - + INFO_FILES_GAPS + MANIFEST_GAPS, + + INFO_NOTICES_COLUMNS + INFO_LICENSES_COLUMNS + INFO_SPDX_COLUMNS + + INFO_FILES_GAPS + MANIFEST_GAPS, EXTENDED_INFO_END_COLUMN = EXTENDED_INFO_START_COLUMN + EXTENDED_INFO_COLUMNS; // Width of gap columns @@ -113,7 +118,9 @@ public class ExcelFileWriter private static final int GAP_WIDTH = 3 * EXCEL_WIDTH_SCALE; private static final BorderStyle HEADER_CELLS_BORDER_STYLE = BorderStyle.MEDIUM; private static final int TIMEZONE_WIDTH = " Timezone ".length() * EXCEL_WIDTH_SCALE, - INCEPTION_YEAR_WIDTH = " Inception Year ".length() * EXCEL_WIDTH_SCALE; + INCEPTION_YEAR_WIDTH = " Inception Year ".length() * EXCEL_WIDTH_SCALE; + private static final Color ALTERNATING_ROWS_COLOR = new Color( 240, 240, 240 ); + private static final String COPYRIGHT_JOIN_SEPARATOR = "§"; /** * Writes list of projects into excel file. @@ -129,17 +136,21 @@ public static void write( List projectLicenseInfos, final Fi return; } - Workbook wb = new XSSFWorkbook(); - Sheet sheet = wb.createSheet( WorkbookUtil.createSafeSheetName( "License information" ) ); + final XSSFWorkbook wb = new XSSFWorkbook(); + final Sheet sheet = wb.createSheet( WorkbookUtil.createSafeSheetName( "License information" ) ); + + final IndexedColorMap colorMap = wb.getStylesSource().getIndexedColors(); + final XSSFColor alternatingRowsColor = new XSSFColor( ALTERNATING_ROWS_COLOR, colorMap ); createHeader( projectLicenseInfos, wb, sheet ); - writeData( projectLicenseInfos, wb, sheet ); + writeData( projectLicenseInfos, wb, sheet, alternatingRowsColor ); try ( OutputStream fileOut = new FileOutputStream( licensesExcelOutputFile ) ) { wb.write( fileOut ); - } catch ( IOException e ) + } + catch ( IOException e ) { LOG.error( "Error on storing Excel file with license and other information", e ); } @@ -159,8 +170,9 @@ private static void createHeader( List projectLicenseInfos, // Create header style CellStyle headerCellStyle = wb.createCellStyle(); - headerCellStyle.setFillBackgroundColor( IndexedColors.GREY_25_PERCENT.getIndex() ); - Font headerFont = new XSSFFont(); + headerCellStyle.setFillForegroundColor( IndexedColors.LIGHT_GREEN.getIndex() ); + headerCellStyle.setFillPattern( FillPatternType.SOLID_FOREGROUND ); + Font headerFont = wb.createFont(); headerFont.setBold( true ); headerCellStyle.setFont( headerFont ); headerCellStyle.setAlignment( HorizontalAlignment.CENTER ); @@ -289,30 +301,52 @@ private static void createHeader( List projectLicenseInfos, sheet.createFreezePane( GENERAL_END_COLUMN, headerLineCount ); } - - private static void writeData( List projectLicenseInfos, Workbook wb, Sheet sheet ) + // TODO: Clean this method up. Too many parameters, too complicated parameters/DTO pattern. But keep it still threadsafe. + private static void writeData( List projectLicenseInfos, XSSFWorkbook wb, Sheet sheet, + XSSFColor alternatingRowsColor ) { final int firstRowIndex = 3; int currentRowIndex = firstRowIndex; - final Map rows = new HashMap<>(); + final Map rowMap = new HashMap<>(); boolean hasExtendedInfo = false; - final CellStyle hyperlinkStyle = createHyperlinkStyle( wb ); + final CellStyle hyperlinkStyleNormal = createHyperlinkStyle( wb, null ); + final CellStyle hyperlinkStyleGray = createHyperlinkStyle( wb, alternatingRowsColor ); + + boolean grayBackground = false; + XSSFCellStyle styleGray = wb.createCellStyle(); + styleGray.setFillForegroundColor( alternatingRowsColor ); + styleGray.setFillPattern( FillPatternType.SOLID_FOREGROUND ); for ( ProjectLicenseInfo projectInfo : projectLicenseInfos ) { + final CellStyle cellStyle, hyperlinkStyle; + if ( grayBackground ) + { + cellStyle = styleGray; + hyperlinkStyle = hyperlinkStyleGray; + } + else + { + cellStyle = null; + hyperlinkStyle = hyperlinkStyleNormal; + } + grayBackground = !grayBackground; + int extraRows = 0; Row currentRow = sheet.createRow( currentRowIndex ); - rows.put( currentRowIndex, currentRow ); + rowMap.put( currentRowIndex, currentRow ); // Plugin ID - createCellsInRow( currentRow, PLUGIN_ID_START_COLUMN, - projectInfo.getGroupId(), projectInfo.getArtifactId(), projectInfo.getVersion() ); + createDataCellsInRow( currentRow, PLUGIN_ID_START_COLUMN, + cellStyle, projectInfo.getGroupId(), projectInfo.getArtifactId(), projectInfo.getVersion() ); // Licenses - extraRows = addCollection( sheet, rows, currentRowIndex, extraRows, - projectInfo.getLicenses(), + final CellListParameter cellListParameter = new CellListParameter( sheet, rowMap, cellStyle ); + CurrentRowData currentRowData = new CurrentRowData( currentRowIndex, extraRows, hasExtendedInfo ); + extraRows = addList( cellListParameter, currentRowData, + LICENSES_START_COLUMN, LICENSES_COLUMNS, projectInfo.getLicenses(), ( Row licenseRow, ProjectLicense license ) -> { - Cell[] licenses = createCellsInRow( licenseRow, LICENSES_START_COLUMN, - license.getName(), license.getUrl(), + Cell[] licenses = createDataCellsInRow( licenseRow, LICENSES_START_COLUMN, + cellStyle, license.getName(), license.getUrl(), license.getDistribution(), license.getComments(), license.getFile() ); addHyperlinkIfExists( wb, licenses[ 1 ], hyperlinkStyle, HyperlinkType.URL ); @@ -323,14 +357,15 @@ private static void writeData( List projectLicenseInfos, Wor { hasExtendedInfo = true; // General - createCellsInRow( currentRow, GENERAL_START_COLUMN, - extendedInfo.getName() ); + createDataCellsInRow( currentRow, GENERAL_START_COLUMN, + cellStyle, extendedInfo.getName() ); // Developers - extraRows = addCollection( sheet, rows, currentRowIndex, extraRows, - extendedInfo.getDevelopers(), + currentRowData = new CurrentRowData( currentRowIndex, extraRows, hasExtendedInfo ); + extraRows = addList( cellListParameter, currentRowData, + DEVELOPERS_START_COLUMN, DEVELOPERS_COLUMNS, extendedInfo.getDevelopers(), ( Row developerRow, Developer developer ) -> { - Cell[] licenses = createCellsInRow( developerRow, DEVELOPERS_START_COLUMN, - developer.getId(), developer.getEmail(), + Cell[] licenses = createDataCellsInRow( developerRow, DEVELOPERS_START_COLUMN, + cellStyle, developer.getId(), developer.getEmail(), developer.getName(), developer.getOrganization(), developer.getOrganizationUrl(), developer.getUrl(), developer.getTimezone() ); @@ -339,8 +374,8 @@ private static void writeData( List projectLicenseInfos, Wor addHyperlinkIfExists( wb, licenses[ 5 ], hyperlinkStyle, HyperlinkType.URL ); } ); // Miscellaneous - Cell[] miscCells = createCellsInRow( currentRow, MISC_START_COLUMN, - extendedInfo.getInceptionYear(), + Cell[] miscCells = createDataCellsInRow( currentRow, MISC_START_COLUMN, + cellStyle, extendedInfo.getInceptionYear(), Optional.ofNullable( extendedInfo.getOrganization() ) .map( Organization::getName ) .orElse( null ), @@ -352,8 +387,8 @@ private static void writeData( List projectLicenseInfos, Wor addHyperlinkIfExists( wb, miscCells[ 3 ], hyperlinkStyle, HyperlinkType.URL ); // MANIFEST.MF - createCellsInRow( currentRow, MANIFEST_START_COLUMN, - extendedInfo.getBundleLicense(), extendedInfo.getBundleVendor(), + createDataCellsInRow( currentRow, MANIFEST_START_COLUMN, + cellStyle, extendedInfo.getBundleLicense(), extendedInfo.getBundleVendor(), extendedInfo.getImplementationVendor() ); // Info files @@ -381,14 +416,26 @@ private static void writeData( List projectLicenseInfos, Wor } ); // InfoFile notices text file - extraRows = addInfoFileList( sheet, rows, currentRowIndex, extraRows, - INFO_NOTICES_START_COLUMN, notices ); + currentRowData = new CurrentRowData( currentRowIndex, extraRows, hasExtendedInfo ); + extraRows = addInfoFileList( cellListParameter, currentRowData, + INFO_NOTICES_START_COLUMN, INFO_NOTICES_COLUMNS, notices ); // InfoFile licenses text file - extraRows = addInfoFileList( sheet, rows, currentRowIndex, extraRows, - INFO_LICENSES_START_COLUMN, licenses ); + currentRowData = new CurrentRowData( currentRowIndex, extraRows, hasExtendedInfo ); + extraRows = addInfoFileList( cellListParameter, currentRowData, + INFO_LICENSES_START_COLUMN, INFO_LICENSES_COLUMNS, licenses ); // InfoFile spdx licenses text file - extraRows = addInfoFileList( sheet, rows, currentRowIndex, extraRows, - INFO_SPDX_START_COLUMN, spdxs ); + currentRowData = new CurrentRowData( currentRowIndex, extraRows, hasExtendedInfo ); + extraRows = addInfoFileList( cellListParameter, currentRowData, + INFO_SPDX_START_COLUMN, INFO_SPDX_COLUMNS, spdxs ); + } + else if ( cellListParameter.cellStyle != null ) + { + setStyleOnEmptyCells( cellListParameter, currentRowData, + INFO_NOTICES_START_COLUMN, INFO_NOTICES_COLUMNS ); + setStyleOnEmptyCells( cellListParameter, currentRowData, + INFO_LICENSES_START_COLUMN, INFO_LICENSES_COLUMNS ); + setStyleOnEmptyCells( cellListParameter, currentRowData, + INFO_SPDX_START_COLUMN, INFO_SPDX_COLUMNS ); } } currentRowIndex += extraRows + 1; @@ -397,12 +444,17 @@ private static void writeData( List projectLicenseInfos, Wor autosizeColumns( sheet, hasExtendedInfo ); } - private static CellStyle createHyperlinkStyle( Workbook wb ) + private static CellStyle createHyperlinkStyle( XSSFWorkbook wb, XSSFColor backgroundColor ) { Font hyperlinkFont = wb.createFont(); hyperlinkFont.setUnderline( XSSFFont.U_SINGLE ); hyperlinkFont.setColor( IndexedColors.BLUE.getIndex() ); - CellStyle hyperlinkStyle = wb.createCellStyle(); + XSSFCellStyle hyperlinkStyle = wb.createCellStyle(); + if ( backgroundColor != null ) + { + hyperlinkStyle.setFillForegroundColor( backgroundColor ); + hyperlinkStyle.setFillPattern( FillPatternType.SOLID_FOREGROUND ); + } hyperlinkStyle.setFont( hyperlinkFont ); return hyperlinkStyle; } @@ -416,6 +468,7 @@ private static void autosizeColumns( Sheet sheet, boolean hasExtendedInfo ) new ImmutablePair<>( DEVELOPERS_START_COLUMN, DEVELOPERS_END_COLUMN - 1 ), new ImmutablePair<>( MISC_START_COLUMN + 1, MISC_END_COLUMN ) ); + // The column header widths are most likely wider than the actual cells content. sheet.setColumnWidth( DEVELOPERS_END_COLUMN - 1, TIMEZONE_WIDTH ); sheet.setColumnWidth( MISC_START_COLUMN, INCEPTION_YEAR_WIDTH ); if ( hasExtendedInfo ) @@ -429,6 +482,7 @@ private static void autosizeColumns( Sheet sheet, boolean hasExtendedInfo ) } } + @SafeVarargs private static void autosizeColumns( Sheet sheet, Pair... ranges ) { for ( Pair range : ranges ) @@ -440,41 +494,100 @@ private static void autosizeColumns( Sheet sheet, Pair... rang } } - private static int addInfoFileList( Sheet sheet, Map rows, int currentRowIndex, int extraRows, - int startColumn, List infoFiles ) + private static int addInfoFileList( CellListParameter cellListParameter, CurrentRowData currentRowData, + int startColumn, int columnsToFill, List infoFiles ) { - return addCollection( sheet, rows, currentRowIndex, extraRows, infoFiles, + return addList( cellListParameter, currentRowData, startColumn, columnsToFill, infoFiles, ( Row infoFileRow, InfoFile infoFile ) -> { final String copyrightLines = Optional .ofNullable( infoFile.getExtractedCopyrightLines() ) - .map( strings -> String.join( "§", strings ) ) + .map( strings -> String.join( COPYRIGHT_JOIN_SEPARATOR, strings ) ) .orElse( null ); - createCellsInRow( infoFileRow, startColumn, - infoFile.getContent(), copyrightLines, + createDataCellsInRow( infoFileRow, startColumn, + cellListParameter.getCellStyle(), infoFile.getContent(), copyrightLines, infoFile.getFileName() ); } ); } - private static int addCollection( Sheet sheet, Map rows, int currentRowIndex, int extraRows, - List list, BiConsumer biConsumer ) + private static int addList( CellListParameter cellListParameter, CurrentRowData currentRowData, + int startColumn, int columnsToFill, + List list, BiConsumer biConsumer ) { if ( !CollectionUtils.isEmpty( list ) ) { for ( int i = 0; i < list.size(); i++ ) { - T license = list.get( i ); - Integer index = currentRowIndex + i; - Row row = rows.get( index ); + T type = list.get( i ); + Integer index = currentRowData.getCurrentRowIndex() + i; + Row row = cellListParameter.getRows().get( index ); if ( row == null ) { - row = sheet.createRow( index ); - rows.put( index, row ); - extraRows++; + row = cellListParameter.getSheet().createRow( index ); + cellListParameter.getRows().put( index, row ); + if ( cellListParameter.getCellStyle() != null ) + { + // Style all empty left cells, in the columns left from this + createAndStyleCells( row, cellListParameter.getCellStyle(), + new ImmutablePair<>( GENERAL_START_COLUMN, GENERAL_END_COLUMN ), + new ImmutablePair<>( PLUGIN_ID_START_COLUMN, PLUGIN_ID_END_COLUMN ), + new ImmutablePair<>( LICENSES_START_COLUMN, LICENSES_END_COLUMN ) + ); + if ( currentRowData.isHasExtendedInfo() ) + { + createAndStyleCells( row, cellListParameter.getCellStyle(), + new ImmutablePair<>( DEVELOPERS_START_COLUMN, DEVELOPERS_END_COLUMN ), + new ImmutablePair<>( MISC_START_COLUMN, MISC_END_COLUMN ), + // JAR + new ImmutablePair<>( MANIFEST_START_COLUMN, MANIFEST_END_COLUMN ), + new ImmutablePair<>( INFO_LICENSES_START_COLUMN, INFO_LICENSES_END_COLUMN ), + new ImmutablePair<>( INFO_NOTICES_START_COLUMN, INFO_NOTICES_END_COLUMN ), + new ImmutablePair<>( INFO_SPDX_START_COLUMN, INFO_SPDX_END_COLUMN ) + ); + } + } + currentRowData.setExtraRows( currentRowData.getExtraRows() + 1 ); } - biConsumer.accept( row, license ); + biConsumer.accept( row, type ); + } + } + else if ( cellListParameter.cellStyle != null ) + { + setStyleOnEmptyCells( cellListParameter, currentRowData, startColumn, columnsToFill ); + } + return currentRowData.getExtraRows(); + } + + /** + * If no cells are set, color at least the background, + * to color concatenated blocks with the same background color. + * + * @param cellListParameter Passes data about sheet, row, cell style. + * @param currentRowData Passes data about the current indices for rows and columns. + * @param startColumn Column where to start setting the style. + * @param columnsToFill How many columns to set the style on, starting from 'startColumn'. + */ + private static void setStyleOnEmptyCells( CellListParameter cellListParameter, CurrentRowData currentRowData, + int startColumn, int columnsToFill ) + { + Row row = cellListParameter.getRows().get( currentRowData.getCurrentRowIndex() ); + for ( int i = 0; i < columnsToFill; i++ ) + { + Cell cell = row.createCell( startColumn + i, CellType.STRING ); + cell.setCellStyle( cellListParameter.getCellStyle() ); + } + } + + @SafeVarargs + private static void createAndStyleCells( Row row, CellStyle cellStyle, Pair... ranges ) + { + for ( Pair range : ranges ) + { + for ( int i = range.getLeft(); i < range.getRight(); i++ ) + { + Cell cell = row.createCell( i, CellType.STRING ); + cell.setCellStyle( cellStyle ); } } - return extraRows; } private static void addHyperlinkIfExists( Workbook workbook, Cell cell, CellStyle hyperlinkStyle, @@ -497,12 +610,16 @@ private static void addHyperlinkIfExists( Workbook workbook, Cell cell, CellStyl } } - private static Cell[] createCellsInRow( Row row, int startColumn, String... names ) + private static Cell[] createDataCellsInRow( Row row, int startColumn, CellStyle cellStyle, String... names ) { Cell[] result = new Cell[ names.length ]; for ( int i = 0; i < names.length; i++ ) { Cell cell = row.createCell( startColumn + i, CellType.STRING ); + if ( cellStyle != null ) + { + cell.setCellStyle( cellStyle ); + } if ( !StringUtils.isEmpty( names[ i ] ) ) { final String value; @@ -598,4 +715,73 @@ private static void setBorderStyle( CellStyle cellStyle, BorderStyle borderStyle cellStyle.setBorderRight( borderStyle ); cellStyle.setBorderBottom( borderStyle ); } + + /** + * Parameters for cells which apply to all cells in each loop iteration. + */ + private static class CellListParameter + { + private final Sheet sheet; + private final Map rows; + private final CellStyle cellStyle; + + private CellListParameter( Sheet sheet, Map rows, CellStyle cellStyle ) + { + this.sheet = sheet; + this.rows = rows; + this.cellStyle = cellStyle; + } + + Sheet getSheet() + { + return sheet; + } + + Map getRows() + { + return rows; + } + + CellStyle getCellStyle() + { + return cellStyle; + } + } + + /** + * Parameters which may change constantly. + */ + private static class CurrentRowData + { + private final int currentRowIndex; + private int extraRows; + private final boolean hasExtendedInfo; + + CurrentRowData( int currentRowIndex, int extraRows, boolean hasExtendedInfo ) + { + this.currentRowIndex = currentRowIndex; + this.extraRows = extraRows; + this.hasExtendedInfo = hasExtendedInfo; + } + + int getCurrentRowIndex() + { + return currentRowIndex; + } + + int getExtraRows() + { + return extraRows; + } + + void setExtraRows( int extraRows ) + { + this.extraRows = extraRows; + } + + boolean isHasExtendedInfo() + { + return hasExtendedInfo; + } + } } \ No newline at end of file From 82062572b63c4bd12a8d64c9b477719442aa52af Mon Sep 17 00:00:00 2001 From: Jan-Hendrik Diederich Date: Mon, 18 Nov 2019 16:26:59 +0100 Subject: [PATCH 07/34] Extended license information logs the zip file name which couldn't be opened --- .../org/codehaus/mojo/license/download/LicensedArtifact.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/codehaus/mojo/license/download/LicensedArtifact.java b/src/main/java/org/codehaus/mojo/license/download/LicensedArtifact.java index cacc5664c..b1a1de3b2 100644 --- a/src/main/java/org/codehaus/mojo/license/download/LicensedArtifact.java +++ b/src/main/java/org/codehaus/mojo/license/download/LicensedArtifact.java @@ -290,7 +290,7 @@ else if ( fileName.equals( "meta-inf/manifest.mf" ) ) } catch ( IOException e ) { - LOG.warn( "Can't open zip file", e ); + LOG.warn( "Can't open zip file \"" + artifact.getFile() + "\"", e ); } return result; } From 51fc6c18537228529c02c28dab929f7f9a237c16 Mon Sep 17 00:00:00 2001 From: Jan-Hendrik Diederich Date: Tue, 19 Nov 2019 11:04:15 +0100 Subject: [PATCH 08/34] License file checksum generation replaces http with https --- .../license/download/LicenseDownloader.java | 44 ++++++++++--------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/src/main/java/org/codehaus/mojo/license/download/LicenseDownloader.java b/src/main/java/org/codehaus/mojo/license/download/LicenseDownloader.java index c010eed03..8f59704f2 100644 --- a/src/main/java/org/codehaus/mojo/license/download/LicenseDownloader.java +++ b/src/main/java/org/codehaus/mojo/license/download/LicenseDownloader.java @@ -22,26 +22,6 @@ * #L% */ -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.net.URI; -import java.net.URISyntaxException; -import java.nio.charset.Charset; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.regex.Pattern; - import org.apache.commons.codec.binary.Hex; import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.io.IOUtils; @@ -74,6 +54,26 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.regex.Pattern; + /** * Utilities for downloading remote license files. * @@ -484,6 +484,10 @@ private static String normalizeString( String contentString ) .replace( "\n", " " ) // Set all spaces, tabs, etc. to one space width .replaceAll( "\\s\\s+", " " ) + /* License files exist which are completely identical, except that someone changed + to . + */ + .replace( "http://", "https://" ) // All to lowercase .toLowerCase(); } From 214c9ad08a2c307c329b16da8462af78a64c731e Mon Sep 17 00:00:00 2001 From: Jan-Hendrik Diederich Date: Tue, 19 Nov 2019 11:11:14 +0100 Subject: [PATCH 09/34] Generated Excel file had a too low contrast alternating rows color --- .../mojo/license/extended/spreadsheet/ExcelFileWriter.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/ExcelFileWriter.java b/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/ExcelFileWriter.java index faf0bb307..05f0fff02 100644 --- a/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/ExcelFileWriter.java +++ b/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/ExcelFileWriter.java @@ -119,7 +119,8 @@ public class ExcelFileWriter private static final BorderStyle HEADER_CELLS_BORDER_STYLE = BorderStyle.MEDIUM; private static final int TIMEZONE_WIDTH = " Timezone ".length() * EXCEL_WIDTH_SCALE, INCEPTION_YEAR_WIDTH = " Inception Year ".length() * EXCEL_WIDTH_SCALE; - private static final Color ALTERNATING_ROWS_COLOR = new Color( 240, 240, 240 ); + // Color must be dark enough for low contrast monitors + private static final Color ALTERNATING_ROWS_COLOR = new Color( 220, 220, 220 ); private static final String COPYRIGHT_JOIN_SEPARATOR = "§"; /** From 8fd021893629208192d5d18228ae7f78a30dbd64 Mon Sep 17 00:00:00 2001 From: Jan-Hendrik Diederich Date: Tue, 1 Mar 2022 12:30:44 +0100 Subject: [PATCH 10/34] Update README.md to explain this Maven License Plugin fork. --- README.md | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 95 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b485defd4..62d22b926 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,9 @@ # license-maven-plugin -This is the [license-maven-plugin](http://www.mojohaus.org/license-maven-plugin/). +This is the [license-maven-plugin](http://www.mojohaus.org/license-maven-plugin/). It has been forked and extended with the option +to extract more license information from the dependencies. It can also write a report to an Excel file. + +Information about the source project (the license stays of course the same): [![Build Status](https://travis-ci.org/mojohaus/license-maven-plugin.svg?branch=master)](https://travis-ci.org/mojohaus/license-maven-plugin) [![Maven Central](https://img.shields.io/maven-central/v/org.codehaus.mojo/license-maven-plugin.svg?label=Maven%20Central)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22org.codehaus.mojo%22%20a%3A%license-maven-plugin%22) @@ -18,3 +21,94 @@ For publishing the site do the following: cd target/checkout mvn verify site -DperformRelease scm-publish:publish-scm ``` + +## How to configure the extended Excel report + +The projects `pom.xml` must have the lines marked with "``" to use the new options (`extendedInfo` +and `writeExcelFile`): + + + + + + org.codehaus.mojo + license-maven-plugin + 2.1.0-SNAPSHOT + + + true + + true + ... + + + + + Apache License, Version 2.0|Apache 2.0|Apache 2|Apache License 2.0|The Apache + Software License, Version 2.0|Apache + License, version 2.0|AL 2.0|ASF 2.0 + + MIT License|The MIT License|The MIT License (MIT) + GNU Lesser General Public License|GNU Lesser General Public Licence|GNU LESSER + GENERAL PUBLIC LICENSE|GNU Lesser + Public License|Lesser General Public License (LGPL) + + GNU General Lesser Public License (LGPL) version 3.0|GNU LESSER GENERAL PUBLIC + LICENSE, version 3 (LGPL-3.0) + + + The BSD License|BSD License|BSD + The BSD 3-Clause License|The New BSD License|New BSD License + + +Since this hasn't been published to the official Maven repository yet, you must compile it yourself and install it to +your local repository. + +If you want to include it in your project and make sure all dependencies are packed together and +solved, install it by adding: + + + + + + + + + + maven-install-plugin + 3.0.0-M1 + + true + + + ... + + + + + maven-install-plugin + false + + + install-own-maven-license-plugin + validate + + install-file + + + ${third.party.dir}/license-maven-plugin-2.1.0-SNAPSHOT.jar + org.codehaus.mojo + license-maven-plugin + 2.1.0-SNAPSHOT + jar + + + + + ... + +Then, to install the plugin a `mvn validate` is enough. + +After that, generate the report with `mvn license:aggregate-download-licenses`. + +Under `./target/generated-resources/licenses.xlsx` is then the generated Excel-Report with the extended information. \ No newline at end of file From a37d0083d687a3687b565eeca8b0330efcfea19e Mon Sep 17 00:00:00 2001 From: Jan-Hendrik Diederich Date: Tue, 31 May 2022 14:01:26 +0200 Subject: [PATCH 11/34] ISSUE-145 test fixed, it used an outdated Java version --- src/it/ISSUE-145/pom.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/it/ISSUE-145/pom.xml b/src/it/ISSUE-145/pom.xml index 4241fddd7..870629c98 100644 --- a/src/it/ISSUE-145/pom.xml +++ b/src/it/ISSUE-145/pom.xml @@ -39,6 +39,10 @@ org.apache.maven.plugins maven-compiler-plugin 3.8.0 + + 1.8 + 1.8 + From af22db179be31d736f55dba907f8521b0b95350f Mon Sep 17 00:00:00 2001 From: Jan-Hendrik Diederich Date: Tue, 31 May 2022 14:02:54 +0200 Subject: [PATCH 12/34] ANTLR license website checksum updated to current checksum --- .../postbuild.groovy | 2 +- src/it/download-licenses-file-names/pom.xml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/it/download-licenses-file-names-bad-sha1-force/postbuild.groovy b/src/it/download-licenses-file-names-bad-sha1-force/postbuild.groovy index d92f2289a..f123c1ff5 100644 --- a/src/it/download-licenses-file-names-bad-sha1-force/postbuild.groovy +++ b/src/it/download-licenses-file-names-bad-sha1-force/postbuild.groovy @@ -27,4 +27,4 @@ final Path basePath = basedir.toPath() final Path log = basePath.resolve('build.log') assert Files.exists(log) -assert log.text.contains('URL \'http://www.antlr.org/license.html\' returned content with unexpected sha1 \'074f8d6e91730b40875178666513014472888247\'; expected \'2b8b815229aa8a61e483fb4ba0588b8b6c491890\'') +assert log.text.contains('URL \'http://www.antlr.org/license.html\' returned content with unexpected sha1 \'666518759e606772587886dcb54a9867bcf275e0\'; expected \'2b8b815229aa8a61e483fb4ba0588b8b6c491890\'') diff --git a/src/it/download-licenses-file-names/pom.xml b/src/it/download-licenses-file-names/pom.xml index 284b58dc1..7cdee22dd 100644 --- a/src/it/download-licenses-file-names/pom.xml +++ b/src/it/download-licenses-file-names/pom.xml @@ -88,7 +88,7 @@ - sha1:074f8d6e91730b40875178666513014472888247 + sha1:666518759e606772587886dcb54a9867bcf275e0 \Qhttp://www.antlr.org/license.html\E @@ -123,7 +123,7 @@ - sha1:074f8d6e91730b40875178666513014472888247 + sha1:666518759e606772587886dcb54a9867bcf275e0 \Qhttp://www.antlr.org/license.html\E From f5b3461b1299b1229dea21c21752efdf3e460ee2 Mon Sep 17 00:00:00 2001 From: Jan-Hendrik Diederich Date: Tue, 31 May 2022 14:03:14 +0200 Subject: [PATCH 13/34] maven-wrapper.jar updated --- .mvn/wrapper/maven-wrapper.jar | Bin 48336 -> 48335 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/.mvn/wrapper/maven-wrapper.jar b/.mvn/wrapper/maven-wrapper.jar index 08ebbb67f088c53eac9a4e2cb019b93f69a1e49c..a817247a6a026c5d3ff383cf7df71ada27f556cf 100755 GIT binary patch delta 14 Wcmccclj;0VrVX#fHop;jvJ?P8D+q-E delta 16 YcmX^Alj*`wrVX#f7 Date: Tue, 31 May 2022 14:15:58 +0200 Subject: [PATCH 14/34] Create maven CI file --- .github/workflows/maven.yml | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 .github/workflows/maven.yml diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml new file mode 100644 index 000000000..94d73a47b --- /dev/null +++ b/.github/workflows/maven.yml @@ -0,0 +1,26 @@ +# This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time +# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven + +name: Java CI with Maven + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - name: Set up JDK 8 + uses: actions/setup-java@v3 + with: + java-version: '8' + distribution: 'temurin' + cache: maven + - name: Build with Maven + run: mvn -B verify From d59d93d9887d01e3d08d8ea0b33348f20744fdca Mon Sep 17 00:00:00 2001 From: Jan-Hendrik Diederich Date: Tue, 31 May 2022 14:20:09 +0200 Subject: [PATCH 15/34] test.crlf.sh added missing newline at end-of-file --- .../src/files/properties/test.crlf.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/it/update-file-header-test-mojo/src/files/properties/test.crlf.sh b/src/it/update-file-header-test-mojo/src/files/properties/test.crlf.sh index 0711e4cb1..7c8914fbb 100644 --- a/src/it/update-file-header-test-mojo/src/files/properties/test.crlf.sh +++ b/src/it/update-file-header-test-mojo/src/files/properties/test.crlf.sh @@ -1,3 +1,3 @@ #!/bin/sh -ls ~/* \ No newline at end of file +ls ~/* From 911407ccf5892168f67244997d75e3bc90de8390 Mon Sep 17 00:00:00 2001 From: Jan-Hendrik Diederich Date: Tue, 31 May 2022 14:45:54 +0200 Subject: [PATCH 16/34] GitHub continues integration (CI) badge added Old Mojohaus badge removed --- .github/workflows/maven.yml | 2 +- README.md | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 94d73a47b..f5b159dab 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -1,7 +1,7 @@ # This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time # For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven -name: Java CI with Maven +name: CI on: push: diff --git a/README.md b/README.md index 62d22b926..a736ca46c 100644 --- a/README.md +++ b/README.md @@ -5,8 +5,7 @@ to extract more license information from the dependencies. It can also write a r Information about the source project (the license stays of course the same): -[![Build Status](https://travis-ci.org/mojohaus/license-maven-plugin.svg?branch=master)](https://travis-ci.org/mojohaus/license-maven-plugin) -[![Maven Central](https://img.shields.io/maven-central/v/org.codehaus.mojo/license-maven-plugin.svg?label=Maven%20Central)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22org.codehaus.mojo%22%20a%3A%license-maven-plugin%22) +[![Build status](https://github.com/JD-CSTx/license-maven-plugin/workflows/CI/badge.svg)](https://github.com/JD-CSTx/license-maven-plugin/actions/workflows/maven.yml) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/mojohaus/license-maven-plugin?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![The GNU Lesser General Public License, Version 3.0](https://img.shields.io/badge/license-LGPL3-blue.svg)](http://www.gnu.org/licenses/lgpl-3.0.txt) From 1217989b8d82f9d0368b89739481f7554b4cd9b5 Mon Sep 17 00:00:00 2001 From: Jan-Hendrik Diederich Date: Tue, 31 May 2022 14:52:31 +0200 Subject: [PATCH 17/34] test.crlf.sh fixed line endings --- .../src/files/properties/test.crlf.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/src/it/update-file-header-test-mojo/src/files/properties/test.crlf.sh b/src/it/update-file-header-test-mojo/src/files/properties/test.crlf.sh index 7c8914fbb..981870746 100644 --- a/src/it/update-file-header-test-mojo/src/files/properties/test.crlf.sh +++ b/src/it/update-file-header-test-mojo/src/files/properties/test.crlf.sh @@ -1,3 +1,4 @@ #!/bin/sh ls ~/* + From 514741da2b51ff14a100ff62f2f8d2c94912a6e3 Mon Sep 17 00:00:00 2001 From: Jan-Hendrik Diederich Date: Tue, 31 May 2022 15:04:46 +0200 Subject: [PATCH 18/34] test.crlf.sh line endings fixed through changing .gitattributes --- .gitattributes | 5 +++-- .../src/files/properties/test.crlf.sh | 3 +-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.gitattributes b/.gitattributes index 8151bc4fa..4db9f210e 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,2 +1,3 @@ -* text eol=lf -*.cmd text eol=crlf +* text eol=lf +*.cmd text eol=crlf +*.crlf.sh text eol=crlf \ No newline at end of file diff --git a/src/it/update-file-header-test-mojo/src/files/properties/test.crlf.sh b/src/it/update-file-header-test-mojo/src/files/properties/test.crlf.sh index 981870746..0711e4cb1 100644 --- a/src/it/update-file-header-test-mojo/src/files/properties/test.crlf.sh +++ b/src/it/update-file-header-test-mojo/src/files/properties/test.crlf.sh @@ -1,4 +1,3 @@ #!/bin/sh -ls ~/* - +ls ~/* \ No newline at end of file From 7edfef66a60d14fd9e4856a8aeb07ed12ebbba8c Mon Sep 17 00:00:00 2001 From: Jan-Hendrik Diederich Date: Tue, 31 May 2022 15:29:26 +0200 Subject: [PATCH 19/34] README.md annotation added --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index a736ca46c..b4072560e 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,8 @@ to extract more license information from the dependencies. It can also write a r Information about the source project (the license stays of course the same): [![Build status](https://github.com/JD-CSTx/license-maven-plugin/workflows/CI/badge.svg)](https://github.com/JD-CSTx/license-maven-plugin/actions/workflows/maven.yml) +Tests pass locally, currently just not on Github. + [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/mojohaus/license-maven-plugin?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![The GNU Lesser General Public License, Version 3.0](https://img.shields.io/badge/license-LGPL3-blue.svg)](http://www.gnu.org/licenses/lgpl-3.0.txt) From 54aed69d31792238c31132b047104bd873090399 Mon Sep 17 00:00:00 2001 From: Jan Diederich Date: Sun, 24 Sep 2023 16:58:34 +0200 Subject: [PATCH 20/34] Improved README.md formatting --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index b4072560e..7260cbf9f 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,7 @@ mvn verify site -DperformRelease scm-publish:publish-scm The projects `pom.xml` must have the lines marked with "``" to use the new options (`extendedInfo` and `writeExcelFile`): +```xml @@ -61,13 +62,13 @@ and `writeExcelFile`): The BSD License|BSD License|BSD The BSD 3-Clause License|The New BSD License|New BSD License - +``` Since this hasn't been published to the official Maven repository yet, you must compile it yourself and install it to your local repository. If you want to include it in your project and make sure all dependencies are packed together and solved, install it by adding: - +```xml @@ -107,7 +108,7 @@ solved, install it by adding: ... - +``` Then, to install the plugin a `mvn validate` is enough. After that, generate the report with `mvn license:aggregate-download-licenses`. From 634c01f63e570ea4d6beb4fcbc203ac48d194a3a Mon Sep 17 00:00:00 2001 From: Jan Diederich Date: Tue, 3 Oct 2023 19:02:18 +0200 Subject: [PATCH 21/34] Merged latest version from original project / repository --- README.md | 2 +- pom.xml | 27 +- .../child1/pom.xml | 51 + .../child2/pom.xml | 58 ++ .../invoker.properties | 23 + .../pom.xml | 76 ++ .../postbuild.groovy | 68 ++ .../license/AbstractAddThirdPartyMojo.java | 15 - .../license/AbstractDownloadLicensesMojo.java | 89 +- .../mojo/license/AbstractLicensesXmlMojo.java | 4 +- .../license/AbstractThirdPartyReportMojo.java | 18 +- .../AggregateDownloadLicensesMojo.java | 14 +- .../license/AggregatorAddThirdPartyMojo.java | 8 - .../mojo/license/DownloadLicensesMojo.java | 7 +- .../LicensesXmlInsertVersionsMojo.java | 7 +- .../license/api/DefaultThirdPartyHelper.java | 13 - .../codehaus/mojo/license/download/Cache.java | 18 +- .../license/download/LicenseDownloader.java | 104 +- .../download/LicenseSummaryWriter.java | 176 ++-- .../license/download/LicensedArtifact.java | 265 +++--- .../download/LicensedArtifactResolver.java | 23 +- .../license/download/ProjectLicenseInfo.java | 9 +- .../mojo/license/extended/ExtendedInfo.java | 77 +- .../mojo/license/extended/InfoFile.java | 41 +- .../extended/spreadsheet/ExcelFileWriter.java | 901 +++++++++--------- .../license/download/LicenseMatchersTest.java | 4 +- .../license/download/LicenseSummaryTest.java | 12 +- 27 files changed, 1146 insertions(+), 964 deletions(-) create mode 100644 src/it/aggregate-download-licenses-extended-excel/child1/pom.xml create mode 100644 src/it/aggregate-download-licenses-extended-excel/child2/pom.xml create mode 100644 src/it/aggregate-download-licenses-extended-excel/invoker.properties create mode 100644 src/it/aggregate-download-licenses-extended-excel/pom.xml create mode 100644 src/it/aggregate-download-licenses-extended-excel/postbuild.groovy diff --git a/README.md b/README.md index f093779bc..994b33761 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ and `writeExcelFile`): org.codehaus.mojo license-maven-plugin - 2.1.0-SNAPSHOT + 2.2.1-SNAPSHOT true diff --git a/pom.xml b/pom.xml index 202b2a6bd..b4a500010 100644 --- a/pom.xml +++ b/pom.xml @@ -328,7 +328,7 @@ org.apache.poi poi-ooxml - 5.2.3 + 5.2.4 @@ -511,6 +511,18 @@ ${project.version} + + + org.apache.poi + poi-ooxml + 5.2.4 + + + commons-io + commons-io + 2.13.0 + + all-integration-test @@ -576,7 +588,18 @@ src/it/settings.xml ${project.build.directory}/local-repo - + + + org.apache.poi + poi-ooxml + 5.2.4 + + + commons-io + commons-io + 2.13.0 + + one-integration-test diff --git a/src/it/aggregate-download-licenses-extended-excel/child1/pom.xml b/src/it/aggregate-download-licenses-extended-excel/child1/pom.xml new file mode 100644 index 000000000..d770f50d8 --- /dev/null +++ b/src/it/aggregate-download-licenses-extended-excel/child1/pom.xml @@ -0,0 +1,51 @@ + + + + + + 4.0.0 + + + org.codehaus.mojo.license.test + test-aggregate-download-licenses-extended-excel + @project.version@ + + test-aggregate-download-licenses-extended-excel-child1 + + License Test :: aggregate-download-licenses - Extended Excel - child 1 + + + + + + commons-logging + commons-logging + 1.1.1 + + + + + + diff --git a/src/it/aggregate-download-licenses-extended-excel/child2/pom.xml b/src/it/aggregate-download-licenses-extended-excel/child2/pom.xml new file mode 100644 index 000000000..aa85ddbe8 --- /dev/null +++ b/src/it/aggregate-download-licenses-extended-excel/child2/pom.xml @@ -0,0 +1,58 @@ + + + + + + 4.0.0 + + + org.codehaus.mojo.license.test + test-aggregate-download-licenses-extended-excel + @project.version@ + + test-aggregate-download-licenses-extended-excel-child2 + + License Test :: aggregate-download-licenses - Extended Excel - child 2 + + + + + + com.jhlabs + filters + 2.0.235 + + + + + org.sonatype.plexus + plexus-cipher + 1.4 + + + + + + diff --git a/src/it/aggregate-download-licenses-extended-excel/invoker.properties b/src/it/aggregate-download-licenses-extended-excel/invoker.properties new file mode 100644 index 000000000..f12518fee --- /dev/null +++ b/src/it/aggregate-download-licenses-extended-excel/invoker.properties @@ -0,0 +1,23 @@ +### +# #%L +# License Maven Plugin +# %% +# Copyright (C) 2008 - 2011 CodeLutin, Codehaus, Tony Chemit +# %% +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Lesser Public License for more details. +# +# You should have received a copy of the GNU General Lesser Public +# License along with this program. If not, see +# . +# #L% +### +invoker.goals=clean license:aggregate-download-licenses +invoker.failureBehavior=fail-fast \ No newline at end of file diff --git a/src/it/aggregate-download-licenses-extended-excel/pom.xml b/src/it/aggregate-download-licenses-extended-excel/pom.xml new file mode 100644 index 000000000..86b40b4a7 --- /dev/null +++ b/src/it/aggregate-download-licenses-extended-excel/pom.xml @@ -0,0 +1,76 @@ + + + + + + 4.0.0 + + org.codehaus.mojo.license.test + test-aggregate-download-licenses-extended-excel + @project.version@ + + + child1 + child2 + + + License Test :: aggregate-download-licenses - Extended Excel + + pom + + + UTF-8 + true + + + + + + + org.codehaus.mojo + license-maven-plugin + @project.version@ + + true + true + + The Apache Software License, Version 2.0|Apache License, Version 2.0|Apache Public License + 2.0 + + + + + + + + + + + org.sonarsource.sonarlint.core + sonarlint-core + 9.2.0.74516 + + + \ No newline at end of file diff --git a/src/it/aggregate-download-licenses-extended-excel/postbuild.groovy b/src/it/aggregate-download-licenses-extended-excel/postbuild.groovy new file mode 100644 index 000000000..72c3c2864 --- /dev/null +++ b/src/it/aggregate-download-licenses-extended-excel/postbuild.groovy @@ -0,0 +1,68 @@ +/* + * #%L + * License Maven Plugin + * %% + * Copyright (C) 2008 - 2011 CodeLutin, Codehaus, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * . + * #L% + */ +import java.util.logging.Level +import java.util.logging.Logger + +import org.apache.poi.ss.usermodel.Cell +import org.apache.poi.ss.usermodel.CellType +import org.apache.poi.ss.usermodel.Row +import org.apache.poi.ss.usermodel.Sheet +import org.apache.poi.ss.usermodel.WorkbookFactory + +log = Logger.getLogger("test-aggregate-download-licenses-extended-excel") + +static boolean searchText(Sheet sheet, String searchText) { + def log2 = Logger.getLogger("test-aggregate-download-licenses-extended-excel-search") + + for (Iterator rowIterator = sheet.rowIterator(); rowIterator.hasNext();) { + Row row = rowIterator.next() + for (Iterator cellIterator = row.cellIterator(); cellIterator.hasNext();) { + Cell cell = cellIterator.next() + if (cell.cellType == CellType.STRING || cell.cellType == CellType.BLANK) { + def cellValue = cell.stringCellValue + if (cellValue == searchText) { + return true + } else { + log2.log(Level.FINEST, "Cell Value: {}", cellValue) + } + } + } + } + return false +} + +file = new File(basedir, 'target/generated-resources/licenses.xlsx'); +assert file.exists() +assert file.length() > 100 + +searchText = "YourSearchText" +input = new FileInputStream(file) +// So it can be easily opened and inspected manually. In a modern IDE it's just a (double-)click in the log output. +log.log(Level.FINE, "Excel export at: {}", file.absolutePath) +workbook = WorkbookFactory.create(input) +Sheet sheet = workbook.getSheetAt(0) + +assert searchText(sheet, "Maven information") +assert searchText(sheet, "Apache Software Foundation") +assert searchText(sheet, "The Apache Software Foundation") + +input.close() \ No newline at end of file diff --git a/src/main/java/org/codehaus/mojo/license/AbstractAddThirdPartyMojo.java b/src/main/java/org/codehaus/mojo/license/AbstractAddThirdPartyMojo.java index 3a44b1cd1..3853fc35d 100644 --- a/src/main/java/org/codehaus/mojo/license/AbstractAddThirdPartyMojo.java +++ b/src/main/java/org/codehaus/mojo/license/AbstractAddThirdPartyMojo.java @@ -58,21 +58,6 @@ import org.eclipse.aether.transfer.ArtifactNotFoundException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.eclipse.aether.resolution.ArtifactResolutionException; -import org.eclipse.aether.transfer.ArtifactNotFoundException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.IOException; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.SortedMap; -import java.util.SortedSet; /** * Abstract mojo for all third-party mojos. diff --git a/src/main/java/org/codehaus/mojo/license/AbstractDownloadLicensesMojo.java b/src/main/java/org/codehaus/mojo/license/AbstractDownloadLicensesMojo.java index f196daf06..29a93a64b 100644 --- a/src/main/java/org/codehaus/mojo/license/AbstractDownloadLicensesMojo.java +++ b/src/main/java/org/codehaus/mojo/license/AbstractDownloadLicensesMojo.java @@ -22,6 +22,9 @@ * #L% */ +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.TransformerException; + import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; @@ -71,27 +74,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.transform.TransformerException; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Set; -import java.util.TreeMap; -import java.util.regex.Pattern; - /** * Created on 23/05/16. * @@ -266,8 +248,9 @@ public abstract class AbstractDownloadLicensesMojo extends AbstractLicensesXmlMo * * @since 2.1 */ - @Parameter( property = "license.licensesExcelErrorFile", - defaultValue = "${project.build.directory}/generated-resources/licenses-errors.xlsx" ) + @Parameter( + property = "license.licensesExcelErrorFile", + defaultValue = "${project.build.directory}/generated-resources/licenses-errors.xlsx") private File licensesExcelErrorFile; /** @@ -701,7 +684,7 @@ public abstract class AbstractDownloadLicensesMojo extends AbstractLicensesXmlMo * * @since 2.1 */ - @Parameter( property = "license.writeExcelFile", defaultValue = "false" ) + @Parameter(property = "license.writeExcelFile", defaultValue = "false") private boolean writeExcelFile; /** @@ -713,8 +696,9 @@ public abstract class AbstractDownloadLicensesMojo extends AbstractLicensesXmlMo * @see AggregateDownloadLicensesMojo#extendedInfo * @since 2.1 */ - @Parameter( property = "licensesExcelOutputFile", - defaultValue = "${project.build.directory}/generated-resources/licenses.xlsx" ) + @Parameter( + property = "licensesExcelOutputFile", + defaultValue = "${project.build.directory}/generated-resources/licenses.xlsx") protected File licensesExcelOutputFile; // ---------------------------------------------------------------------- @@ -838,7 +822,7 @@ public void execute() throws MojoExecutionException, MojoFailureException { } } - filterCopyrightLines( depProjectLicenses ); + filterCopyrightLines(depProjectLicenses); } catch (IOException e) { throw new RuntimeException(e); } @@ -849,8 +833,9 @@ public void execute() throws MojoExecutionException, MojoFailureException { } List depProjectLicensesWithErrors = filterErrors(depProjectLicenses); - if ( !CollectionUtils.isEmpty( depProjectLicensesWithErrors ) ) { - writeLicenseSummaries( depProjectLicensesWithErrors, licensesErrorsFile, licensesExcelErrorFile ); + writeLicenseSummaries(depProjectLicenses, licensesOutputFile, licensesExcelOutputFile); + if (!CollectionUtils.isEmpty(depProjectLicensesWithErrors)) { + writeLicenseSummaries(depProjectLicensesWithErrors, licensesErrorsFile, licensesExcelErrorFile); } removeOrphanFiles(depProjectLicenses); @@ -877,15 +862,12 @@ public void execute() throws MojoExecutionException, MojoFailureException { } } - private void writeLicenseSummaries( List depProjectLicenses, - File licensesOutputFile, - File licensesExcelOutputFile ) - throws ParserConfigurationException, TransformerException, IOException - { - writeLicenseSummary( depProjectLicenses, licensesOutputFile, writeVersions ); - if ( writeExcelFile ) - { - ExcelFileWriter.write( depProjectLicenses, licensesExcelOutputFile ); + private void writeLicenseSummaries( + List depProjectLicenses, File licensesOutputFile, File licensesExcelOutputFile) + throws ParserConfigurationException, TransformerException, IOException { + writeLicenseSummary(depProjectLicenses, licensesOutputFile, writeVersions); + if (writeExcelFile) { + ExcelFileWriter.write(depProjectLicenses, licensesExcelOutputFile); } } @@ -895,24 +877,20 @@ private void writeLicenseSummaries( List depProjectLicenses, * * @param depProjectLicenses Projects with extracted copyright lines. */ - private void filterCopyrightLines( List depProjectLicenses ) - { - for ( ProjectLicenseInfo projectLicenseInfo : depProjectLicenses ) - { - if ( projectLicenseInfo.getExtendedInfo() == null - || CollectionUtils.isEmpty( projectLicenseInfo.getExtendedInfo().getInfoFiles() ) ) - { + private void filterCopyrightLines(List depProjectLicenses) { + for (ProjectLicenseInfo projectLicenseInfo : depProjectLicenses) { + if (projectLicenseInfo.getExtendedInfo() == null + || CollectionUtils.isEmpty( + projectLicenseInfo.getExtendedInfo().getInfoFiles())) { continue; } List infoFiles = projectLicenseInfo.getExtendedInfo().getInfoFiles(); - for ( InfoFile infoFile : infoFiles ) - { - if ( cache.hasNormalizedContent( infoFile.getNormalizedContent() ) ) - { - LOG.debug( "Removed extracted copyright lines for " + for (InfoFile infoFile : infoFiles) { + if (cache.hasNormalizedContent(infoFile.getNormalizedContent())) { + LOG.debug("Removed extracted copyright lines for " + projectLicenseInfo.getExtendedInfo().getName() - + " (" + projectLicenseInfo.toGavString() + ")" ); - infoFile.setExtractedCopyrightLines( null ); + + " (" + projectLicenseInfo.toGavString() + ")"); + infoFile.setExtractedCopyrightLines(null); } } } @@ -1006,7 +984,7 @@ private List filterErrors(List depProjec while (it.hasNext()) { final ProjectLicenseInfo dep = it.next(); final List messages = dep.getDownloaderMessages(); - if (messages != null && !messages.isEmpty()) { + if (CollectionUtils.isNotEmpty(messages)) { it.remove(); result.add(dep); } @@ -1125,7 +1103,10 @@ private Proxy findActiveProxy() throws MojoExecutionException { */ private ProjectLicenseInfo createDependencyProject(LicensedArtifact depMavenProject) throws MojoFailureException { final ProjectLicenseInfo dependencyProject = new ProjectLicenseInfo( - depMavenProject.getGroupId(), depMavenProject.getArtifactId(), depMavenProject.getVersion(), depMavenProject.getExtendedInfos()); + depMavenProject.getGroupId(), + depMavenProject.getArtifactId(), + depMavenProject.getVersion(), + depMavenProject.getExtendedInfos()); final List licenses = depMavenProject.getLicenses(); for (org.codehaus.mojo.license.download.License license : licenses) { dependencyProject.addLicense(new ProjectLicense( diff --git a/src/main/java/org/codehaus/mojo/license/AbstractLicensesXmlMojo.java b/src/main/java/org/codehaus/mojo/license/AbstractLicensesXmlMojo.java index c1f92b5de..cd20e2de2 100644 --- a/src/main/java/org/codehaus/mojo/license/AbstractLicensesXmlMojo.java +++ b/src/main/java/org/codehaus/mojo/license/AbstractLicensesXmlMojo.java @@ -158,9 +158,9 @@ protected Path[] getAutodetectEolFiles() { } protected void writeLicenseSummary(List deps, File licensesOutputFile, boolean writeVersions) - throws ParserConfigurationException, TransformerException, IOException { + throws ParserConfigurationException, TransformerException, IOException { initEncoding(); LicenseSummaryWriter.writeLicenseSummary( - deps, licensesOutputFile, charset, licensesOutputFileEol, writeVersions); + deps, licensesOutputFile, charset, licensesOutputFileEol, writeVersions); } } diff --git a/src/main/java/org/codehaus/mojo/license/AbstractThirdPartyReportMojo.java b/src/main/java/org/codehaus/mojo/license/AbstractThirdPartyReportMojo.java index 2ee510c01..171c4e6ab 100644 --- a/src/main/java/org/codehaus/mojo/license/AbstractThirdPartyReportMojo.java +++ b/src/main/java/org/codehaus/mojo/license/AbstractThirdPartyReportMojo.java @@ -384,21 +384,9 @@ protected void executeReport(Locale locale) throws MavenReportException { try { init(); details = createThirdPartyDetails(); - } catch (IOException e) { - throw new MavenReportException(e.getMessage(), e); - } catch (ThirdPartyToolException e) { - throw new MavenReportException(e.getMessage(), e); - } catch (ProjectBuildingException e) { - throw new MavenReportException(e.getMessage(), e); - } catch (ArtifactNotFoundException e) { - throw new MavenReportException(e.getMessage(), e); - } catch (ArtifactResolutionException e) { - throw new MavenReportException(e.getMessage(), e); - } catch (MojoFailureException e) { - throw new MavenReportException(e.getMessage(), e); - } catch (DependenciesToolException e) { - throw new MavenReportException(e.getMessage(), e); - } catch (MojoExecutionException e) { + } catch (IOException | ThirdPartyToolException | ArtifactNotFoundException | ArtifactResolutionException | + ProjectBuildingException | MojoFailureException | DependenciesToolException | + MojoExecutionException e) { throw new MavenReportException(e.getMessage(), e); } diff --git a/src/main/java/org/codehaus/mojo/license/AggregateDownloadLicensesMojo.java b/src/main/java/org/codehaus/mojo/license/AggregateDownloadLicensesMojo.java index 18bb287d1..d4a27018c 100644 --- a/src/main/java/org/codehaus/mojo/license/AggregateDownloadLicensesMojo.java +++ b/src/main/java/org/codehaus/mojo/license/AggregateDownloadLicensesMojo.java @@ -105,7 +105,7 @@ public class AggregateDownloadLicensesMojo extends AbstractDownloadLicensesMojo * * @since 2.1 */ - @Parameter( property = "license.extendedInfo", defaultValue = "false" ) + @Parameter(property = "license.extendedInfo", defaultValue = "false") private boolean extendedInfo; // ---------------------------------------------------------------------- @@ -126,11 +126,13 @@ protected boolean isSkip() { protected Map getDependencies() { final Map result = new TreeMap<>(); - for ( MavenProject p : reactorProjects ) - { - licensedArtifactResolver.loadProjectDependencies( new ResolvedProjectDependencies( p.getArtifacts(), - p.getDependencyArtifacts() ), - this, remoteRepositories, result, extendedInfo ); + for (MavenProject p : reactorProjects) { + licensedArtifactResolver.loadProjectDependencies( + new ResolvedProjectDependencies(p.getArtifacts(), MojoHelper.getDependencyArtifacts(p)), + this, + remoteRepositories, + result, + extendedInfo); } return result; } diff --git a/src/main/java/org/codehaus/mojo/license/AggregatorAddThirdPartyMojo.java b/src/main/java/org/codehaus/mojo/license/AggregatorAddThirdPartyMojo.java index 2c3d5ce33..f2d691482 100644 --- a/src/main/java/org/codehaus/mojo/license/AggregatorAddThirdPartyMojo.java +++ b/src/main/java/org/codehaus/mojo/license/AggregatorAddThirdPartyMojo.java @@ -46,14 +46,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.SortedMap; -import java.util.SortedSet; - /** * This goal forks executions of the add-third-party goal for all the leaf projects * of the tree of modules below the point where it is executed. Note that this diff --git a/src/main/java/org/codehaus/mojo/license/DownloadLicensesMojo.java b/src/main/java/org/codehaus/mojo/license/DownloadLicensesMojo.java index c891d93c1..1edf507aa 100644 --- a/src/main/java/org/codehaus/mojo/license/DownloadLicensesMojo.java +++ b/src/main/java/org/codehaus/mojo/license/DownloadLicensesMojo.java @@ -85,8 +85,11 @@ protected boolean isSkip() { protected Map getDependencies() { final Map result = new TreeMap<>(); licensedArtifactResolver.loadProjectDependencies( - new ResolvedProjectDependencies( project.getArtifacts(), MojoHelper.getDependencyArtifacts(project) ), - this, remoteRepositories, result, false ); + new ResolvedProjectDependencies(project.getArtifacts(), MojoHelper.getDependencyArtifacts(project)), + this, + remoteRepositories, + result, + false); return result; } } diff --git a/src/main/java/org/codehaus/mojo/license/LicensesXmlInsertVersionsMojo.java b/src/main/java/org/codehaus/mojo/license/LicensesXmlInsertVersionsMojo.java index 203bb820d..7675e9073 100644 --- a/src/main/java/org/codehaus/mojo/license/LicensesXmlInsertVersionsMojo.java +++ b/src/main/java/org/codehaus/mojo/license/LicensesXmlInsertVersionsMojo.java @@ -130,8 +130,11 @@ public ArtifactFilters getArtifactFilters() { }; final Map resolvedDeps = new TreeMap(); licensedArtifactResolver.loadProjectDependencies( - new ResolvedProjectDependencies( project.getArtifacts(), MojoHelper.getDependencyArtifacts(project) ), - config, remoteRepositories, resolvedDeps, false ); + new ResolvedProjectDependencies(project.getArtifacts(), MojoHelper.getDependencyArtifacts(project)), + config, + remoteRepositories, + resolvedDeps, + false); final Map resolvedDepsMap = new HashMap<>(resolvedDeps.size()); for (LicensedArtifact dep : resolvedDeps.values()) { resolvedDepsMap.put(dep.getGroupId() + ":" + dep.getArtifactId(), dep); diff --git a/src/main/java/org/codehaus/mojo/license/api/DefaultThirdPartyHelper.java b/src/main/java/org/codehaus/mojo/license/api/DefaultThirdPartyHelper.java index 8c1f84362..4915b2608 100644 --- a/src/main/java/org/codehaus/mojo/license/api/DefaultThirdPartyHelper.java +++ b/src/main/java/org/codehaus/mojo/license/api/DefaultThirdPartyHelper.java @@ -22,19 +22,6 @@ * #L% */ -import org.apache.commons.collections.CollectionUtils; -import org.apache.maven.artifact.Artifact; -import org.apache.maven.artifact.repository.ArtifactRepository; -import org.apache.maven.plugin.MojoExecutionException; -import org.apache.maven.plugin.MojoFailureException; -import org.apache.maven.project.MavenProject; -import org.apache.maven.project.ProjectBuildingException; -import org.codehaus.mojo.license.model.LicenseMap; -import org.codehaus.mojo.license.utils.SortedProperties; -import org.eclipse.aether.repository.RemoteRepository; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.io.File; import java.io.IOException; import java.util.ArrayList; diff --git a/src/main/java/org/codehaus/mojo/license/download/Cache.java b/src/main/java/org/codehaus/mojo/license/download/Cache.java index b3cca51d6..3a0880b68 100644 --- a/src/main/java/org/codehaus/mojo/license/download/Cache.java +++ b/src/main/java/org/codehaus/mojo/license/download/Cache.java @@ -38,7 +38,7 @@ * @since 1.18 */ public class Cache { - private static final Logger LOG = LoggerFactory.getLogger( Cache.class ); + private static final Logger LOG = LoggerFactory.getLogger(Cache.class); private final Map urlToFile = new HashMap<>(); @@ -68,9 +68,8 @@ public LicenseDownloadResult get(String url) { * @param normalizedContentChecksum Normalized file content. * @return If the cache has a license file with the same normalized content. */ - public boolean hasNormalizedContent( String normalizedContentChecksum ) - { - return normalizedContentToFile.get( normalizedContentChecksum ) != null; + public boolean hasNormalizedContent(String normalizedContentChecksum) { + return normalizedContentToFile.get(normalizedContentChecksum) != null; } /** @@ -105,13 +104,10 @@ public void put(String url, LicenseDownloadResult entry) { + "' together with URLs '" + sb.toString() + "'"); } final String normalizedContentChecksum = entry.getNormalizedContentChecksum(); - if ( normalizedContentChecksum != null ) - { - normalizedContentToFile.put( normalizedContentChecksum, entry ); - } - else - { - LOG.warn( "Couldn't find normalized content checksum for license download " + entry ); + if (normalizedContentChecksum != null) { + normalizedContentToFile.put(normalizedContentChecksum, entry); + } else { + LOG.warn("Couldn't find normalized content checksum for license download " + entry); } } urlToFile.put(url, entry); diff --git a/src/main/java/org/codehaus/mojo/license/download/LicenseDownloader.java b/src/main/java/org/codehaus/mojo/license/download/LicenseDownloader.java index f3d19d965..c22893101 100644 --- a/src/main/java/org/codehaus/mojo/license/download/LicenseDownloader.java +++ b/src/main/java/org/codehaus/mojo/license/download/LicenseDownloader.java @@ -22,6 +22,26 @@ * #L% */ +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.regex.Pattern; + import org.apache.commons.codec.binary.Hex; import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.io.IOUtils; @@ -55,26 +75,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.net.URI; -import java.net.URISyntaxException; -import java.nio.charset.Charset; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.regex.Pattern; - /** * Utilities for downloading remote license files. * @@ -306,8 +306,8 @@ public void close() throws IOException { */ public static class LicenseDownloadResult { public static LicenseDownloadResult success(File file, String sha1, boolean preferredFileName) { - final LicenseDownloadResult licenseDownloadResult - = new LicenseDownloadResult( file, sha1, preferredFileName, null ); + final LicenseDownloadResult licenseDownloadResult = + new LicenseDownloadResult(file, sha1, preferredFileName, null); licenseDownloadResult.calculateFileChecksum(); return licenseDownloadResult; } @@ -367,8 +367,7 @@ public String getSha1() { return sha1; } - public String getNormalizedContentChecksum() - { + public String getNormalizedContentChecksum() { return normalizedContentChecksum; } @@ -376,14 +375,12 @@ public LicenseDownloadResult withFile(File otherFile) { return new LicenseDownloadResult(otherFile, sha1, preferredFileName, errorMessage); } - public void calculateFileChecksum() - { - normalizedContentChecksum = LicenseDownloader.calculateFileChecksum( file ); + public void calculateFileChecksum() { + normalizedContentChecksum = LicenseDownloader.calculateFileChecksum(file); } @Override - public String toString() - { + public String toString() { return "LicenseDownloadResult{" + "file=" + file + ", errorMessage='" + errorMessage + '\'' @@ -394,51 +391,42 @@ public String toString() } } - private static String calculateFileChecksum( File file ) - { - try ( InputStream inputStream = new FileInputStream( file ) ) - { - byte[] content = IOUtils.readFully( inputStream, (int) file.length() ); - String contentString = new String( content ); - return calculateStringChecksum( contentString ); - } - catch ( IOException e ) - { - LOG.error( "Error reading license file and normalizing it ", e ); + private static String calculateFileChecksum(File file) { + try (InputStream inputStream = new FileInputStream(file)) { + byte[] content = IOUtils.readFully(inputStream, (int) file.length()); + String contentString = new String(content); + return calculateStringChecksum(contentString); + } catch (IOException e) { + LOG.error("Error reading license file and normalizing it ", e); return null; } } - public static String calculateStringChecksum( String contentString ) - { - contentString = normalizeString( contentString ); - try - { - final MessageDigest md = MessageDigest.getInstance( "SHA-1" ); - return Hex.encodeHexString( md.digest( contentString.getBytes() ) ); - } - catch ( NoSuchAlgorithmException e ) - { - LOG.error( "Error fetching SHA-1 hashsum generator ", e ); + public static String calculateStringChecksum(String contentString) { + contentString = normalizeString(contentString); + try { + final MessageDigest md = MessageDigest.getInstance("SHA-1"); + return Hex.encodeHexString(md.digest(contentString.getBytes())); + } catch (NoSuchAlgorithmException e) { + LOG.error("Error fetching SHA-1 hashsum generator ", e); return null; } } - private static String normalizeString( String contentString ) - { + private static String normalizeString(String contentString) { return contentString // Windows - .replace( "\r\n", " " ) + .replace("\r\n", " ") // Classic MacOS - .replace( "\r", " " ) + .replace("\r", " ") // *nix - .replace( "\n", " " ) + .replace("\n", " ") // Set all spaces, tabs, etc. to one space width - .replaceAll( "\\s\\s+", " " ) + .replaceAll("\\s\\s+", " ") /* License files exist which are completely identical, except that someone changed to . */ - .replace( "http://", "https://" ) + .replace("http://", "https://") // All to lowercase .toLowerCase(); } diff --git a/src/main/java/org/codehaus/mojo/license/download/LicenseSummaryWriter.java b/src/main/java/org/codehaus/mojo/license/download/LicenseSummaryWriter.java index b77c6942e..a3cebc666 100644 --- a/src/main/java/org/codehaus/mojo/license/download/LicenseSummaryWriter.java +++ b/src/main/java/org/codehaus/mojo/license/download/LicenseSummaryWriter.java @@ -22,16 +22,6 @@ * #L% */ -import org.apache.commons.collections.CollectionUtils; -import org.apache.maven.model.Developer; -import org.apache.maven.model.Organization; -import org.apache.maven.model.Scm; -import org.codehaus.mojo.license.Eol; -import org.codehaus.mojo.license.extended.ExtendedInfo; -import org.codehaus.mojo.license.extended.InfoFile; -import org.w3c.dom.Document; -import org.w3c.dom.Node; - import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; @@ -54,7 +44,13 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.apache.commons.collections.CollectionUtils; +import org.apache.maven.model.Developer; +import org.apache.maven.model.Organization; +import org.apache.maven.model.Scm; import org.codehaus.mojo.license.Eol; +import org.codehaus.mojo.license.extended.ExtendedInfo; +import org.codehaus.mojo.license.extended.InfoFile; import org.w3c.dom.Document; import org.w3c.dom.Node; @@ -121,7 +117,7 @@ public static Node createDependencyNode(Document doc, ProjectLicenseInfo dep, bo if (hasDownloaderMessages) { Node matchLicensesNode = doc.createElement("matchLicenses"); - if (dep.getLicenses() == null || dep.getLicenses().size() == 0) { + if (dep.getLicenses() == null || dep.getLicenses().isEmpty()) { matchLicensesNode.appendChild(doc.createComment(" Match dependency with no licenses ")); } else { for (ProjectLicense lic : dep.getLicenses()) { @@ -131,39 +127,47 @@ public static Node createDependencyNode(Document doc, ProjectLicenseInfo dep, bo depNode.appendChild(matchLicensesNode); } - if ( dep.getExtendedInfo() != null ) - { + if (dep.getExtendedInfo() != null) { ExtendedInfo extendedInfo = dep.getExtendedInfo(); - addTextPropertyIfSet( doc, depNode, "name", extendedInfo.getName() ); - addTextPropertyIfSet( doc, depNode, "bundleLicense", extendedInfo.getBundleLicense() ); - addCdataIfSet( doc, depNode, "bundleVendor", extendedInfo.getBundleVendor() ); - appendChildNodesIfSet( doc, depNode, "developers", extendedInfo.getDevelopers(), - ( doc1, developer ) -> createDeveloperNode( doc, developer ) ); - addCdataIfSet( doc, depNode, "implementationVendor", extendedInfo.getImplementationVendor() ); - addTextPropertyIfSet( doc, depNode, "inceptionYear", extendedInfo.getInceptionYear() ); - appendChildNodesIfSet( doc, depNode, "infoFiles", extendedInfo.getInfoFiles(), - ( doc1, infoFile ) -> createInfoFileNode( doc, infoFile ) ); - if ( extendedInfo.getOrganization() != null - && ( extendedInfo.getOrganization().getName() != null - || extendedInfo.getOrganization().getUrl() != null ) ) - { - Node organizationNode = doc.createElement( "organization" ); + addTextPropertyIfSet(doc, depNode, "name", extendedInfo.getName()); + addTextPropertyIfSet(doc, depNode, "bundleLicense", extendedInfo.getBundleLicense()); + addCdataIfSet(doc, depNode, "bundleVendor", extendedInfo.getBundleVendor()); + appendChildNodesIfSet( + doc, + depNode, + "developers", + extendedInfo.getDevelopers(), + (doc1, developer) -> createDeveloperNode(doc, developer)); + addCdataIfSet(doc, depNode, "implementationVendor", extendedInfo.getImplementationVendor()); + addTextPropertyIfSet(doc, depNode, "inceptionYear", extendedInfo.getInceptionYear()); + appendChildNodesIfSet( + doc, + depNode, + "infoFiles", + extendedInfo.getInfoFiles(), + (doc1, infoFile) -> createInfoFileNode(doc, infoFile)); + if (extendedInfo.getOrganization() != null + && (extendedInfo.getOrganization().getName() != null + || extendedInfo.getOrganization().getUrl() != null)) { + Node organizationNode = doc.createElement("organization"); final Organization organization = extendedInfo.getOrganization(); - addTextPropertyIfSet( doc, organizationNode, "name", organization.getName() ); - addTextPropertyIfSet( doc, organizationNode, "url", organization.getUrl() ); - depNode.appendChild( organizationNode ); + addTextPropertyIfSet(doc, organizationNode, "name", organization.getName()); + addTextPropertyIfSet(doc, organizationNode, "url", organization.getUrl()); + depNode.appendChild(organizationNode); } - addTextPropertyIfSet( doc, depNode, "scm", Optional.ofNullable( extendedInfo.getScm() ) - .map( Scm::getUrl ) - .orElse( null ) ); - addTextPropertyIfSet( doc, depNode, "url", extendedInfo.getUrl() ); + addTextPropertyIfSet( + doc, + depNode, + "scm", + Optional.ofNullable(extendedInfo.getScm()).map(Scm::getUrl).orElse(null)); + addTextPropertyIfSet(doc, depNode, "url", extendedInfo.getUrl()); } Node licensesNode = doc.createElement("licenses"); - if ( CollectionUtils.isEmpty( dep.getLicenses() ) ) - { - final String comment = - hasDownloaderMessages ? " Manually add license elements here: " : " No license information available. "; + if (CollectionUtils.isEmpty(dep.getLicenses())) { + final String comment = hasDownloaderMessages + ? " Manually add license elements here: " + : " No license information available. "; licensesNode.appendChild(doc.createComment(comment)); } else { if (hasDownloaderMessages) { @@ -193,22 +197,22 @@ public static Node createDependencyNode(Document doc, ProjectLicenseInfo dep, bo * * @param Type in collection to add as child node entries. */ - interface CreateSubNode - { - Node createSubNode( Document doc, T t ); + interface CreateSubNode { + Node createSubNode(Document doc, T t); } - private static void appendChildNodesIfSet( Document doc, Node parentNode, String elementName, - Collection collection, CreateSubNode createSubNode ) - { - if ( !CollectionUtils.isEmpty( collection ) ) - { - Node developersNode = doc.createElement( elementName ); - for ( T t : collection ) - { - developersNode.appendChild( createSubNode.createSubNode( doc, t ) ); + private static void appendChildNodesIfSet( + Document doc, + Node parentNode, + String elementName, + Collection collection, + CreateSubNode createSubNode) { + if (!CollectionUtils.isEmpty(collection)) { + Node developersNode = doc.createElement(elementName); + for (T t : collection) { + developersNode.appendChild(createSubNode.createSubNode(doc, t)); } - parentNode.appendChild( developersNode ); + parentNode.appendChild(developersNode); } } @@ -248,47 +252,42 @@ public static Node createLicenseNode(Document doc, ProjectLicense lic, boolean i return licenseNode; } - private static Node createDeveloperNode( Document doc, Developer developer ) - { - Node developerNode = doc.createElement( "developer" ); + private static Node createDeveloperNode(Document doc, Developer developer) { + Node developerNode = doc.createElement("developer"); - addTextPropertyIfSet( doc, developerNode, "id", developer.getId() ); - addTextPropertyIfSet( doc, developerNode, "email", developer.getEmail() ); - addTextPropertyIfSet( doc, developerNode, "name", developer.getName() ); - addTextPropertyIfSet( doc, developerNode, "organization", developer.getOrganization() ); - addTextPropertyIfSet( doc, developerNode, "organizationUrl", developer.getOrganizationUrl() ); - addTextPropertyIfSet( doc, developerNode, "url", developer.getUrl() ); - addTextPropertyIfSet( doc, developerNode, "timezone", developer.getTimezone() ); + addTextPropertyIfSet(doc, developerNode, "id", developer.getId()); + addTextPropertyIfSet(doc, developerNode, "email", developer.getEmail()); + addTextPropertyIfSet(doc, developerNode, "name", developer.getName()); + addTextPropertyIfSet(doc, developerNode, "organization", developer.getOrganization()); + addTextPropertyIfSet(doc, developerNode, "organizationUrl", developer.getOrganizationUrl()); + addTextPropertyIfSet(doc, developerNode, "url", developer.getUrl()); + addTextPropertyIfSet(doc, developerNode, "timezone", developer.getTimezone()); return developerNode; } - private static Node createInfoFileNode( Document doc, InfoFile infoFile ) - { - Node infoFileNode = doc.createElement( "infoFile" ); + private static Node createInfoFileNode(Document doc, InfoFile infoFile) { + Node infoFileNode = doc.createElement("infoFile"); - addCdataIfSet( doc, infoFileNode, "content", infoFile.getContent() ); - appendChildNodesIfSet( doc, infoFileNode, "extractedCopyrightLines", infoFile.getExtractedCopyrightLines(), - ( doc1, line ) -> { - Node devNameNode = doc.createElement( "line" ); - devNameNode.appendChild( doc.createCDATASection( line ) ); + addCdataIfSet(doc, infoFileNode, "content", infoFile.getContent()); + appendChildNodesIfSet( + doc, infoFileNode, "extractedCopyrightLines", infoFile.getExtractedCopyrightLines(), (doc1, line) -> { + Node devNameNode = doc.createElement("line"); + devNameNode.appendChild(doc.createCDATASection(line)); return devNameNode; - } ); - addCdataIfSet( doc, infoFileNode, "fileName", infoFile.getFileName() ); - addTextPropertyIfSet( doc, infoFileNode, "type", infoFile.getType().toString() ); + }); + addCdataIfSet(doc, infoFileNode, "fileName", infoFile.getFileName()); + addTextPropertyIfSet(doc, infoFileNode, "type", infoFile.getType().toString()); return infoFileNode; } - private static void addTextPropertyIfSet( Document doc, Node parentNode, String elementName, String property ) - { - addPropertyIfSet( doc, parentNode, elementName, property, () -> doc.createTextNode( property ) ); + private static void addTextPropertyIfSet(Document doc, Node parentNode, String elementName, String property) { + addPropertyIfSet(doc, parentNode, elementName, property, () -> doc.createTextNode(property)); } - private static void addCdataIfSet( Document doc, Node parentNode, String elementName, String property ) - { - addPropertyIfSet( doc, parentNode, elementName, property, - () -> doc.createCDATASection( prepareCdata( property ) ) ); + private static void addCdataIfSet(Document doc, Node parentNode, String elementName, String property) { + addPropertyIfSet(doc, parentNode, elementName, property, () -> doc.createCDATASection(prepareCdata(property))); } /** @@ -298,19 +297,16 @@ private static void addCdataIfSet( Document doc, Node parentNode, String element * @param property Property to prepare being written as XML CDATA * @return The properly prepared string. */ - private static String prepareCdata( String property ) - { - return property.replace( "\r\n", "\n" ); + private static String prepareCdata(String property) { + return property.replace("\r\n", "\n"); } - private static void addPropertyIfSet( Document doc, Node parentNode, String elementName, - String property, Supplier nodeSupplier ) - { - if ( property != null ) - { - Node devNameNode = doc.createElement( elementName ); - devNameNode.appendChild( nodeSupplier.get() ); - parentNode.appendChild( devNameNode ); + private static void addPropertyIfSet( + Document doc, Node parentNode, String elementName, String property, Supplier nodeSupplier) { + if (property != null) { + Node devNameNode = doc.createElement(elementName); + devNameNode.appendChild(nodeSupplier.get()); + parentNode.appendChild(devNameNode); } } diff --git a/src/main/java/org/codehaus/mojo/license/download/LicensedArtifact.java b/src/main/java/org/codehaus/mojo/license/download/LicensedArtifact.java index 97d5a8f6b..ec6799d5c 100644 --- a/src/main/java/org/codehaus/mojo/license/download/LicensedArtifact.java +++ b/src/main/java/org/codehaus/mojo/license/download/LicensedArtifact.java @@ -22,22 +22,6 @@ * #L% */ -import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang3.tuple.ImmutablePair; -import org.apache.commons.lang3.tuple.Pair; -import org.apache.maven.artifact.Artifact; -import org.apache.maven.model.Developer; -import org.apache.maven.model.Organization; -import org.apache.maven.model.Scm; -import org.codehaus.mojo.license.spdx.SpdxLicenseInfo; -import org.codehaus.mojo.license.spdx.SpdxLicenseList; -import org.codehaus.mojo.license.extended.ExtendedInfo; -import org.codehaus.mojo.license.extended.InfoFile; -import org.osgi.framework.Constants; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; @@ -52,15 +36,31 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipFile; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; +import org.apache.maven.artifact.Artifact; +import org.apache.maven.model.Developer; +import org.apache.maven.model.Organization; +import org.apache.maven.model.Scm; +import org.codehaus.mojo.license.extended.ExtendedInfo; +import org.codehaus.mojo.license.extended.InfoFile; +import org.codehaus.mojo.license.spdx.SpdxLicenseInfo; +import org.codehaus.mojo.license.spdx.SpdxLicenseList; +import org.osgi.framework.Constants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * @author Peter Palaga, Jan-Hendrik Diederich (for the extended information) * @since 1.20 */ public class LicensedArtifact { - private static final Logger LOG = LoggerFactory.getLogger( LicensedArtifact.class ); + private static final Logger LOG = LoggerFactory.getLogger(LicensedArtifact.class); - public static Builder builder( Artifact artifact, boolean useNonMavenData ) { - return new Builder( artifact, useNonMavenData ); + public static Builder builder(Artifact artifact, boolean useNonMavenData) { + return new Builder(artifact, useNonMavenData); } private final String groupId; @@ -75,9 +75,13 @@ public static Builder builder( Artifact artifact, boolean useNonMavenData ) { private final ExtendedInfo extendedInfos; - LicensedArtifact( String groupId, String artifactId, String version, List licenses, - List errorMessages, ExtendedInfo extendedInfos ) - { + LicensedArtifact( + String groupId, + String artifactId, + String version, + List licenses, + List errorMessages, + ExtendedInfo extendedInfos) { super(); this.groupId = groupId; this.artifactId = artifactId; @@ -147,25 +151,20 @@ public List getErrorMessages() { * @return Extended information. * @since 2.1.0 */ - public ExtendedInfo getExtendedInfos() - { + public ExtendedInfo getExtendedInfos() { return extendedInfos; } /** * A {@link LicensedArtifact} builder. */ - public static class Builder - { - public Builder( Artifact artifact, boolean useNonMavenData ) - { + public static class Builder { + public Builder(Artifact artifact, boolean useNonMavenData) { super(); this.groupId = artifact.getGroupId(); this.artifactId = artifact.getArtifactId(); this.version = artifact.getVersion(); - this.extendedInfos = useNonMavenData - ? extraInfosFromArtifact( artifact ) - : null; + this.extendedInfos = useNonMavenData ? extraInfosFromArtifact(artifact) : null; } private final String groupId; @@ -195,113 +194,88 @@ public LicensedArtifact build() { licenses = null; final List msgs = Collections.unmodifiableList(errorMessages); errorMessages = null; - return new LicensedArtifact( groupId, artifactId, version, lics, msgs, extendedInfos ); + return new LicensedArtifact(groupId, artifactId, version, lics, msgs, extendedInfos); } - private ExtendedInfo extraInfosFromArtifact( Artifact artifact ) - { - if ( artifact.getFile() == null ) - { - LOG.error( "Artifact " + artifact + " has no valid file set" ); + private ExtendedInfo extraInfosFromArtifact(Artifact artifact) { + if (artifact.getFile() == null) { + LOG.error("Artifact " + artifact + " has no valid file set"); return null; } ExtendedInfo result = new ExtendedInfo(); - result.setArtifact( artifact ); - try ( ZipFile zipFile = new ZipFile( artifact.getFile() ) ) - { + result.setArtifact(artifact); + try (ZipFile zipFile = new ZipFile(artifact.getFile())) { Enumeration entries = zipFile.entries(); - while ( entries.hasMoreElements() ) - { + while (entries.hasMoreElements()) { ZipEntry zipEntry = entries.nextElement(); final String fileName = zipEntry.getName().toLowerCase(); - if ( textFileMatcher( fileName, "notice" ) ) - { + if (textFileMatcher(fileName, "notice")) { // Should match "NOTICE.txt", "NOTICES.txt"..., // if someone decides to go slightly against convention. - final InfoFile infoFile = buildInfoFile( zipFile, zipEntry, InfoFile.Type.NOTICE ); - result.getInfoFiles().add( infoFile ); - } - else if ( textFileMatcher( fileName, "license", "licence" ) ) - { + final InfoFile infoFile = buildInfoFile(zipFile, zipEntry, InfoFile.Type.NOTICE); + result.getInfoFiles().add(infoFile); + } else if (textFileMatcher(fileName, "license", "licence")) { // Match against british and american english writing type of "license" - final InfoFile infoFile = buildInfoFile( zipFile, zipEntry, InfoFile.Type.LICENSE ); - result.getInfoFiles().add( infoFile ); - } - else if ( fileMatchesSpdxId( fileName ) ) - { - final InfoFile infoFile = buildInfoFile( zipFile, zipEntry, InfoFile.Type.SPDX_LICENSE ); - result.getInfoFiles().add( infoFile ); - } - else if ( fileName.equals( "meta-inf/manifest.mf" ) ) - { - try ( InputStream inputStream = zipFile.getInputStream( zipEntry ) ) - { - Manifest manifest = new Manifest( inputStream ); + final InfoFile infoFile = buildInfoFile(zipFile, zipEntry, InfoFile.Type.LICENSE); + result.getInfoFiles().add(infoFile); + } else if (fileMatchesSpdxId(fileName)) { + final InfoFile infoFile = buildInfoFile(zipFile, zipEntry, InfoFile.Type.SPDX_LICENSE); + result.getInfoFiles().add(infoFile); + } else if (fileName.equals("meta-inf/manifest.mf")) { + try (InputStream inputStream = zipFile.getInputStream(zipEntry)) { + Manifest manifest = new Manifest(inputStream); final Attributes mainAttributes = manifest.getMainAttributes(); // Fetch Java standard JAR manifest attributes. - final Object implementationVendor = mainAttributes - .get( Attributes.Name.IMPLEMENTATION_VENDOR ); - if ( implementationVendor instanceof String ) - { - result.setImplementationVendor( (String) implementationVendor ); + final Object implementationVendor = + mainAttributes.get(Attributes.Name.IMPLEMENTATION_VENDOR); + if (implementationVendor instanceof String) { + result.setImplementationVendor((String) implementationVendor); } // Fetch OSGI framework JAR manifest attributes. - final String bundleVendor = mainAttributes.getValue( Constants.BUNDLE_VENDOR ); - result.setBundleVendor( bundleVendor ); - final String bundleLicense = mainAttributes.getValue( Constants.BUNDLE_LICENSE ); - result.setBundleLicense( bundleLicense ); - } - catch ( IOException e ) - { - LOG.warn( "Error at reading data from jar manifest", e ); + final String bundleVendor = mainAttributes.getValue(Constants.BUNDLE_VENDOR); + result.setBundleVendor(bundleVendor); + final String bundleLicense = mainAttributes.getValue(Constants.BUNDLE_LICENSE); + result.setBundleLicense(bundleLicense); + } catch (IOException e) { + LOG.warn("Error at reading data from jar manifest", e); } } } - } - catch ( IOException e ) - { - LOG.warn( "Can't open zip file \"" + artifact.getFile() + "\"", e ); + } catch (IOException e) { + LOG.warn("Can't open zip file \"" + artifact.getFile() + "\"", e); } return result; } - private InfoFile buildInfoFile( ZipFile zipFile, ZipEntry zipEntry, InfoFile.Type type ) - { + private InfoFile buildInfoFile(ZipFile zipFile, ZipEntry zipEntry, InfoFile.Type type) { InfoFile infoFile = new InfoFile(); - infoFile.setFileName( zipEntry.getName() ); - infoFile.setType( type ); - Pair contentWithLines = readZipEntryTextLines( zipFile, zipEntry ); - if ( contentWithLines != null ) - { - Set copyrights = scanForCopyrights( contentWithLines.getRight(), "(c)", "copyright" ); - if ( !CollectionUtils.isEmpty( copyrights ) ) - { - infoFile.getExtractedCopyrightLines().addAll( copyrights ); + infoFile.setFileName(zipEntry.getName()); + infoFile.setType(type); + Pair contentWithLines = readZipEntryTextLines(zipFile, zipEntry); + if (contentWithLines != null) { + Set copyrights = scanForCopyrights(contentWithLines.getRight(), "(c)", "copyright"); + if (!CollectionUtils.isEmpty(copyrights)) { + infoFile.getExtractedCopyrightLines().addAll(copyrights); } - infoFile.setContent( contentWithLines.getLeft() ); + infoFile.setContent(contentWithLines.getLeft()); } return infoFile; } - private boolean fileMatchesSpdxId( String fileName ) - { + private boolean fileMatchesSpdxId(String fileName) { final SpdxLicenseList spdxList = SpdxLicenseList.getLatest(); - for ( Map.Entry entry : spdxList.getLicenses().entrySet() ) - { - if ( textFileMatcher( fileName, entry.getValue().getLicenseId().toLowerCase() ) ) - { + for (Map.Entry entry : + spdxList.getLicenses().entrySet()) { + if (textFileMatcher(fileName, entry.getValue().getLicenseId().toLowerCase())) { return true; } } return false; } - private boolean textFileMatcher( String fileName, String... matchStrings ) - { - for ( String matchString : matchStrings ) - { - if ( fileName.matches( ".*" + matchString + ".*\\.txt" ) ) - { + private boolean textFileMatcher(String fileName, String... matchStrings) { + for (String matchString : matchStrings) { + if (fileName.matches(".*" + matchString + ".*\\.txt")) { return true; } } @@ -315,88 +289,67 @@ private boolean textFileMatcher( String fileName, String... matchStrings ) * @param copyrightMatchers Lines containing one of these strings are returned. Arguments must be all lowercase. * @return The found lines containing copyright claims. */ - private Set scanForCopyrights( String[] lines, String... copyrightMatchers ) - { - if ( lines == null ) - { + private Set scanForCopyrights(String[] lines, String... copyrightMatchers) { + if (lines == null) { return null; } Set result = new HashSet<>(); - for ( String line : lines ) - { - for ( String copyrightMatcher : copyrightMatchers ) - { + for (String line : lines) { + for (String copyrightMatcher : copyrightMatchers) { final String trimmedLine = line.trim(); - if ( trimmedLine.toLowerCase().contains( copyrightMatcher ) ) - { - result.add( trimmedLine ); + if (trimmedLine.toLowerCase().contains(copyrightMatcher)) { + result.add(trimmedLine); } } } return result; } - private Pair readZipEntryTextLines( ZipFile zipFile, ZipEntry zipEntry ) - { - try ( InputStream inputStream = zipFile.getInputStream( zipEntry ) ) - { - byte[] content = IOUtils.readFully( inputStream, (int) zipEntry.getSize() ); - String contentString = new String( content ); - return new ImmutablePair<>( contentString, contentString.split( "\\R+" ) ); - } - catch ( IOException e ) - { - LOG.warn( "Can't read zip file entry " + zipEntry, e ); + private Pair readZipEntryTextLines(ZipFile zipFile, ZipEntry zipEntry) { + try (InputStream inputStream = zipFile.getInputStream(zipEntry)) { + byte[] content = IOUtils.readFully(inputStream, (int) zipEntry.getSize()); + String contentString = new String(content); + return new ImmutablePair<>(contentString, contentString.split("\\R+")); + } catch (IOException e) { + LOG.warn("Can't read zip file entry " + zipEntry, e); return null; } } - public void setInceptionYear( String inceptionYear ) - { - if ( extendedInfos != null ) - { - this.extendedInfos.setInceptionYear( inceptionYear ); + public void setInceptionYear(String inceptionYear) { + if (extendedInfos != null) { + this.extendedInfos.setInceptionYear(inceptionYear); } } - public void setOrganization( Organization organization ) - { - if ( extendedInfos != null ) - { - this.extendedInfos.setOrganization( organization ); + public void setOrganization(Organization organization) { + if (extendedInfos != null) { + this.extendedInfos.setOrganization(organization); } } - public void setDevelopers( List developers ) - { - if ( extendedInfos != null ) - { - this.extendedInfos.setDevelopers( developers ); + public void setDevelopers(List developers) { + if (extendedInfos != null) { + this.extendedInfos.setDevelopers(developers); } } - public void setUrl( String url ) - { - if ( extendedInfos != null ) - { - this.extendedInfos.setUrl( url ); + public void setUrl(String url) { + if (extendedInfos != null) { + this.extendedInfos.setUrl(url); } } - public void setScm( Scm scm ) - { - if ( extendedInfos != null ) - { - this.extendedInfos.setScm( scm ); + public void setScm(Scm scm) { + if (extendedInfos != null) { + this.extendedInfos.setScm(scm); } } - public void setName( String name ) - { - if ( extendedInfos != null ) - { - this.extendedInfos.setName( name ); + public void setName(String name) { + if (extendedInfos != null) { + this.extendedInfos.setName(name); } } } -} \ No newline at end of file +} diff --git a/src/main/java/org/codehaus/mojo/license/download/LicensedArtifactResolver.java b/src/main/java/org/codehaus/mojo/license/download/LicensedArtifactResolver.java index 8cd991a1f..67db14819 100644 --- a/src/main/java/org/codehaus/mojo/license/download/LicensedArtifactResolver.java +++ b/src/main/java/org/codehaus/mojo/license/download/LicensedArtifactResolver.java @@ -93,8 +93,7 @@ public void loadProjectDependencies( MavenProjectDependenciesConfigurator configuration, List remoteRepositories, Map result, - boolean extendedInfo ) - { + boolean extendedInfo) { final ArtifactFilters artifactFilters = configuration.getArtifactFilters(); final boolean excludeTransitiveDependencies = configuration.isExcludeTransitiveDependencies(); @@ -152,20 +151,18 @@ public void loadProjectDependencies( LOG.debug("Dependency [{}] already present in the result", id); } else { // build project - final Builder laBuilder = LicensedArtifact.builder( artifact, extendedInfo ); - try - { + final Builder laBuilder = LicensedArtifact.builder(artifact, extendedInfo); + try { final MavenProject project = mavenProjectBuilder .build(artifact, true, projectBuildingRequest) .getProject(); - if ( extendedInfo ) - { - laBuilder.setName( project.getName() ); - laBuilder.setInceptionYear( project.getInceptionYear() ); - laBuilder.setOrganization( project.getOrganization() ); - laBuilder.setDevelopers( project.getDevelopers() ); - laBuilder.setUrl( project.getUrl() ); - laBuilder.setScm( project.getScm() ); + if (extendedInfo) { + laBuilder.setName(project.getName()); + laBuilder.setInceptionYear(project.getInceptionYear()); + laBuilder.setOrganization(project.getOrganization()); + laBuilder.setDevelopers(project.getDevelopers()); + laBuilder.setUrl(project.getUrl()); + laBuilder.setScm(project.getScm()); } List lics = project.getLicenses(); if (lics != null) { diff --git a/src/main/java/org/codehaus/mojo/license/download/ProjectLicenseInfo.java b/src/main/java/org/codehaus/mojo/license/download/ProjectLicenseInfo.java index 4fb6dc659..3ad7ff109 100644 --- a/src/main/java/org/codehaus/mojo/license/download/ProjectLicenseInfo.java +++ b/src/main/java/org/codehaus/mojo/license/download/ProjectLicenseInfo.java @@ -22,14 +22,12 @@ * #L% */ -import org.apache.maven.artifact.Artifact; -import org.codehaus.mojo.license.extended.ExtendedInfo; - import java.util.ArrayList; import java.util.List; import java.util.Objects; import org.apache.maven.artifact.Artifact; +import org.codehaus.mojo.license.extended.ExtendedInfo; /** * Contains the license information for a single project/dependency @@ -60,7 +58,7 @@ public class ProjectLicenseInfo { */ public ProjectLicenseInfo() {} - public ProjectLicenseInfo( String groupId, String artifactId, String version, ExtendedInfo extendedInfo ) { + public ProjectLicenseInfo(String groupId, String artifactId, String version, ExtendedInfo extendedInfo) { this.groupId = groupId; this.artifactId = artifactId; this.version = version; @@ -221,8 +219,7 @@ public boolean isApproved() { return approved; } - public ExtendedInfo getExtendedInfo() - { + public ExtendedInfo getExtendedInfo() { return extendedInfo; } } diff --git a/src/main/java/org/codehaus/mojo/license/extended/ExtendedInfo.java b/src/main/java/org/codehaus/mojo/license/extended/ExtendedInfo.java index 05cf69bc0..24a7b7d0e 100644 --- a/src/main/java/org/codehaus/mojo/license/extended/ExtendedInfo.java +++ b/src/main/java/org/codehaus/mojo/license/extended/ExtendedInfo.java @@ -22,20 +22,19 @@ * #L% */ +import java.util.ArrayList; +import java.util.List; + import org.apache.maven.artifact.Artifact; import org.apache.maven.model.Developer; import org.apache.maven.model.Organization; import org.apache.maven.model.Scm; -import java.util.ArrayList; -import java.util.List; - /** * Class which contains extended licensing information which was found in other files in the JAR, * not only Mavens pom.xml's. */ -public class ExtendedInfo -{ +public class ExtendedInfo { private String name; private Artifact artifact; private List infoFiles = new ArrayList<>(); @@ -49,113 +48,91 @@ public class ExtendedInfo private Scm scm; private String url; - public Artifact getArtifact() - { + public Artifact getArtifact() { return artifact; } - public void setArtifact( Artifact artifact ) - { + public void setArtifact(Artifact artifact) { this.artifact = artifact; } - public List getInfoFiles() - { + public List getInfoFiles() { return infoFiles; } - public void setInfoFiles( List infoFiles ) - { + public void setInfoFiles(List infoFiles) { this.infoFiles = infoFiles; } - public String getImplementationVendor() - { + public String getImplementationVendor() { return implementationVendor; } - public void setImplementationVendor( String implementationVendor ) - { + public void setImplementationVendor(String implementationVendor) { this.implementationVendor = implementationVendor; } - public String getBundleVendor() - { + public String getBundleVendor() { return bundleVendor; } - public void setBundleVendor( String bundleVendor ) - { + public void setBundleVendor(String bundleVendor) { this.bundleVendor = bundleVendor; } - public String getBundleLicense() - { + public String getBundleLicense() { return bundleLicense; } - public void setBundleLicense( String bundleLicense ) - { + public void setBundleLicense(String bundleLicense) { this.bundleLicense = bundleLicense; } - public String getInceptionYear() - { + public String getInceptionYear() { return inceptionYear; } - public void setInceptionYear( String inceptionYear ) - { + public void setInceptionYear(String inceptionYear) { this.inceptionYear = inceptionYear; } - public Organization getOrganization() - { + public Organization getOrganization() { return organization; } - public void setOrganization( Organization organization ) - { + public void setOrganization(Organization organization) { this.organization = organization; } - public List getDevelopers() - { + public List getDevelopers() { return developers; } - public void setDevelopers( List developers ) - { + public void setDevelopers(List developers) { this.developers = developers; } - public Scm getScm() - { + public Scm getScm() { return scm; } - public void setScm( Scm scm ) - { + public void setScm(Scm scm) { this.scm = scm; } - public String getUrl() - { + public String getUrl() { return url; } - public void setUrl( String url ) - { + public void setUrl(String url) { this.url = url; } - public String getName() - { + public String getName() { return name; } - public void setName( String name ) - { + public void setName(String name) { this.name = name; } -} \ No newline at end of file +} diff --git a/src/main/java/org/codehaus/mojo/license/extended/InfoFile.java b/src/main/java/org/codehaus/mojo/license/extended/InfoFile.java index 0834bd09d..af7e59c5e 100644 --- a/src/main/java/org/codehaus/mojo/license/extended/InfoFile.java +++ b/src/main/java/org/codehaus/mojo/license/extended/InfoFile.java @@ -22,21 +22,19 @@ * #L% */ -import org.codehaus.mojo.license.download.LicenseDownloader; - import java.util.HashSet; import java.util.Set; +import org.codehaus.mojo.license.download.LicenseDownloader; + /** * Information about a NOTICE or LICENSE file. */ -public class InfoFile -{ +public class InfoFile { /** * The type of the source for the info file. */ - public enum Type - { + public enum Type { /** * Generic ...NOTICE....txt file. */ @@ -58,49 +56,40 @@ public enum Type private String normalizedContent; - public String getFileName() - { + public String getFileName() { return fileName; } - public void setFileName( String fileName ) - { + public void setFileName(String fileName) { this.fileName = fileName; } - public String getContent() - { + public String getContent() { return content; } - public void setContent( String content ) - { + public void setContent(String content) { this.content = content; - this.normalizedContent = LicenseDownloader.calculateStringChecksum( content ); + this.normalizedContent = LicenseDownloader.calculateStringChecksum(content); } - public Set getExtractedCopyrightLines() - { + public Set getExtractedCopyrightLines() { return extractedCopyrightLines; } - public void setExtractedCopyrightLines( Set extractedCopyrightLines ) - { + public void setExtractedCopyrightLines(Set extractedCopyrightLines) { this.extractedCopyrightLines = extractedCopyrightLines; } - public Type getType() - { + public Type getType() { return type; } - public void setType( Type type ) - { + public void setType(Type type) { this.type = type; } - public String getNormalizedContent() - { + public String getNormalizedContent() { return normalizedContent; } -} \ No newline at end of file +} diff --git a/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/ExcelFileWriter.java b/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/ExcelFileWriter.java index 05f0fff02..09d4c7c64 100644 --- a/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/ExcelFileWriter.java +++ b/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/ExcelFileWriter.java @@ -22,6 +22,18 @@ * #L% */ +import java.awt.Color; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.function.BiConsumer; + import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.ImmutablePair; @@ -57,41 +69,33 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.awt.Color; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.function.BiConsumer; - /** * Writes project license infos into Excel file. */ -public class ExcelFileWriter -{ - private static final Logger LOG = LoggerFactory.getLogger( ExcelFileWriter.class ); +public class ExcelFileWriter { + private static final Logger LOG = LoggerFactory.getLogger(ExcelFileWriter.class); // Columns values for Maven data, including separator gaps for data grouping. - private static final int GENERAL_START_COLUMN = 0, GENERAL_COLUMNS = 1, + private static final int GENERAL_START_COLUMN = 0, + GENERAL_COLUMNS = 1, GENERAL_END_COLUMN = GENERAL_START_COLUMN + GENERAL_COLUMNS; - private static final int PLUGIN_ID_START_COLUMN = GENERAL_END_COLUMN + 1, PLUGIN_ID_COLUMNS = 3, + private static final int PLUGIN_ID_START_COLUMN = GENERAL_END_COLUMN + 1, + PLUGIN_ID_COLUMNS = 3, PLUGIN_ID_END_COLUMN = PLUGIN_ID_START_COLUMN + PLUGIN_ID_COLUMNS; // "Start" column are the actual start columns, they are inclusive. // "End" columns point just one column behind the last one, it's the exclusive column index. - private static final int LICENSES_START_COLUMN = PLUGIN_ID_END_COLUMN + 1, LICENSES_COLUMNS = 5, + private static final int LICENSES_START_COLUMN = PLUGIN_ID_END_COLUMN + 1, + LICENSES_COLUMNS = 5, LICENSES_END_COLUMN = LICENSES_START_COLUMN + LICENSES_COLUMNS; - private static final int DEVELOPERS_START_COLUMN = LICENSES_END_COLUMN + 1, DEVELOPERS_COLUMNS = 7, + private static final int DEVELOPERS_START_COLUMN = LICENSES_END_COLUMN + 1, + DEVELOPERS_COLUMNS = 7, DEVELOPERS_END_COLUMN = DEVELOPERS_START_COLUMN + DEVELOPERS_COLUMNS; - private static final int MISC_START_COLUMN = DEVELOPERS_END_COLUMN + 1, MISC_COLUMNS = 4, + private static final int MISC_START_COLUMN = DEVELOPERS_END_COLUMN + 1, + MISC_COLUMNS = 4, MISC_END_COLUMN = MISC_START_COLUMN + MISC_COLUMNS; - - private static final int MAVEN_DATA_COLUMNS = GENERAL_COLUMNS + PLUGIN_ID_COLUMNS + LICENSES_COLUMNS - + DEVELOPERS_COLUMNS + MISC_COLUMNS, + private static final int + MAVEN_DATA_COLUMNS = + GENERAL_COLUMNS + PLUGIN_ID_COLUMNS + LICENSES_COLUMNS + DEVELOPERS_COLUMNS + MISC_COLUMNS, MAVEN_COLUMN_GROUPING_GAPS = 4; private static final int MAVEN_START_COLUMN = 0, MAVEN_COLUMNS = MAVEN_DATA_COLUMNS + MAVEN_COLUMN_GROUPING_GAPS, @@ -99,18 +103,26 @@ public class ExcelFileWriter // Columns values for JAR data, including separator gaps for data grouping. private static final int INFO_FILES_GAPS = 2, MANIFEST_GAPS = 1; - private static final int MANIFEST_START_COLUMN = MAVEN_COLUMNS + 1, MANIFEST_COLUMNS = 3, + private static final int MANIFEST_START_COLUMN = MAVEN_COLUMNS + 1, + MANIFEST_COLUMNS = 3, MANIFEST_END_COLUMN = MANIFEST_START_COLUMN + MANIFEST_COLUMNS; - private static final int INFO_NOTICES_START_COLUMN = MANIFEST_END_COLUMN + 1, INFO_NOTICES_COLUMNS = 3, + private static final int INFO_NOTICES_START_COLUMN = MANIFEST_END_COLUMN + 1, + INFO_NOTICES_COLUMNS = 3, INFO_NOTICES_END_COLUMN = INFO_NOTICES_START_COLUMN + INFO_NOTICES_COLUMNS; - private static final int INFO_LICENSES_START_COLUMN = INFO_NOTICES_END_COLUMN + 1, INFO_LICENSES_COLUMNS = 3, + private static final int INFO_LICENSES_START_COLUMN = INFO_NOTICES_END_COLUMN + 1, + INFO_LICENSES_COLUMNS = 3, INFO_LICENSES_END_COLUMN = INFO_LICENSES_START_COLUMN + INFO_LICENSES_COLUMNS; - private static final int INFO_SPDX_START_COLUMN = INFO_LICENSES_END_COLUMN + 1, INFO_SPDX_COLUMNS = 3, + private static final int INFO_SPDX_START_COLUMN = INFO_LICENSES_END_COLUMN + 1, + INFO_SPDX_COLUMNS = 3, INFO_SPDX_END_COLUMN = INFO_SPDX_START_COLUMN + INFO_SPDX_COLUMNS; private static final int EXTENDED_INFO_START_COLUMN = MAVEN_END_COLUMN + 1, - EXTENDED_INFO_COLUMNS = MANIFEST_COLUMNS - + INFO_NOTICES_COLUMNS + INFO_LICENSES_COLUMNS + INFO_SPDX_COLUMNS - + INFO_FILES_GAPS + MANIFEST_GAPS, + EXTENDED_INFO_COLUMNS = + MANIFEST_COLUMNS + + INFO_NOTICES_COLUMNS + + INFO_LICENSES_COLUMNS + + INFO_SPDX_COLUMNS + + INFO_FILES_GAPS + + MANIFEST_GAPS, EXTENDED_INFO_END_COLUMN = EXTENDED_INFO_START_COLUMN + EXTENDED_INFO_COLUMNS; // Width of gap columns @@ -119,8 +131,12 @@ public class ExcelFileWriter private static final BorderStyle HEADER_CELLS_BORDER_STYLE = BorderStyle.MEDIUM; private static final int TIMEZONE_WIDTH = " Timezone ".length() * EXCEL_WIDTH_SCALE, INCEPTION_YEAR_WIDTH = " Inception Year ".length() * EXCEL_WIDTH_SCALE; - // Color must be dark enough for low contrast monitors - private static final Color ALTERNATING_ROWS_COLOR = new Color( 220, 220, 220 ); + /** + * Color must be dark enough for low contrast monitors. + *
If you get a compile error here, make sure you're using Java 8, not higher. + */ + private static final Color ALTERNATING_ROWS_COLOR = new Color(220, 220, 220); + private static final String COPYRIGHT_JOIN_SEPARATOR = "§"; /** @@ -129,41 +145,33 @@ public class ExcelFileWriter * @param projectLicenseInfos Project license infos to write. * @param licensesExcelOutputFile Excel output file in latest format (OOXML). */ - public static void write( List projectLicenseInfos, final File licensesExcelOutputFile ) - { - if ( CollectionUtils.isEmpty( projectLicenseInfos ) ) - { - LOG.debug( "Nothing to write to excel, no project data." ); + public static void write(List projectLicenseInfos, final File licensesExcelOutputFile) { + if (CollectionUtils.isEmpty(projectLicenseInfos)) { + LOG.debug("Nothing to write to excel, no project data."); return; } final XSSFWorkbook wb = new XSSFWorkbook(); - final Sheet sheet = wb.createSheet( WorkbookUtil.createSafeSheetName( "License information" ) ); + final Sheet sheet = wb.createSheet(WorkbookUtil.createSafeSheetName("License information")); final IndexedColorMap colorMap = wb.getStylesSource().getIndexedColors(); - final XSSFColor alternatingRowsColor = new XSSFColor( ALTERNATING_ROWS_COLOR, colorMap ); + final XSSFColor alternatingRowsColor = new XSSFColor(ALTERNATING_ROWS_COLOR, colorMap); - createHeader( projectLicenseInfos, wb, sheet ); + createHeader(projectLicenseInfos, wb, sheet); - writeData( projectLicenseInfos, wb, sheet, alternatingRowsColor ); + writeData(projectLicenseInfos, wb, sheet, alternatingRowsColor); - try ( OutputStream fileOut = new FileOutputStream( licensesExcelOutputFile ) ) - { - wb.write( fileOut ); - } - catch ( IOException e ) - { - LOG.error( "Error on storing Excel file with license and other information", e ); + try (OutputStream fileOut = new FileOutputStream(licensesExcelOutputFile)) { + wb.write(fileOut); + } catch (IOException e) { + LOG.error("Error on storing Excel file with license and other information", e); } } - private static void createHeader( List projectLicenseInfos, Workbook wb, Sheet sheet ) - { + private static void createHeader(List projectLicenseInfos, Workbook wb, Sheet sheet) { boolean hasExtendedInfo = false; - for ( ProjectLicenseInfo projectLicenseInfo : projectLicenseInfos ) - { - if ( projectLicenseInfo.getExtendedInfo() != null ) - { + for (ProjectLicenseInfo projectLicenseInfo : projectLicenseInfos) { + if (projectLicenseInfo.getExtendedInfo() != null) { hasExtendedInfo = true; break; } @@ -171,389 +179,469 @@ private static void createHeader( List projectLicenseInfos, // Create header style CellStyle headerCellStyle = wb.createCellStyle(); - headerCellStyle.setFillForegroundColor( IndexedColors.LIGHT_GREEN.getIndex() ); - headerCellStyle.setFillPattern( FillPatternType.SOLID_FOREGROUND ); + headerCellStyle.setFillForegroundColor(IndexedColors.LIGHT_GREEN.getIndex()); + headerCellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); Font headerFont = wb.createFont(); - headerFont.setBold( true ); - headerCellStyle.setFont( headerFont ); - headerCellStyle.setAlignment( HorizontalAlignment.CENTER ); - setBorderStyle( headerCellStyle, HEADER_CELLS_BORDER_STYLE ); + headerFont.setBold(true); + headerCellStyle.setFont(headerFont); + headerCellStyle.setAlignment(HorizontalAlignment.CENTER); + setBorderStyle(headerCellStyle, HEADER_CELLS_BORDER_STYLE); // Create 1st header row. The Maven/JAR header row - Row mavenJarRow = sheet.createRow( 0 ); + Row mavenJarRow = sheet.createRow(0); // Create Maven header cell - createMergedCellsInRow( sheet, MAVEN_START_COLUMN, MAVEN_END_COLUMN, headerCellStyle, mavenJarRow, - "Maven information", 0 ); + createMergedCellsInRow( + sheet, MAVEN_START_COLUMN, MAVEN_END_COLUMN, headerCellStyle, mavenJarRow, "Maven information", 0); - if ( hasExtendedInfo ) - { + if (hasExtendedInfo) { // Create JAR header cell - createMergedCellsInRow( sheet, EXTENDED_INFO_START_COLUMN, EXTENDED_INFO_END_COLUMN, - headerCellStyle, mavenJarRow, - "JAR Content", 0 ); + createMergedCellsInRow( + sheet, + EXTENDED_INFO_START_COLUMN, + EXTENDED_INFO_END_COLUMN, + headerCellStyle, + mavenJarRow, + "JAR Content", + 0); } // Create 2nd header row - Row secondHeaderRow = sheet.createRow( 1 ); + Row secondHeaderRow = sheet.createRow(1); // Create Maven "General" header - createMergedCellsInRow( sheet, GENERAL_START_COLUMN, GENERAL_END_COLUMN, headerCellStyle, secondHeaderRow, - "General", 1 ); + createMergedCellsInRow( + sheet, GENERAL_START_COLUMN, GENERAL_END_COLUMN, headerCellStyle, secondHeaderRow, "General", 1); // Create Maven "Plugin ID" header - createMergedCellsInRow( sheet, PLUGIN_ID_START_COLUMN, PLUGIN_ID_END_COLUMN, headerCellStyle, secondHeaderRow, - "Plugin ID", 1 ); + createMergedCellsInRow( + sheet, PLUGIN_ID_START_COLUMN, PLUGIN_ID_END_COLUMN, headerCellStyle, secondHeaderRow, "Plugin ID", 1); // Gap "General" <-> "Plugin ID". - sheet.setColumnWidth( GENERAL_END_COLUMN, GAP_WIDTH ); + sheet.setColumnWidth(GENERAL_END_COLUMN, GAP_WIDTH); // Create Maven "Licenses" header - createMergedCellsInRow( sheet, LICENSES_START_COLUMN, LICENSES_END_COLUMN, headerCellStyle, secondHeaderRow, - "Licenses", 1 ); + createMergedCellsInRow( + sheet, LICENSES_START_COLUMN, LICENSES_END_COLUMN, headerCellStyle, secondHeaderRow, "Licenses", 1); // Gap "Plugin ID" <-> "Licenses". - sheet.setColumnWidth( PLUGIN_ID_END_COLUMN, GAP_WIDTH ); + sheet.setColumnWidth(PLUGIN_ID_END_COLUMN, GAP_WIDTH); // Create Maven "Developers" header - createMergedCellsInRow( sheet, DEVELOPERS_START_COLUMN, DEVELOPERS_END_COLUMN, headerCellStyle, + createMergedCellsInRow( + sheet, + DEVELOPERS_START_COLUMN, + DEVELOPERS_END_COLUMN, + headerCellStyle, secondHeaderRow, - "Developers", 1 ); + "Developers", + 1); // Gap "Licenses" <-> "Developers". - sheet.setColumnWidth( LICENSES_END_COLUMN, GAP_WIDTH ); + sheet.setColumnWidth(LICENSES_END_COLUMN, GAP_WIDTH); // Create Maven "Miscellaneous" header - createMergedCellsInRow( sheet, MISC_START_COLUMN, MISC_END_COLUMN, headerCellStyle, - secondHeaderRow, - "Miscellaneous", 1 ); + createMergedCellsInRow( + sheet, MISC_START_COLUMN, MISC_END_COLUMN, headerCellStyle, secondHeaderRow, "Miscellaneous", 1); // Gap "Developers" <-> "Miscellaneous". - sheet.setColumnWidth( DEVELOPERS_END_COLUMN, GAP_WIDTH ); - - if ( hasExtendedInfo ) - { - createMergedCellsInRow( sheet, MANIFEST_START_COLUMN, MANIFEST_END_COLUMN, headerCellStyle, + sheet.setColumnWidth(DEVELOPERS_END_COLUMN, GAP_WIDTH); + + if (hasExtendedInfo) { + createMergedCellsInRow( + sheet, + MANIFEST_START_COLUMN, + MANIFEST_END_COLUMN, + headerCellStyle, secondHeaderRow, - "MANIFEST.MF", 1 ); + "MANIFEST.MF", + 1); // Gap "Miscellaneous" <-> "MANIFEST.MF". - sheet.setColumnWidth( DEVELOPERS_END_COLUMN, GAP_WIDTH ); + sheet.setColumnWidth(DEVELOPERS_END_COLUMN, GAP_WIDTH); - createMergedCellsInRow( sheet, INFO_NOTICES_START_COLUMN, INFO_NOTICES_END_COLUMN, headerCellStyle, + createMergedCellsInRow( + sheet, + INFO_NOTICES_START_COLUMN, + INFO_NOTICES_END_COLUMN, + headerCellStyle, secondHeaderRow, - "Notices text files", 1 ); + "Notices text files", + 1); // Gap "MANIFEST.MF" <-> "Notice text files". - sheet.setColumnWidth( MANIFEST_END_COLUMN, GAP_WIDTH ); + sheet.setColumnWidth(MANIFEST_END_COLUMN, GAP_WIDTH); - createMergedCellsInRow( sheet, INFO_LICENSES_START_COLUMN, INFO_LICENSES_END_COLUMN, headerCellStyle, + createMergedCellsInRow( + sheet, + INFO_LICENSES_START_COLUMN, + INFO_LICENSES_END_COLUMN, + headerCellStyle, secondHeaderRow, - "License text files", 1 ); + "License text files", + 1); // Gap "Notice text files" <-> "License text files". - sheet.setColumnWidth( INFO_NOTICES_END_COLUMN, GAP_WIDTH ); + sheet.setColumnWidth(INFO_NOTICES_END_COLUMN, GAP_WIDTH); - createMergedCellsInRow( sheet, INFO_SPDX_START_COLUMN, INFO_SPDX_END_COLUMN, headerCellStyle, + createMergedCellsInRow( + sheet, + INFO_SPDX_START_COLUMN, + INFO_SPDX_END_COLUMN, + headerCellStyle, secondHeaderRow, - "SPDX license id matched", 1 ); + "SPDX license id matched", + 1); // Gap "License text files" <-> "SPDX license matches". - sheet.setColumnWidth( INFO_LICENSES_END_COLUMN, GAP_WIDTH ); + sheet.setColumnWidth(INFO_LICENSES_END_COLUMN, GAP_WIDTH); } -// sheet.setColumnGroupCollapsed(); + // sheet.setColumnGroupCollapsed(); // Create 3rd header row - Row thirdHeaderRow = sheet.createRow( 2 ); + Row thirdHeaderRow = sheet.createRow(2); // General - createCellsInRow( thirdHeaderRow, GENERAL_START_COLUMN, headerCellStyle, "Name" ); + createCellsInRow(thirdHeaderRow, GENERAL_START_COLUMN, headerCellStyle, "Name"); // Plugin ID - createCellsInRow( thirdHeaderRow, PLUGIN_ID_START_COLUMN, headerCellStyle, - "Group ID", "Artifact ID", "Version" ); + createCellsInRow(thirdHeaderRow, PLUGIN_ID_START_COLUMN, headerCellStyle, "Group ID", "Artifact ID", "Version"); // Licenses - createCellsInRow( thirdHeaderRow, LICENSES_START_COLUMN, headerCellStyle, - "Name", "URL", "Distribution", "Comments", "File" ); + createCellsInRow( + thirdHeaderRow, + LICENSES_START_COLUMN, + headerCellStyle, + "Name", + "URL", + "Distribution", + "Comments", + "File"); // Developers - createCellsInRow( thirdHeaderRow, DEVELOPERS_START_COLUMN, headerCellStyle, - "Id", "Email", "Name", "Organization", "Organization URL", "URL", "Timezone" ); + createCellsInRow( + thirdHeaderRow, + DEVELOPERS_START_COLUMN, + headerCellStyle, + "Id", + "Email", + "Name", + "Organization", + "Organization URL", + "URL", + "Timezone"); // Miscellaneous - createCellsInRow( thirdHeaderRow, MISC_START_COLUMN, headerCellStyle, - "Inception Year", "Organization", "SCM", "URL" ); + createCellsInRow( + thirdHeaderRow, MISC_START_COLUMN, headerCellStyle, "Inception Year", "Organization", "SCM", "URL"); int headerLineCount = 3; - if ( hasExtendedInfo ) - { + if (hasExtendedInfo) { // MANIFEST.MF - createCellsInRow( thirdHeaderRow, MANIFEST_START_COLUMN, headerCellStyle, - "Bundle license", "Bundle vendor", "Implementation vendor" ); + createCellsInRow( + thirdHeaderRow, + MANIFEST_START_COLUMN, + headerCellStyle, + "Bundle license", + "Bundle vendor", + "Implementation vendor"); // 3 InfoFile groups: Notices, Licenses and SPDX-Licenses. - createInfoFileCellsInRow( thirdHeaderRow, headerCellStyle, - INFO_NOTICES_START_COLUMN, INFO_LICENSES_START_COLUMN, INFO_SPDX_START_COLUMN ); + createInfoFileCellsInRow( + thirdHeaderRow, + headerCellStyle, + INFO_NOTICES_START_COLUMN, + INFO_LICENSES_START_COLUMN, + INFO_SPDX_START_COLUMN); - sheet.createFreezePane( EXTENDED_INFO_END_COLUMN, headerLineCount ); - } - else - { - sheet.createFreezePane( MAVEN_END_COLUMN, headerLineCount ); + sheet.createFreezePane(EXTENDED_INFO_END_COLUMN, headerLineCount); + } else { + sheet.createFreezePane(MAVEN_END_COLUMN, headerLineCount); } - sheet.createFreezePane( GENERAL_END_COLUMN, headerLineCount ); + sheet.createFreezePane(GENERAL_END_COLUMN, headerLineCount); } - // TODO: Clean this method up. Too many parameters, too complicated parameters/DTO pattern. But keep it still threadsafe. - private static void writeData( List projectLicenseInfos, XSSFWorkbook wb, Sheet sheet, - XSSFColor alternatingRowsColor ) - { + // TODO: Clean this method up. Too many parameters, too complicated parameters/DTO pattern. But keep it still + // threadsafe. + private static void writeData( + List projectLicenseInfos, + XSSFWorkbook wb, + Sheet sheet, + XSSFColor alternatingRowsColor) { final int firstRowIndex = 3; int currentRowIndex = firstRowIndex; final Map rowMap = new HashMap<>(); boolean hasExtendedInfo = false; - final CellStyle hyperlinkStyleNormal = createHyperlinkStyle( wb, null ); - final CellStyle hyperlinkStyleGray = createHyperlinkStyle( wb, alternatingRowsColor ); + final CellStyle hyperlinkStyleNormal = createHyperlinkStyle(wb, null); + final CellStyle hyperlinkStyleGray = createHyperlinkStyle(wb, alternatingRowsColor); boolean grayBackground = false; XSSFCellStyle styleGray = wb.createCellStyle(); - styleGray.setFillForegroundColor( alternatingRowsColor ); - styleGray.setFillPattern( FillPatternType.SOLID_FOREGROUND ); + styleGray.setFillForegroundColor(alternatingRowsColor); + styleGray.setFillPattern(FillPatternType.SOLID_FOREGROUND); - for ( ProjectLicenseInfo projectInfo : projectLicenseInfos ) - { + for (ProjectLicenseInfo projectInfo : projectLicenseInfos) { final CellStyle cellStyle, hyperlinkStyle; - if ( grayBackground ) - { + if (grayBackground) { cellStyle = styleGray; hyperlinkStyle = hyperlinkStyleGray; - } - else - { + } else { cellStyle = null; hyperlinkStyle = hyperlinkStyleNormal; } grayBackground = !grayBackground; int extraRows = 0; - Row currentRow = sheet.createRow( currentRowIndex ); - rowMap.put( currentRowIndex, currentRow ); + Row currentRow = sheet.createRow(currentRowIndex); + rowMap.put(currentRowIndex, currentRow); // Plugin ID - createDataCellsInRow( currentRow, PLUGIN_ID_START_COLUMN, - cellStyle, projectInfo.getGroupId(), projectInfo.getArtifactId(), projectInfo.getVersion() ); + createDataCellsInRow( + currentRow, + PLUGIN_ID_START_COLUMN, + cellStyle, + projectInfo.getGroupId(), + projectInfo.getArtifactId(), + projectInfo.getVersion()); // Licenses - final CellListParameter cellListParameter = new CellListParameter( sheet, rowMap, cellStyle ); - CurrentRowData currentRowData = new CurrentRowData( currentRowIndex, extraRows, hasExtendedInfo ); - extraRows = addList( cellListParameter, currentRowData, - LICENSES_START_COLUMN, LICENSES_COLUMNS, projectInfo.getLicenses(), - ( Row licenseRow, ProjectLicense license ) -> { - Cell[] licenses = createDataCellsInRow( licenseRow, LICENSES_START_COLUMN, - cellStyle, license.getName(), license.getUrl(), - license.getDistribution(), license.getComments(), - license.getFile() ); - addHyperlinkIfExists( wb, licenses[ 1 ], hyperlinkStyle, HyperlinkType.URL ); - } ); + final CellListParameter cellListParameter = new CellListParameter(sheet, rowMap, cellStyle); + CurrentRowData currentRowData = new CurrentRowData(currentRowIndex, extraRows, hasExtendedInfo); + extraRows = addList( + cellListParameter, + currentRowData, + LICENSES_START_COLUMN, + LICENSES_COLUMNS, + projectInfo.getLicenses(), + (Row licenseRow, ProjectLicense license) -> { + Cell[] licenses = createDataCellsInRow( + licenseRow, + LICENSES_START_COLUMN, + cellStyle, + license.getName(), + license.getUrl(), + license.getDistribution(), + license.getComments(), + license.getFile()); + addHyperlinkIfExists(wb, licenses[1], hyperlinkStyle, HyperlinkType.URL); + }); final ExtendedInfo extendedInfo = projectInfo.getExtendedInfo(); - if ( extendedInfo != null ) - { + if (extendedInfo != null) { hasExtendedInfo = true; // General - createDataCellsInRow( currentRow, GENERAL_START_COLUMN, - cellStyle, extendedInfo.getName() ); + createDataCellsInRow(currentRow, GENERAL_START_COLUMN, cellStyle, extendedInfo.getName()); // Developers - currentRowData = new CurrentRowData( currentRowIndex, extraRows, hasExtendedInfo ); - extraRows = addList( cellListParameter, currentRowData, - DEVELOPERS_START_COLUMN, DEVELOPERS_COLUMNS, extendedInfo.getDevelopers(), - ( Row developerRow, Developer developer ) -> { - Cell[] licenses = createDataCellsInRow( developerRow, DEVELOPERS_START_COLUMN, - cellStyle, developer.getId(), developer.getEmail(), + currentRowData = new CurrentRowData(currentRowIndex, extraRows, hasExtendedInfo); + extraRows = addList( + cellListParameter, + currentRowData, + DEVELOPERS_START_COLUMN, + DEVELOPERS_COLUMNS, + extendedInfo.getDevelopers(), + (Row developerRow, Developer developer) -> { + Cell[] licenses = createDataCellsInRow( + developerRow, + DEVELOPERS_START_COLUMN, + cellStyle, + developer.getId(), + developer.getEmail(), developer.getName(), - developer.getOrganization(), developer.getOrganizationUrl(), - developer.getUrl(), developer.getTimezone() ); - addHyperlinkIfExists( wb, licenses[ 1 ], hyperlinkStyle, HyperlinkType.EMAIL ); - addHyperlinkIfExists( wb, licenses[ 4 ], hyperlinkStyle, HyperlinkType.URL ); - addHyperlinkIfExists( wb, licenses[ 5 ], hyperlinkStyle, HyperlinkType.URL ); - } ); + developer.getOrganization(), + developer.getOrganizationUrl(), + developer.getUrl(), + developer.getTimezone()); + addHyperlinkIfExists(wb, licenses[1], hyperlinkStyle, HyperlinkType.EMAIL); + addHyperlinkIfExists(wb, licenses[4], hyperlinkStyle, HyperlinkType.URL); + addHyperlinkIfExists(wb, licenses[5], hyperlinkStyle, HyperlinkType.URL); + }); // Miscellaneous - Cell[] miscCells = createDataCellsInRow( currentRow, MISC_START_COLUMN, - cellStyle, extendedInfo.getInceptionYear(), - Optional.ofNullable( extendedInfo.getOrganization() ) - .map( Organization::getName ) - .orElse( null ), - Optional.ofNullable( extendedInfo.getScm() ) - .map( Scm::getUrl ) - .orElse( null ), - extendedInfo.getUrl() ); - addHyperlinkIfExists( wb, miscCells[ 2 ], hyperlinkStyle, HyperlinkType.URL ); - addHyperlinkIfExists( wb, miscCells[ 3 ], hyperlinkStyle, HyperlinkType.URL ); + Cell[] miscCells = createDataCellsInRow( + currentRow, + MISC_START_COLUMN, + cellStyle, + extendedInfo.getInceptionYear(), + Optional.ofNullable(extendedInfo.getOrganization()) + .map(Organization::getName) + .orElse(null), + Optional.ofNullable(extendedInfo.getScm()) + .map(Scm::getUrl) + .orElse(null), + extendedInfo.getUrl()); + addHyperlinkIfExists(wb, miscCells[2], hyperlinkStyle, HyperlinkType.URL); + addHyperlinkIfExists(wb, miscCells[3], hyperlinkStyle, HyperlinkType.URL); // MANIFEST.MF - createDataCellsInRow( currentRow, MANIFEST_START_COLUMN, - cellStyle, extendedInfo.getBundleLicense(), extendedInfo.getBundleVendor(), - extendedInfo.getImplementationVendor() ); + createDataCellsInRow( + currentRow, + MANIFEST_START_COLUMN, + cellStyle, + extendedInfo.getBundleLicense(), + extendedInfo.getBundleVendor(), + extendedInfo.getImplementationVendor()); // Info files - if ( !CollectionUtils.isEmpty( extendedInfo.getInfoFiles() ) ) - { + if (!CollectionUtils.isEmpty(extendedInfo.getInfoFiles())) { // Sort all info files by type into 3 different lists, each list for each of the 3 types. List notices = new ArrayList<>(); List licenses = new ArrayList<>(); List spdxs = new ArrayList<>(); - extendedInfo.getInfoFiles().forEach( infoFile -> { - switch ( infoFile.getType() ) - { - case LICENSE: - licenses.add( infoFile ); - break; - case NOTICE: - notices.add( infoFile ); - break; - case SPDX_LICENSE: - spdxs.add( infoFile ); - break; - default: - break; - } - } - ); + extendedInfo.getInfoFiles().forEach(infoFile -> { + switch (infoFile.getType()) { + case LICENSE: + licenses.add(infoFile); + break; + case NOTICE: + notices.add(infoFile); + break; + case SPDX_LICENSE: + spdxs.add(infoFile); + break; + default: + break; + } + }); // InfoFile notices text file - currentRowData = new CurrentRowData( currentRowIndex, extraRows, hasExtendedInfo ); - extraRows = addInfoFileList( cellListParameter, currentRowData, - INFO_NOTICES_START_COLUMN, INFO_NOTICES_COLUMNS, notices ); + currentRowData = new CurrentRowData(currentRowIndex, extraRows, hasExtendedInfo); + extraRows = addInfoFileList( + cellListParameter, + currentRowData, + INFO_NOTICES_START_COLUMN, + INFO_NOTICES_COLUMNS, + notices); // InfoFile licenses text file - currentRowData = new CurrentRowData( currentRowIndex, extraRows, hasExtendedInfo ); - extraRows = addInfoFileList( cellListParameter, currentRowData, - INFO_LICENSES_START_COLUMN, INFO_LICENSES_COLUMNS, licenses ); + currentRowData = new CurrentRowData(currentRowIndex, extraRows, hasExtendedInfo); + extraRows = addInfoFileList( + cellListParameter, + currentRowData, + INFO_LICENSES_START_COLUMN, + INFO_LICENSES_COLUMNS, + licenses); // InfoFile spdx licenses text file - currentRowData = new CurrentRowData( currentRowIndex, extraRows, hasExtendedInfo ); - extraRows = addInfoFileList( cellListParameter, currentRowData, - INFO_SPDX_START_COLUMN, INFO_SPDX_COLUMNS, spdxs ); - } - else if ( cellListParameter.cellStyle != null ) - { - setStyleOnEmptyCells( cellListParameter, currentRowData, - INFO_NOTICES_START_COLUMN, INFO_NOTICES_COLUMNS ); - setStyleOnEmptyCells( cellListParameter, currentRowData, - INFO_LICENSES_START_COLUMN, INFO_LICENSES_COLUMNS ); - setStyleOnEmptyCells( cellListParameter, currentRowData, - INFO_SPDX_START_COLUMN, INFO_SPDX_COLUMNS ); + currentRowData = new CurrentRowData(currentRowIndex, extraRows, hasExtendedInfo); + extraRows = addInfoFileList( + cellListParameter, currentRowData, INFO_SPDX_START_COLUMN, INFO_SPDX_COLUMNS, spdxs); + } else if (cellListParameter.cellStyle != null) { + setStyleOnEmptyCells( + cellListParameter, currentRowData, INFO_NOTICES_START_COLUMN, INFO_NOTICES_COLUMNS); + setStyleOnEmptyCells( + cellListParameter, currentRowData, INFO_LICENSES_START_COLUMN, INFO_LICENSES_COLUMNS); + setStyleOnEmptyCells(cellListParameter, currentRowData, INFO_SPDX_START_COLUMN, INFO_SPDX_COLUMNS); } } currentRowIndex += extraRows + 1; } - autosizeColumns( sheet, hasExtendedInfo ); + autosizeColumns(sheet, hasExtendedInfo); } - private static CellStyle createHyperlinkStyle( XSSFWorkbook wb, XSSFColor backgroundColor ) - { + private static CellStyle createHyperlinkStyle(XSSFWorkbook wb, XSSFColor backgroundColor) { Font hyperlinkFont = wb.createFont(); - hyperlinkFont.setUnderline( XSSFFont.U_SINGLE ); - hyperlinkFont.setColor( IndexedColors.BLUE.getIndex() ); + hyperlinkFont.setUnderline(XSSFFont.U_SINGLE); + hyperlinkFont.setColor(IndexedColors.BLUE.getIndex()); XSSFCellStyle hyperlinkStyle = wb.createCellStyle(); - if ( backgroundColor != null ) - { - hyperlinkStyle.setFillForegroundColor( backgroundColor ); - hyperlinkStyle.setFillPattern( FillPatternType.SOLID_FOREGROUND ); + if (backgroundColor != null) { + hyperlinkStyle.setFillForegroundColor(backgroundColor); + hyperlinkStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); } - hyperlinkStyle.setFont( hyperlinkFont ); + hyperlinkStyle.setFont(hyperlinkFont); return hyperlinkStyle; } - private static void autosizeColumns( Sheet sheet, boolean hasExtendedInfo ) - { - autosizeColumns( sheet, - new ImmutablePair<>( GENERAL_START_COLUMN, GENERAL_END_COLUMN ), - new ImmutablePair<>( PLUGIN_ID_START_COLUMN, PLUGIN_ID_END_COLUMN ), - new ImmutablePair<>( LICENSES_START_COLUMN, LICENSES_END_COLUMN ), - new ImmutablePair<>( DEVELOPERS_START_COLUMN, DEVELOPERS_END_COLUMN - 1 ), - new ImmutablePair<>( MISC_START_COLUMN + 1, MISC_END_COLUMN ) - ); + private static void autosizeColumns(Sheet sheet, boolean hasExtendedInfo) { + autosizeColumns( + sheet, + new ImmutablePair<>(GENERAL_START_COLUMN, GENERAL_END_COLUMN), + new ImmutablePair<>(PLUGIN_ID_START_COLUMN, PLUGIN_ID_END_COLUMN), + new ImmutablePair<>(LICENSES_START_COLUMN, LICENSES_END_COLUMN), + new ImmutablePair<>(DEVELOPERS_START_COLUMN, DEVELOPERS_END_COLUMN - 1), + new ImmutablePair<>(MISC_START_COLUMN + 1, MISC_END_COLUMN)); // The column header widths are most likely wider than the actual cells content. - sheet.setColumnWidth( DEVELOPERS_END_COLUMN - 1, TIMEZONE_WIDTH ); - sheet.setColumnWidth( MISC_START_COLUMN, INCEPTION_YEAR_WIDTH ); - if ( hasExtendedInfo ) - { - autosizeColumns( sheet, - new ImmutablePair<>( MANIFEST_START_COLUMN, MANIFEST_END_COLUMN ), - new ImmutablePair<>( INFO_NOTICES_START_COLUMN + 2, INFO_NOTICES_END_COLUMN ), - new ImmutablePair<>( INFO_LICENSES_START_COLUMN + 2, INFO_LICENSES_END_COLUMN ), - new ImmutablePair<>( INFO_SPDX_START_COLUMN + 2, INFO_SPDX_END_COLUMN ) - ); + sheet.setColumnWidth(DEVELOPERS_END_COLUMN - 1, TIMEZONE_WIDTH); + sheet.setColumnWidth(MISC_START_COLUMN, INCEPTION_YEAR_WIDTH); + if (hasExtendedInfo) { + autosizeColumns( + sheet, + new ImmutablePair<>(MANIFEST_START_COLUMN, MANIFEST_END_COLUMN), + new ImmutablePair<>(INFO_NOTICES_START_COLUMN + 2, INFO_NOTICES_END_COLUMN), + new ImmutablePair<>(INFO_LICENSES_START_COLUMN + 2, INFO_LICENSES_END_COLUMN), + new ImmutablePair<>(INFO_SPDX_START_COLUMN + 2, INFO_SPDX_END_COLUMN)); } } @SafeVarargs - private static void autosizeColumns( Sheet sheet, Pair... ranges ) - { - for ( Pair range : ranges ) - { - for ( int i = range.getLeft(); i < range.getRight(); i++ ) - { - sheet.autoSizeColumn( i ); + private static void autosizeColumns(Sheet sheet, Pair... ranges) { + for (Pair range : ranges) { + for (int i = range.getLeft(); i < range.getRight(); i++) { + sheet.autoSizeColumn(i); } } } - private static int addInfoFileList( CellListParameter cellListParameter, CurrentRowData currentRowData, - int startColumn, int columnsToFill, List infoFiles ) - { - return addList( cellListParameter, currentRowData, startColumn, columnsToFill, infoFiles, - ( Row infoFileRow, InfoFile infoFile ) -> { - final String copyrightLines = Optional - .ofNullable( infoFile.getExtractedCopyrightLines() ) - .map( strings -> String.join( COPYRIGHT_JOIN_SEPARATOR, strings ) ) - .orElse( null ); - createDataCellsInRow( infoFileRow, startColumn, - cellListParameter.getCellStyle(), infoFile.getContent(), copyrightLines, - infoFile.getFileName() ); - } ); + private static int addInfoFileList( + CellListParameter cellListParameter, + CurrentRowData currentRowData, + int startColumn, + int columnsToFill, + List infoFiles) { + return addList( + cellListParameter, + currentRowData, + startColumn, + columnsToFill, + infoFiles, + (Row infoFileRow, InfoFile infoFile) -> { + final String copyrightLines = Optional.ofNullable(infoFile.getExtractedCopyrightLines()) + .map(strings -> String.join(COPYRIGHT_JOIN_SEPARATOR, strings)) + .orElse(null); + createDataCellsInRow( + infoFileRow, + startColumn, + cellListParameter.getCellStyle(), + infoFile.getContent(), + copyrightLines, + infoFile.getFileName()); + }); } - private static int addList( CellListParameter cellListParameter, CurrentRowData currentRowData, - int startColumn, int columnsToFill, - List list, BiConsumer biConsumer ) - { - if ( !CollectionUtils.isEmpty( list ) ) - { - for ( int i = 0; i < list.size(); i++ ) - { - T type = list.get( i ); + private static int addList( + CellListParameter cellListParameter, + CurrentRowData currentRowData, + int startColumn, + int columnsToFill, + List list, + BiConsumer biConsumer) { + if (!CollectionUtils.isEmpty(list)) { + for (int i = 0; i < list.size(); i++) { + T type = list.get(i); Integer index = currentRowData.getCurrentRowIndex() + i; - Row row = cellListParameter.getRows().get( index ); - if ( row == null ) - { - row = cellListParameter.getSheet().createRow( index ); - cellListParameter.getRows().put( index, row ); - if ( cellListParameter.getCellStyle() != null ) - { + Row row = cellListParameter.getRows().get(index); + if (row == null) { + row = cellListParameter.getSheet().createRow(index); + cellListParameter.getRows().put(index, row); + if (cellListParameter.getCellStyle() != null) { // Style all empty left cells, in the columns left from this - createAndStyleCells( row, cellListParameter.getCellStyle(), - new ImmutablePair<>( GENERAL_START_COLUMN, GENERAL_END_COLUMN ), - new ImmutablePair<>( PLUGIN_ID_START_COLUMN, PLUGIN_ID_END_COLUMN ), - new ImmutablePair<>( LICENSES_START_COLUMN, LICENSES_END_COLUMN ) - ); - if ( currentRowData.isHasExtendedInfo() ) - { - createAndStyleCells( row, cellListParameter.getCellStyle(), - new ImmutablePair<>( DEVELOPERS_START_COLUMN, DEVELOPERS_END_COLUMN ), - new ImmutablePair<>( MISC_START_COLUMN, MISC_END_COLUMN ), + createAndStyleCells( + row, + cellListParameter.getCellStyle(), + new ImmutablePair<>(GENERAL_START_COLUMN, GENERAL_END_COLUMN), + new ImmutablePair<>(PLUGIN_ID_START_COLUMN, PLUGIN_ID_END_COLUMN), + new ImmutablePair<>(LICENSES_START_COLUMN, LICENSES_END_COLUMN)); + if (currentRowData.isHasExtendedInfo()) { + createAndStyleCells( + row, + cellListParameter.getCellStyle(), + new ImmutablePair<>(DEVELOPERS_START_COLUMN, DEVELOPERS_END_COLUMN), + new ImmutablePair<>(MISC_START_COLUMN, MISC_END_COLUMN), // JAR - new ImmutablePair<>( MANIFEST_START_COLUMN, MANIFEST_END_COLUMN ), - new ImmutablePair<>( INFO_LICENSES_START_COLUMN, INFO_LICENSES_END_COLUMN ), - new ImmutablePair<>( INFO_NOTICES_START_COLUMN, INFO_NOTICES_END_COLUMN ), - new ImmutablePair<>( INFO_SPDX_START_COLUMN, INFO_SPDX_END_COLUMN ) - ); + new ImmutablePair<>(MANIFEST_START_COLUMN, MANIFEST_END_COLUMN), + new ImmutablePair<>(INFO_LICENSES_START_COLUMN, INFO_LICENSES_END_COLUMN), + new ImmutablePair<>(INFO_NOTICES_START_COLUMN, INFO_NOTICES_END_COLUMN), + new ImmutablePair<>(INFO_SPDX_START_COLUMN, INFO_SPDX_END_COLUMN)); } } - currentRowData.setExtraRows( currentRowData.getExtraRows() + 1 ); + currentRowData.setExtraRows(currentRowData.getExtraRows() + 1); } - biConsumer.accept( row, type ); + biConsumer.accept(row, type); } - } - else if ( cellListParameter.cellStyle != null ) - { - setStyleOnEmptyCells( cellListParameter, currentRowData, startColumn, columnsToFill ); + } else if (cellListParameter.cellStyle != null) { + setStyleOnEmptyCells(cellListParameter, currentRowData, startColumn, columnsToFill); } return currentRowData.getExtraRows(); } @@ -567,75 +655,59 @@ else if ( cellListParameter.cellStyle != null ) * @param startColumn Column where to start setting the style. * @param columnsToFill How many columns to set the style on, starting from 'startColumn'. */ - private static void setStyleOnEmptyCells( CellListParameter cellListParameter, CurrentRowData currentRowData, - int startColumn, int columnsToFill ) - { - Row row = cellListParameter.getRows().get( currentRowData.getCurrentRowIndex() ); - for ( int i = 0; i < columnsToFill; i++ ) - { - Cell cell = row.createCell( startColumn + i, CellType.STRING ); - cell.setCellStyle( cellListParameter.getCellStyle() ); + private static void setStyleOnEmptyCells( + CellListParameter cellListParameter, CurrentRowData currentRowData, int startColumn, int columnsToFill) { + Row row = cellListParameter.getRows().get(currentRowData.getCurrentRowIndex()); + for (int i = 0; i < columnsToFill; i++) { + Cell cell = row.createCell(startColumn + i, CellType.STRING); + cell.setCellStyle(cellListParameter.getCellStyle()); } } @SafeVarargs - private static void createAndStyleCells( Row row, CellStyle cellStyle, Pair... ranges ) - { - for ( Pair range : ranges ) - { - for ( int i = range.getLeft(); i < range.getRight(); i++ ) - { - Cell cell = row.createCell( i, CellType.STRING ); - cell.setCellStyle( cellStyle ); + private static void createAndStyleCells(Row row, CellStyle cellStyle, Pair... ranges) { + for (Pair range : ranges) { + for (int i = range.getLeft(); i < range.getRight(); i++) { + Cell cell = row.createCell(i, CellType.STRING); + cell.setCellStyle(cellStyle); } } } - private static void addHyperlinkIfExists( Workbook workbook, Cell cell, CellStyle hyperlinkStyle, - HyperlinkType hyperlinkType ) - { - if ( !StringUtils.isEmpty( cell.getStringCellValue() ) ) - { - Hyperlink hyperlink = workbook.getCreationHelper().createHyperlink( hyperlinkType ); - try - { - hyperlink.setAddress( cell.getStringCellValue() ); - cell.setHyperlink( hyperlink ); - cell.setCellStyle( hyperlinkStyle ); - } - catch ( IllegalArgumentException e ) - { - LOG.debug( "Can't set Hyperlink for cell value " + cell.getStringCellValue() - + " it gets rejected as URI", e ); + private static void addHyperlinkIfExists( + Workbook workbook, Cell cell, CellStyle hyperlinkStyle, HyperlinkType hyperlinkType) { + if (!StringUtils.isEmpty(cell.getStringCellValue())) { + Hyperlink hyperlink = workbook.getCreationHelper().createHyperlink(hyperlinkType); + try { + hyperlink.setAddress(cell.getStringCellValue()); + cell.setHyperlink(hyperlink); + cell.setCellStyle(hyperlinkStyle); + } catch (IllegalArgumentException e) { + LOG.debug( + "Can't set Hyperlink for cell value " + cell.getStringCellValue() + " it gets rejected as URI", + e); } } } - private static Cell[] createDataCellsInRow( Row row, int startColumn, CellStyle cellStyle, String... names ) - { - Cell[] result = new Cell[ names.length ]; - for ( int i = 0; i < names.length; i++ ) - { - Cell cell = row.createCell( startColumn + i, CellType.STRING ); - if ( cellStyle != null ) - { - cell.setCellStyle( cellStyle ); + private static Cell[] createDataCellsInRow(Row row, int startColumn, CellStyle cellStyle, String... names) { + Cell[] result = new Cell[names.length]; + for (int i = 0; i < names.length; i++) { + Cell cell = row.createCell(startColumn + i, CellType.STRING); + if (cellStyle != null) { + cell.setCellStyle(cellStyle); } - if ( !StringUtils.isEmpty( names[ i ] ) ) - { + if (!StringUtils.isEmpty(names[i])) { final String value; final int maxCellStringLength = Short.MAX_VALUE; - if ( names[ i ].length() > maxCellStringLength ) - { - value = names[ i ].substring( 0, maxCellStringLength - 3 ) + "..."; - } - else - { - value = names[ i ]; + if (names[i].length() > maxCellStringLength) { + value = names[i].substring(0, maxCellStringLength - 3) + "..."; + } else { + value = names[i]; } - cell.setCellValue( value ); + cell.setCellValue(value); } - result[ i ] = cell; + result[i] = cell; } return result; } @@ -647,104 +719,87 @@ private static Cell[] createDataCellsInRow( Row row, int startColumn, CellStyle * @param cellStyle The cell style of the created cell. * @param startPositions The start position of the 3 columns for an InfoFile. */ - private static void createInfoFileCellsInRow( Row row, CellStyle cellStyle, int... startPositions ) - { - for ( int startPosition : startPositions ) - { - createCellsInRow( row, startPosition, cellStyle, "Content", "Extracted copyright lines", "File" ); + private static void createInfoFileCellsInRow(Row row, CellStyle cellStyle, int... startPositions) { + for (int startPosition : startPositions) { + createCellsInRow(row, startPosition, cellStyle, "Content", "Extracted copyright lines", "File"); } } - private static void createCellsInRow( Row row, int startColumn, CellStyle cellStyle, String... names ) - { - for ( int i = 0; i < names.length; i++ ) - { - Cell cell = row.createCell( startColumn + i, CellType.STRING ); - cell.setCellStyle( cellStyle ); - cell.setCellValue( names[ i ] ); + private static void createCellsInRow(Row row, int startColumn, CellStyle cellStyle, String... names) { + for (int i = 0; i < names.length; i++) { + Cell cell = row.createCell(startColumn + i, CellType.STRING); + cell.setCellStyle(cellStyle); + cell.setCellValue(names[i]); } } - private static void createMergedCellsInRow( Sheet sheet, int startColumn, int endColumn, CellStyle cellStyle, - Row row, String cellValue, int rowIndex ) - { - Cell cell = createCellsInRow( startColumn, endColumn, row ); + private static void createMergedCellsInRow( + Sheet sheet, int startColumn, int endColumn, CellStyle cellStyle, Row row, String cellValue, int rowIndex) { + Cell cell = createCellsInRow(startColumn, endColumn, row); final boolean merge = endColumn - 1 > startColumn; CellRangeAddress mergeAddress = null; - if ( merge ) - { - mergeAddress = new CellRangeAddress( rowIndex, rowIndex, startColumn, endColumn - 1 ); - sheet.addMergedRegion( mergeAddress ); + if (merge) { + mergeAddress = new CellRangeAddress(rowIndex, rowIndex, startColumn, endColumn - 1); + sheet.addMergedRegion(mergeAddress); } // Set value and style only after merge - cell.setCellValue( cellValue ); - cell.setCellStyle( cellStyle ); - if ( merge ) - { - setBorderAroundRegion( sheet, mergeAddress, HEADER_CELLS_BORDER_STYLE ); - sheet.groupColumn( startColumn, endColumn - 1 ); + cell.setCellValue(cellValue); + cell.setCellStyle(cellStyle); + if (merge) { + setBorderAroundRegion(sheet, mergeAddress, HEADER_CELLS_BORDER_STYLE); + sheet.groupColumn(startColumn, endColumn - 1); } } - private static void setBorderAroundRegion( Sheet sheet, CellRangeAddress licensesHeaderAddress, - BorderStyle borderStyle ) - { - RegionUtil.setBorderLeft( borderStyle, licensesHeaderAddress, sheet ); - RegionUtil.setBorderTop( borderStyle, licensesHeaderAddress, sheet ); - RegionUtil.setBorderRight( borderStyle, licensesHeaderAddress, sheet ); - RegionUtil.setBorderBottom( borderStyle, licensesHeaderAddress, sheet ); + private static void setBorderAroundRegion( + Sheet sheet, CellRangeAddress licensesHeaderAddress, BorderStyle borderStyle) { + RegionUtil.setBorderLeft(borderStyle, licensesHeaderAddress, sheet); + RegionUtil.setBorderTop(borderStyle, licensesHeaderAddress, sheet); + RegionUtil.setBorderRight(borderStyle, licensesHeaderAddress, sheet); + RegionUtil.setBorderBottom(borderStyle, licensesHeaderAddress, sheet); } - private static Cell createCellsInRow( int startColumn, int exclusiveEndColumn, Row inRow ) - { + private static Cell createCellsInRow(int startColumn, int exclusiveEndColumn, Row inRow) { Cell firstCell = null; - for ( int i = startColumn; i < exclusiveEndColumn; i++ ) - { - Cell cell = inRow.createCell( i ); - if ( i == startColumn ) - { + for (int i = startColumn; i < exclusiveEndColumn; i++) { + Cell cell = inRow.createCell(i); + if (i == startColumn) { firstCell = cell; } } return firstCell; } - private static void setBorderStyle( CellStyle cellStyle, BorderStyle borderStyle ) - { - cellStyle.setBorderLeft( borderStyle ); - cellStyle.setBorderTop( borderStyle ); - cellStyle.setBorderRight( borderStyle ); - cellStyle.setBorderBottom( borderStyle ); + private static void setBorderStyle(CellStyle cellStyle, BorderStyle borderStyle) { + cellStyle.setBorderLeft(borderStyle); + cellStyle.setBorderTop(borderStyle); + cellStyle.setBorderRight(borderStyle); + cellStyle.setBorderBottom(borderStyle); } /** * Parameters for cells which apply to all cells in each loop iteration. */ - private static class CellListParameter - { + private static class CellListParameter { private final Sheet sheet; private final Map rows; private final CellStyle cellStyle; - private CellListParameter( Sheet sheet, Map rows, CellStyle cellStyle ) - { + private CellListParameter(Sheet sheet, Map rows, CellStyle cellStyle) { this.sheet = sheet; this.rows = rows; this.cellStyle = cellStyle; } - Sheet getSheet() - { + Sheet getSheet() { return sheet; } - Map getRows() - { + Map getRows() { return rows; } - CellStyle getCellStyle() - { + CellStyle getCellStyle() { return cellStyle; } } @@ -752,37 +807,31 @@ CellStyle getCellStyle() /** * Parameters which may change constantly. */ - private static class CurrentRowData - { + private static class CurrentRowData { private final int currentRowIndex; private int extraRows; private final boolean hasExtendedInfo; - CurrentRowData( int currentRowIndex, int extraRows, boolean hasExtendedInfo ) - { + CurrentRowData(int currentRowIndex, int extraRows, boolean hasExtendedInfo) { this.currentRowIndex = currentRowIndex; this.extraRows = extraRows; this.hasExtendedInfo = hasExtendedInfo; } - int getCurrentRowIndex() - { + int getCurrentRowIndex() { return currentRowIndex; } - int getExtraRows() - { + int getExtraRows() { return extraRows; } - void setExtraRows( int extraRows ) - { + void setExtraRows(int extraRows) { this.extraRows = extraRows; } - boolean isHasExtendedInfo() - { + boolean isHasExtendedInfo() { return hasExtendedInfo; } } -} \ No newline at end of file +} diff --git a/src/test/java/org/codehaus/mojo/license/download/LicenseMatchersTest.java b/src/test/java/org/codehaus/mojo/license/download/LicenseMatchersTest.java index 80021b523..28c758840 100644 --- a/src/test/java/org/codehaus/mojo/license/download/LicenseMatchersTest.java +++ b/src/test/java/org/codehaus/mojo/license/download/LicenseMatchersTest.java @@ -70,7 +70,7 @@ public void licenseMatches() { @Test public void replaceMatchesLegacy() { - final ProjectLicenseInfo dep = new ProjectLicenseInfo( "myGroup", "myArtifact", "1a2.3", null ); + final ProjectLicenseInfo dep = new ProjectLicenseInfo("myGroup", "myArtifact", "1a2.3", null); final ProjectLicenseInfo pli1 = new ProjectLicenseInfo("myGroup", "myArtifact", "1.2.3", false); final ProjectLicense lic2 = new ProjectLicense("lic2", "http://other.org", null, "other comment", null); pli1.addLicense(lic2); @@ -126,7 +126,7 @@ public void replaceMatches() { dep.addLicense(new ProjectLicense("lic1", "http://some.org", null, "comment", null)); Assert.assertFalse(m1.matches(dep)); - final ProjectLicenseInfo dep11 = new ProjectLicenseInfo( "myGroup", "myArtifact", "1.2.3", null ); + final ProjectLicenseInfo dep11 = new ProjectLicenseInfo("myGroup", "myArtifact", "1.2.3", null); dep11.addLicense(new ProjectLicense("lic1", "http://some.org", null, "comment", null)); final List oldLics11 = dep.cloneLicenses(); final ProjectLicenseInfo pli11 = new ProjectLicenseInfo("myGroup", "myArtifact", "1\\.2\\.3", true); diff --git a/src/test/java/org/codehaus/mojo/license/download/LicenseSummaryTest.java b/src/test/java/org/codehaus/mojo/license/download/LicenseSummaryTest.java index fdc8cd21f..5e46616e5 100644 --- a/src/test/java/org/codehaus/mojo/license/download/LicenseSummaryTest.java +++ b/src/test/java/org/codehaus/mojo/license/download/LicenseSummaryTest.java @@ -75,8 +75,8 @@ public void testWriteReadLicenseSummary() throws IOException, SAXException, ParserConfigurationException, TransformerFactoryConfigurationError, TransformerException { List licSummary = new ArrayList<>(); - ProjectLicenseInfo dep1 = new ProjectLicenseInfo( "org.test", "test1", "1.0", buildExtendedInfo(1) ); - ProjectLicenseInfo dep2 = new ProjectLicenseInfo( "org.test", "test2", "2.0", buildExtendedInfo(2) ); + ProjectLicenseInfo dep1 = new ProjectLicenseInfo("org.test", "test1", "1.0", buildExtendedInfo(1)); + ProjectLicenseInfo dep2 = new ProjectLicenseInfo("org.test", "test2", "2.0", buildExtendedInfo(2)); ProjectLicense lic = new ProjectLicense(); lic.setName("lgpl"); @@ -136,14 +136,13 @@ public void testWriteReadLicenseSummary() } File licensesExcelOutputFile = File.createTempFile("licExcel", ".xlsx"); - ExcelFileWriter.write( licSummary, licensesExcelOutputFile ); + ExcelFileWriter.write(licSummary, licensesExcelOutputFile); } private static ExtendedInfo buildExtendedInfo(int suffix) { ExtendedInfo extendedInfo = new ExtendedInfo(); Artifact artifact = new DefaultArtifact( - "org.test", "test" + suffix, "2.0", "compile", "jar", null, - new DefaultArtifactHandler()); + "org.test", "test" + suffix, "2.0", "compile", "jar", null, new DefaultArtifactHandler()); extendedInfo.setArtifact(artifact); extendedInfo.setBundleLicense("Bundle Test License " + suffix); extendedInfo.setBundleVendor("Bundle Test Vendor " + suffix); @@ -179,7 +178,8 @@ private static ExtendedInfo buildExtendedInfo(int suffix) { private static InfoFile createInfoFile(InfoFile.Type noticeType, int suffix) { InfoFile infoFile = new InfoFile(); infoFile.setContent("This is " + noticeType.name() + " test content " + suffix); - infoFile.setExtractedCopyrightLines(new HashSet<>(Collections.singletonList("Test " + noticeType.name() + suffix))); + infoFile.setExtractedCopyrightLines( + new HashSet<>(Collections.singletonList("Test " + noticeType.name() + suffix))); infoFile.setFileName(noticeType.name() + " " + suffix + ".txt"); infoFile.setType(noticeType); return infoFile; From 3b9b2c9b5ed97ab02f321e0a6421e339872dc877 Mon Sep 17 00:00:00 2001 From: Jan Diederich Date: Sun, 22 Oct 2023 21:50:56 +0200 Subject: [PATCH 22/34] Added license merge to `license:aggregate-download-licenses` and LibreOffice ODS export --- README.md | 3 +- pom.xml | 24 +- .../child1/pom.xml | 11 +- .../child2/pom.xml | 12 +- .../invoker.properties | 0 .../pom.xml | 3 +- .../postbuild.groovy | 46 +- .../license/AbstractDownloadLicensesMojo.java | 59 +- .../license/AbstractThirdPartyReportMojo.java | 11 +- .../AggregateDownloadLicensesMojo.java | 5 +- .../mojo/license/DownloadLicensesMojo.java | 3 +- .../LicensesXmlInsertVersionsMojo.java | 3 +- .../license/api/DefaultThirdPartyHelper.java | 3 +- .../download/LicensedArtifactResolver.java | 43 +- .../extended/spreadsheet/CalcFileWriter.java | 979 ++++++++++++++++++ .../extended/spreadsheet/ExcelFileWriter.java | 691 ++++++------ .../extended/spreadsheet/SpreadsheetUtil.java | 99 ++ .../mojo/license/utils/StringToList.java | 6 +- .../license/download/LicenseSummaryTest.java | 4 + 19 files changed, 1614 insertions(+), 391 deletions(-) rename src/it/{aggregate-download-licenses-extended-excel => aggregate-download-licenses-extended-spreadsheet}/child1/pom.xml (80%) rename src/it/{aggregate-download-licenses-extended-excel => aggregate-download-licenses-extended-spreadsheet}/child2/pom.xml (82%) rename src/it/{aggregate-download-licenses-extended-excel => aggregate-download-licenses-extended-spreadsheet}/invoker.properties (100%) rename src/it/{aggregate-download-licenses-extended-excel => aggregate-download-licenses-extended-spreadsheet}/pom.xml (94%) rename src/it/{aggregate-download-licenses-extended-excel => aggregate-download-licenses-extended-spreadsheet}/postbuild.groovy (60%) create mode 100644 src/main/java/org/codehaus/mojo/license/extended/spreadsheet/CalcFileWriter.java create mode 100644 src/main/java/org/codehaus/mojo/license/extended/spreadsheet/SpreadsheetUtil.java diff --git a/README.md b/README.md index 994b33761..e7009033e 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,8 @@ and `writeExcelFile`): true true - ... + + true diff --git a/pom.xml b/pom.xml index b4a500010..c643ecfcb 100644 --- a/pom.xml +++ b/pom.xml @@ -324,12 +324,20 @@ 6.0.0 - + org.apache.poi poi-ooxml 5.2.4 + + + + org.odftoolkit + odfdom-java + + 0.9.0 +
@@ -512,11 +520,18 @@ + org.apache.poi poi-ooxml 5.2.4 + + + org.odftoolkit + odfdom-java + 0.9.0 + commons-io commons-io @@ -589,11 +604,18 @@ ${project.build.directory}/local-repo + org.apache.poi poi-ooxml 5.2.4 + + + org.odftoolkit + odfdom-java + 0.9.0 + commons-io commons-io diff --git a/src/it/aggregate-download-licenses-extended-excel/child1/pom.xml b/src/it/aggregate-download-licenses-extended-spreadsheet/child1/pom.xml similarity index 80% rename from src/it/aggregate-download-licenses-extended-excel/child1/pom.xml rename to src/it/aggregate-download-licenses-extended-spreadsheet/child1/pom.xml index d770f50d8..6ea8c2b92 100644 --- a/src/it/aggregate-download-licenses-extended-excel/child1/pom.xml +++ b/src/it/aggregate-download-licenses-extended-spreadsheet/child1/pom.xml @@ -32,9 +32,9 @@ test-aggregate-download-licenses-extended-excel @project.version@ - test-aggregate-download-licenses-extended-excel-child1 + test-aggregate-download-licenses-extended-spreadsheet-child1 - License Test :: aggregate-download-licenses - Extended Excel - child 1 + License Test :: aggregate-download-licenses - Extended Spreadsheet — child 1 @@ -42,7 +42,12 @@ commons-logging commons-logging - 1.1.1 + 1.2 + + + org.eclipse.jdt + org.eclipse.jdt.core + 3.35.0 diff --git a/src/it/aggregate-download-licenses-extended-excel/child2/pom.xml b/src/it/aggregate-download-licenses-extended-spreadsheet/child2/pom.xml similarity index 82% rename from src/it/aggregate-download-licenses-extended-excel/child2/pom.xml rename to src/it/aggregate-download-licenses-extended-spreadsheet/child2/pom.xml index aa85ddbe8..bbe7f6d7e 100644 --- a/src/it/aggregate-download-licenses-extended-excel/child2/pom.xml +++ b/src/it/aggregate-download-licenses-extended-spreadsheet/child2/pom.xml @@ -32,9 +32,9 @@ test-aggregate-download-licenses-extended-excel @project.version@ - test-aggregate-download-licenses-extended-excel-child2 + test-aggregate-download-licenses-extended-spreadsheet-child2 - License Test :: aggregate-download-licenses - Extended Excel - child 2 + License Test :: aggregate-download-licenses - Extended Spreadsheet — child 2 @@ -49,7 +49,13 @@ org.sonatype.plexus plexus-cipher - 1.4 + 1.7 + + + + org.junit.jupiter + junit-jupiter-api + 5.10.0 diff --git a/src/it/aggregate-download-licenses-extended-excel/invoker.properties b/src/it/aggregate-download-licenses-extended-spreadsheet/invoker.properties similarity index 100% rename from src/it/aggregate-download-licenses-extended-excel/invoker.properties rename to src/it/aggregate-download-licenses-extended-spreadsheet/invoker.properties diff --git a/src/it/aggregate-download-licenses-extended-excel/pom.xml b/src/it/aggregate-download-licenses-extended-spreadsheet/pom.xml similarity index 94% rename from src/it/aggregate-download-licenses-extended-excel/pom.xml rename to src/it/aggregate-download-licenses-extended-spreadsheet/pom.xml index 86b40b4a7..440e75bf5 100644 --- a/src/it/aggregate-download-licenses-extended-excel/pom.xml +++ b/src/it/aggregate-download-licenses-extended-spreadsheet/pom.xml @@ -36,7 +36,7 @@ child2 - License Test :: aggregate-download-licenses - Extended Excel + License Test :: aggregate-download-licenses - Extended Spreadsheet pom @@ -54,6 +54,7 @@ @project.version@ true + true true The Apache Software License, Version 2.0|Apache License, Version 2.0|Apache Public License diff --git a/src/it/aggregate-download-licenses-extended-excel/postbuild.groovy b/src/it/aggregate-download-licenses-extended-spreadsheet/postbuild.groovy similarity index 60% rename from src/it/aggregate-download-licenses-extended-excel/postbuild.groovy rename to src/it/aggregate-download-licenses-extended-spreadsheet/postbuild.groovy index 72c3c2864..86b24a7ab 100644 --- a/src/it/aggregate-download-licenses-extended-excel/postbuild.groovy +++ b/src/it/aggregate-download-licenses-extended-spreadsheet/postbuild.groovy @@ -19,6 +19,10 @@ * . * #L% */ + +import org.odftoolkit.odfdom.doc.OdfSpreadsheetDocument +import org.odftoolkit.odfdom.doc.table.OdfTable + import java.util.logging.Level import java.util.logging.Logger @@ -28,10 +32,10 @@ import org.apache.poi.ss.usermodel.Row import org.apache.poi.ss.usermodel.Sheet import org.apache.poi.ss.usermodel.WorkbookFactory -log = Logger.getLogger("test-aggregate-download-licenses-extended-excel") +log = Logger.getLogger("test-aggregate-download-licenses-extended-spreadsheet") static boolean searchText(Sheet sheet, String searchText) { - def log2 = Logger.getLogger("test-aggregate-download-licenses-extended-excel-search") + def log2 = Logger.getLogger("test-aggregate-download-licenses-extended-spreadsheet-search") for (Iterator rowIterator = sheet.rowIterator(); rowIterator.hasNext();) { Row row = rowIterator.next() @@ -50,19 +54,31 @@ static boolean searchText(Sheet sheet, String searchText) { return false } -file = new File(basedir, 'target/generated-resources/licenses.xlsx'); -assert file.exists() -assert file.length() > 100 +// -------------- Excel ---------------------- + +excelFile = new File(basedir, 'target/generated-resources/licenses.xlsx') +assert excelFile.exists() +assert excelFile.length() > 100 + +try (InputStream input = new FileInputStream(excelFile)) { + // So it can be easily opened and inspected manually. In a modern IDE it's just a (double-)click in the log output. + log.log(Level.FINE, "Excel export at: {}", excelFile.absolutePath) + workbook = WorkbookFactory.create(input) + Sheet sheet = workbook.getSheetAt(0) + + assert searchText(sheet, "Maven information") + assert searchText(sheet, "The Apache Software License, Version 2.0") + assert searchText(sheet, "The Apache Software Foundation") +} -searchText = "YourSearchText" -input = new FileInputStream(file) -// So it can be easily opened and inspected manually. In a modern IDE it's just a (double-)click in the log output. -log.log(Level.FINE, "Excel export at: {}", file.absolutePath) -workbook = WorkbookFactory.create(input) -Sheet sheet = workbook.getSheetAt(0) +// -------------- Calc ----------------- -assert searchText(sheet, "Maven information") -assert searchText(sheet, "Apache Software Foundation") -assert searchText(sheet, "The Apache Software Foundation") +calcFile = new File(basedir, 'target/generated-resources/licenses.ods') +assert calcFile.exists() +assert calcFile.length() > 100 -input.close() \ No newline at end of file +try (OdfSpreadsheetDocument spreadsheet = OdfSpreadsheetDocument.loadDocument(calcFile)) { + List tableList = spreadsheet.getTableList() + OdfTable table = tableList.get(0) + assert table.getRowCount() >= 3 +} \ No newline at end of file diff --git a/src/main/java/org/codehaus/mojo/license/AbstractDownloadLicensesMojo.java b/src/main/java/org/codehaus/mojo/license/AbstractDownloadLicensesMojo.java index 29a93a64b..b1fbad58b 100644 --- a/src/main/java/org/codehaus/mojo/license/AbstractDownloadLicensesMojo.java +++ b/src/main/java/org/codehaus/mojo/license/AbstractDownloadLicensesMojo.java @@ -67,6 +67,7 @@ import org.codehaus.mojo.license.download.ProjectLicenseInfo; import org.codehaus.mojo.license.download.UrlReplacements; import org.codehaus.mojo.license.extended.InfoFile; +import org.codehaus.mojo.license.extended.spreadsheet.CalcFileWriter; import org.codehaus.mojo.license.extended.spreadsheet.ExcelFileWriter; import org.codehaus.mojo.license.spdx.SpdxLicenseList; import org.codehaus.mojo.license.spdx.SpdxLicenseList.Attachments.ContentSanitizer; @@ -680,27 +681,67 @@ public abstract class AbstractDownloadLicensesMojo extends AbstractLicensesXmlMo private boolean useDefaultContentSanitizers; /** - * Write Excel file (XLSX) for goal license:aggregate-download-licenses. + * Write Microsoft Office Excel file (XLSX) for goal license:aggregate-download-licenses. * - * @since 2.1 + * @since 2.2.1 */ @Parameter(property = "license.writeExcelFile", defaultValue = "false") private boolean writeExcelFile; /** - * The excel output file used if {@link #writeExcelFile} is true, + * Write LibreOffice Calc file (ODS) for goal license:aggregate-download-licenses. + * + * @since 2.2.1 + */ + @Parameter(property = "license.writeExcelFile", defaultValue = "false") + private boolean writeCalcFile; + + /** + * To merge licenses in the Excel file. + *

+ * Each entry represents a merge (first license is main license to keep), licenses are separated by {@code |}. + *

+ * Example: + *

+ *

+     * <licenseMerges>
+     * <licenseMerge>The Apache Software License|Version 2.0,Apache License, Version 2.0</licenseMerge>
+     * </licenseMerges>
+     * </pre>
+     *
+     * @since 2.2.1
+     */
+    @Parameter
+    List licenseMerges;
+
+    /**
+     * The Excel output file used if {@link #writeExcelFile} is true,
      * containing a mapping between each dependency and it's license information.
      * With extended information, if available.
      *
      * @see AbstractDownloadLicensesMojo#writeExcelFile
      * @see AggregateDownloadLicensesMojo#extendedInfo
-     * @since 2.1
+     * @since 2.2.1
      */
     @Parameter(
             property = "licensesExcelOutputFile",
             defaultValue = "${project.build.directory}/generated-resources/licenses.xlsx")
     protected File licensesExcelOutputFile;
 
+    /**
+     * The Calc output file used if {@link #writeCalcFile} is true,
+     * containing a mapping between each dependency and it's license information.
+     * With extended information, if available.
+     *
+     * @see AbstractDownloadLicensesMojo#writeCalcFile
+     * @see AggregateDownloadLicensesMojo#extendedInfo
+     * @since 2.2.1
+     */
+    @Parameter(
+            property = "licensesCalcOutputFile",
+            defaultValue = "${project.build.directory}/generated-resources/licenses.ods")
+    protected File licensesCalcOutputFile;
+
     // ----------------------------------------------------------------------
     // Plexus Components
     // ----------------------------------------------------------------------
@@ -833,9 +874,9 @@ public void execute() throws MojoExecutionException, MojoFailureException {
             }
 
             List depProjectLicensesWithErrors = filterErrors(depProjectLicenses);
-            writeLicenseSummaries(depProjectLicenses, licensesOutputFile, licensesExcelOutputFile);
+            writeLicenseSummaries(depProjectLicenses);
             if (!CollectionUtils.isEmpty(depProjectLicensesWithErrors)) {
-                writeLicenseSummaries(depProjectLicensesWithErrors, licensesErrorsFile, licensesExcelErrorFile);
+                writeLicenseSummaries(depProjectLicensesWithErrors);
             }
 
             removeOrphanFiles(depProjectLicenses);
@@ -862,13 +903,15 @@ public void execute() throws MojoExecutionException, MojoFailureException {
         }
     }
 
-    private void writeLicenseSummaries(
-            List depProjectLicenses, File licensesOutputFile, File licensesExcelOutputFile)
+    private void writeLicenseSummaries(List depProjectLicenses)
             throws ParserConfigurationException, TransformerException, IOException {
         writeLicenseSummary(depProjectLicenses, licensesOutputFile, writeVersions);
         if (writeExcelFile) {
             ExcelFileWriter.write(depProjectLicenses, licensesExcelOutputFile);
         }
+        if (writeCalcFile) {
+            CalcFileWriter.write(depProjectLicenses, licensesCalcOutputFile);
+        }
     }
 
     /**
diff --git a/src/main/java/org/codehaus/mojo/license/AbstractThirdPartyReportMojo.java b/src/main/java/org/codehaus/mojo/license/AbstractThirdPartyReportMojo.java
index 171c4e6ab..401ec2f36 100644
--- a/src/main/java/org/codehaus/mojo/license/AbstractThirdPartyReportMojo.java
+++ b/src/main/java/org/codehaus/mojo/license/AbstractThirdPartyReportMojo.java
@@ -384,9 +384,14 @@ protected void executeReport(Locale locale) throws MavenReportException {
         try {
             init();
             details = createThirdPartyDetails();
-        } catch (IOException | ThirdPartyToolException | ArtifactNotFoundException | ArtifactResolutionException |
-                 ProjectBuildingException | MojoFailureException | DependenciesToolException |
-                 MojoExecutionException e) {
+        } catch (IOException
+                | ThirdPartyToolException
+                | ArtifactNotFoundException
+                | ArtifactResolutionException
+                | ProjectBuildingException
+                | MojoFailureException
+                | DependenciesToolException
+                | MojoExecutionException e) {
             throw new MavenReportException(e.getMessage(), e);
         }
 
diff --git a/src/main/java/org/codehaus/mojo/license/AggregateDownloadLicensesMojo.java b/src/main/java/org/codehaus/mojo/license/AggregateDownloadLicensesMojo.java
index d4a27018c..39b5d0792 100644
--- a/src/main/java/org/codehaus/mojo/license/AggregateDownloadLicensesMojo.java
+++ b/src/main/java/org/codehaus/mojo/license/AggregateDownloadLicensesMojo.java
@@ -103,7 +103,7 @@ public class AggregateDownloadLicensesMojo extends AbstractDownloadLicensesMojo
      * 

* This means it will read infos from the JAR's MANIFEST.MF file, look for NOTICE.txt and similar files. * - * @since 2.1 + * @since 2.2.1 */ @Parameter(property = "license.extendedInfo", defaultValue = "false") private boolean extendedInfo; @@ -132,7 +132,8 @@ protected Map getDependencies() { this, remoteRepositories, result, - extendedInfo); + extendedInfo, + licenseMerges); } return result; } diff --git a/src/main/java/org/codehaus/mojo/license/DownloadLicensesMojo.java b/src/main/java/org/codehaus/mojo/license/DownloadLicensesMojo.java index 1edf507aa..34a059510 100644 --- a/src/main/java/org/codehaus/mojo/license/DownloadLicensesMojo.java +++ b/src/main/java/org/codehaus/mojo/license/DownloadLicensesMojo.java @@ -89,7 +89,8 @@ protected Map getDependencies() { this, remoteRepositories, result, - false); + false, + licenseMerges); return result; } } diff --git a/src/main/java/org/codehaus/mojo/license/LicensesXmlInsertVersionsMojo.java b/src/main/java/org/codehaus/mojo/license/LicensesXmlInsertVersionsMojo.java index 7675e9073..fe1fae60d 100644 --- a/src/main/java/org/codehaus/mojo/license/LicensesXmlInsertVersionsMojo.java +++ b/src/main/java/org/codehaus/mojo/license/LicensesXmlInsertVersionsMojo.java @@ -134,7 +134,8 @@ public ArtifactFilters getArtifactFilters() { config, remoteRepositories, resolvedDeps, - false); + false, + null); final Map resolvedDepsMap = new HashMap<>(resolvedDeps.size()); for (LicensedArtifact dep : resolvedDeps.values()) { resolvedDepsMap.put(dep.getGroupId() + ":" + dep.getArtifactId(), dep); diff --git a/src/main/java/org/codehaus/mojo/license/api/DefaultThirdPartyHelper.java b/src/main/java/org/codehaus/mojo/license/api/DefaultThirdPartyHelper.java index 4915b2608..48e20849c 100644 --- a/src/main/java/org/codehaus/mojo/license/api/DefaultThirdPartyHelper.java +++ b/src/main/java/org/codehaus/mojo/license/api/DefaultThirdPartyHelper.java @@ -45,6 +45,7 @@ import org.apache.maven.project.ProjectBuildingException; import org.codehaus.mojo.license.model.LicenseMap; import org.codehaus.mojo.license.utils.SortedProperties; +import org.codehaus.mojo.license.utils.StringToList; import org.eclipse.aether.repository.RemoteRepository; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -275,7 +276,7 @@ public void mergeLicenses(List licenseMerges, LicenseMap licenseMap) thr for (String merge : licenseMerges) { merge = merge.trim(); - String[] split = merge.split("\\s*\\|\\s*"); + String[] split = merge.split(StringToList.LIST_OF_LICENSES_REG_EX); String mainLicense = split[0]; diff --git a/src/main/java/org/codehaus/mojo/license/download/LicensedArtifactResolver.java b/src/main/java/org/codehaus/mojo/license/download/LicensedArtifactResolver.java index 67db14819..dd1c1b979 100644 --- a/src/main/java/org/codehaus/mojo/license/download/LicensedArtifactResolver.java +++ b/src/main/java/org/codehaus/mojo/license/download/LicensedArtifactResolver.java @@ -32,6 +32,8 @@ import java.util.Map; import java.util.Set; +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.annotations.Nullable; import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.repository.ArtifactRepository; import org.apache.maven.execution.MavenSession; @@ -41,12 +43,10 @@ import org.apache.maven.project.ProjectBuilder; import org.apache.maven.project.ProjectBuildingException; import org.apache.maven.project.ProjectBuildingRequest; -import org.codehaus.mojo.license.api.ArtifactFilters; -import org.codehaus.mojo.license.api.DefaultThirdPartyTool; -import org.codehaus.mojo.license.api.MavenProjectDependenciesConfigurator; -import org.codehaus.mojo.license.api.ResolvedProjectDependencies; +import org.codehaus.mojo.license.api.*; import org.codehaus.mojo.license.download.LicensedArtifact.Builder; import org.codehaus.mojo.license.utils.MojoHelper; +import org.codehaus.mojo.license.utils.StringToList; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -81,10 +81,11 @@ public class LicensedArtifactResolver { * For a given {@code project}, obtain the universe of its dependencies after applying transitivity and filtering * rules given in the {@code configuration} object. Result is given in a map where keys are unique artifact id * - * @param artifacts Dependencies - * @param configuration the configuration + * @param artifacts Dependencies + * @param configuration the configuration * @param remoteRepositories remote repositories used to resolve dependencies - * @param result Map with Key/Value = PluginID/LicensedArtifact + * @param result Map with Key/Value = PluginID/LicensedArtifact + * @param licenseMerges * @return the map of resolved dependencies indexed by their unique id. * @see MavenProjectDependenciesConfigurator */ @@ -93,7 +94,8 @@ public void loadProjectDependencies( MavenProjectDependenciesConfigurator configuration, List remoteRepositories, Map result, - boolean extendedInfo) { + boolean extendedInfo, + List licenseMerges) { final ArtifactFilters artifactFilters = configuration.getArtifactFilters(); final boolean excludeTransitiveDependencies = configuration.isExcludeTransitiveDependencies(); @@ -120,6 +122,8 @@ public void loadProjectDependencies( .setResolveDependencies(false) .setProcessPlugins(false); + final Map mergedLicenses = buildMergedLicenses(licenseMerges); + for (Artifact artifact : depArtifacts) { excludeArtifacts.put(artifact.getId(), artifact); @@ -167,8 +171,9 @@ public void loadProjectDependencies( List lics = project.getLicenses(); if (lics != null) { for (org.apache.maven.model.License lic : lics) { + final String mergedLicense = mergedLicenses.getOrDefault(lic.getName(), lic.getName()); laBuilder.license( - new License(lic.getName(), lic.getUrl(), lic.getDistribution(), lic.getComments())); + new License(mergedLicense, lic.getUrl(), lic.getDistribution(), lic.getComments())); } } } catch (ProjectBuildingException e) { @@ -210,4 +215,24 @@ public void loadProjectDependencies( } } // CHECKSTYLE_ON: MethodLength + + @Nonnull + private static Map buildMergedLicenses(@Nullable List licenseMerges) { + final Map mergedLicenses = new HashMap<>(); + if (licenseMerges != null) { + for (String licenseMerge : licenseMerges) { + String[] splited = licenseMerge + .trim() + // Replace newlines + .replace('\n', ' ') + // Replace multiple spaces with one. + .replaceAll(" +", " ") + .split(StringToList.LIST_OF_LICENSES_REG_EX); + for (String split : splited) { + mergedLicenses.put(split, splited[0]); + } + } + } + return mergedLicenses; + } } diff --git a/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/CalcFileWriter.java b/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/CalcFileWriter.java new file mode 100644 index 000000000..5e8a1012e --- /dev/null +++ b/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/CalcFileWriter.java @@ -0,0 +1,979 @@ +package org.codehaus.mojo.license.extended.spreadsheet; + +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathExpressionException; + +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.file.Files; +import java.util.*; +import java.util.function.BiConsumer; + +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; +import org.apache.maven.api.annotations.Nullable; +import org.apache.maven.model.Developer; +import org.apache.maven.model.Organization; +import org.apache.maven.model.Scm; +import org.codehaus.mojo.license.download.ProjectLicense; +import org.codehaus.mojo.license.download.ProjectLicenseInfo; +import org.codehaus.mojo.license.extended.ExtendedInfo; +import org.codehaus.mojo.license.extended.InfoFile; +import org.odftoolkit.odfdom.doc.OdfSpreadsheetDocument; +import org.odftoolkit.odfdom.doc.table.*; +import org.odftoolkit.odfdom.dom.OdfContentDom; +import org.odftoolkit.odfdom.dom.OdfSettingsDom; +import org.odftoolkit.odfdom.dom.element.config.ConfigConfigItemElement; +import org.odftoolkit.odfdom.dom.element.config.ConfigConfigItemMapEntryElement; +import org.odftoolkit.odfdom.dom.element.style.StyleParagraphPropertiesElement; +import org.odftoolkit.odfdom.dom.element.style.StyleTableCellPropertiesElement; +import org.odftoolkit.odfdom.dom.element.style.StyleTextPropertiesElement; +import org.odftoolkit.odfdom.dom.element.text.TextAElement; +import org.odftoolkit.odfdom.dom.style.OdfStyleFamily; +import org.odftoolkit.odfdom.dom.style.props.OdfTableColumnProperties; +import org.odftoolkit.odfdom.incubator.doc.office.OdfOfficeStyles; +import org.odftoolkit.odfdom.incubator.doc.style.OdfStyle; +import org.odftoolkit.odfdom.type.Color; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import static org.codehaus.mojo.license.extended.spreadsheet.SpreadsheetUtil.*; + +/** + * Writes LibreOffices Calc ODS file. + */ +public class CalcFileWriter { + private static final Logger LOG = LoggerFactory.getLogger(CalcFileWriter.class); + + private static final String HEADER_CELL_STYLE = "headerCellStyle"; + private static final String HYPERLINK_NORMAL_STYLE = "hyperlinkNormalStyle"; + private static final String HYPERLINK_GRAY_STYLE = "hyperlinkGrayStyle"; + private static final String GRAY_CELL_STYLE = "grayCellStyle"; + private static final String NORMAL_CELL_STYLE = "normalCellStyle"; + public static final String TABLE_NAME = "License information"; + + public static void write(List projectLicenseInfos, final File licensesCalcOutputFile) { + if (CollectionUtils.isEmpty(projectLicenseInfos)) { + LOG.debug("Nothing to write to excel, no project data."); + return; + } + + try (OdfSpreadsheetDocument spreadsheet = OdfSpreadsheetDocument.newSpreadsheetDocument()) { + List tableList = spreadsheet.getTableList(); + final OdfTable table; + if (!tableList.isEmpty()) { + table = tableList.get(0); + table.setTableName(TABLE_NAME); + } else { + table = OdfTable.newTable(spreadsheet); + } + table.setTableName(TABLE_NAME); + + createHeaderStyle(spreadsheet); + + createHeader(projectLicenseInfos, spreadsheet, table); + + writeData( + projectLicenseInfos, spreadsheet, table, convertToOdfColor(SpreadsheetUtil.ALTERNATING_ROWS_COLOR)); + + try (OutputStream fileOut = Files.newOutputStream(licensesCalcOutputFile.toPath())) { + spreadsheet.save(fileOut); + } catch (IOException e) { + LOG.error("Error on storing Calc file with license and other information", e); + } + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private static Color convertToOdfColor(java.awt.Color color) { + return new Color(color.getRed(), color.getGreen(), color.getBlue()); + } + + private static void createHeader( + List projectLicenseInfos, OdfSpreadsheetDocument spreadsheet, OdfTable table) { + boolean hasExtendedInfo = false; + for (ProjectLicenseInfo projectLicenseInfo : projectLicenseInfos) { + if (projectLicenseInfo.getExtendedInfo() != null) { + hasExtendedInfo = true; + break; + } + } + + /* + All rows must be added before any cell merges, or merges on new lines will be merged like the previous + rows. + */ + + // Create 1st header row. The Maven/JAR header row + OdfTableRow mavenJarRow = table.getRowByIndex(0); + + // Create 2nd header row + OdfTableRow secondHeaderRow = table.appendRow(); + + // Create 3rd header row + OdfTableRow thirdHeaderRow = table.appendRow(); + + // Create Maven header cell + createMergedCellsInRow( + table, MAVEN_START_COLUMN, MAVEN_END_COLUMN, mavenJarRow, "Maven information", 0, HEADER_CELL_STYLE); + + if (hasExtendedInfo) { + // Create JAR header cell + createMergedCellsInRow( + table, + EXTENDED_INFO_START_COLUMN, + EXTENDED_INFO_END_COLUMN, + mavenJarRow, + "JAR Content", + 0, + HEADER_CELL_STYLE); + } + + // Create Maven "General" header + createMergedCellsInRow( + table, GENERAL_START_COLUMN, GENERAL_END_COLUMN, secondHeaderRow, "General", 1, HEADER_CELL_STYLE); + + // Create Maven "Plugin ID" header + createMergedCellsInRow( + table, + PLUGIN_ID_START_COLUMN, + PLUGIN_ID_END_COLUMN, + secondHeaderRow, + "Plugin ID", + 1, + HEADER_CELL_STYLE); + + // Gap "General" <-> "Plugin ID". + setColumnWidth(table, GENERAL_END_COLUMN, GAP_WIDTH); + + // Create Maven "Licenses" header + createMergedCellsInRow( + table, LICENSES_START_COLUMN, LICENSES_END_COLUMN, secondHeaderRow, "Licenses", 1, HEADER_CELL_STYLE); + + // Gap "Plugin ID" <-> "Licenses". + setColumnWidth(table, PLUGIN_ID_END_COLUMN, GAP_WIDTH); + + // Create Maven "Developers" header + createMergedCellsInRow( + table, + DEVELOPERS_START_COLUMN, + DEVELOPERS_END_COLUMN, + secondHeaderRow, + "Developers", + 1, + HEADER_CELL_STYLE); + + // Gap "Licenses" <-> "Developers". + setColumnWidth(table, LICENSES_END_COLUMN, GAP_WIDTH); + + // Create Maven "Miscellaneous" header + createMergedCellsInRow( + table, MISC_START_COLUMN, MISC_END_COLUMN, secondHeaderRow, "Miscellaneous", 1, HEADER_CELL_STYLE); + + // Gap "Developers" <-> "Miscellaneous". + setColumnWidth(table, DEVELOPERS_END_COLUMN, GAP_WIDTH); + + if (hasExtendedInfo) { + createMergedCellsInRow( + table, + MANIFEST_START_COLUMN, + MANIFEST_END_COLUMN, + secondHeaderRow, + "MANIFEST.MF", + 1, + HEADER_CELL_STYLE); + + // Gap "Miscellaneous" <-> "MANIFEST.MF". + setColumnWidth(table, DEVELOPERS_END_COLUMN, GAP_WIDTH); + + createMergedCellsInRow( + table, + INFO_NOTICES_START_COLUMN, + INFO_NOTICES_END_COLUMN, + secondHeaderRow, + "Notices text files", + 1, + HEADER_CELL_STYLE); + + // Gap "MANIFEST.MF" <-> "Notice text files". + setColumnWidth(table, MANIFEST_END_COLUMN, GAP_WIDTH); + + createMergedCellsInRow( + table, + INFO_LICENSES_START_COLUMN, + INFO_LICENSES_END_COLUMN, + secondHeaderRow, + "License text files", + 1, + HEADER_CELL_STYLE); + + // Gap "Notice text files" <-> "License text files". + setColumnWidth(table, INFO_NOTICES_END_COLUMN, GAP_WIDTH); + + createMergedCellsInRow( + table, + INFO_SPDX_START_COLUMN, + INFO_SPDX_END_COLUMN, + secondHeaderRow, + "SPDX license id matched", + 1, + HEADER_CELL_STYLE); + + // Gap "License text files" <-> "SPDX license matches". + setColumnWidth(table, INFO_LICENSES_END_COLUMN, GAP_WIDTH); + } + // sheet.setColumnGroupCollapsed(); + + // General + createCellsInRow(thirdHeaderRow, GENERAL_START_COLUMN, HEADER_CELL_STYLE, "Name"); + // Plugin ID + createCellsInRow( + thirdHeaderRow, PLUGIN_ID_START_COLUMN, HEADER_CELL_STYLE, "Group ID", "Artifact ID", "Version"); + // Licenses + createCellsInRow( + thirdHeaderRow, + LICENSES_START_COLUMN, + HEADER_CELL_STYLE, + "Name", + "URL", + "Distribution", + "Comments", + "File"); + // Developers + createCellsInRow( + thirdHeaderRow, + DEVELOPERS_START_COLUMN, + HEADER_CELL_STYLE, + "Id", + "Email", + "Name", + "Organization", + "Organization URL", + "URL", + "Timezone"); + // Miscellaneous + createCellsInRow( + thirdHeaderRow, MISC_START_COLUMN, HEADER_CELL_STYLE, "Inception Year", "Organization", "SCM", "URL"); + + int headerLineCount = 3; + + if (hasExtendedInfo) { + // MANIFEST.MF + createCellsInRow( + thirdHeaderRow, + MANIFEST_START_COLUMN, + HEADER_CELL_STYLE, + "Bundle license", + "Bundle vendor", + "Implementation vendor"); + // 3 InfoFile groups: Notices, Licenses and SPDX-Licenses. + createInfoFileCellsInRow( + thirdHeaderRow, + HEADER_CELL_STYLE, + INFO_NOTICES_START_COLUMN, + INFO_LICENSES_START_COLUMN, + INFO_SPDX_START_COLUMN); + + createFreezePane(spreadsheet, table, EXTENDED_INFO_END_COLUMN, headerLineCount); + } else { + createFreezePane(spreadsheet, table, MAVEN_END_COLUMN, headerLineCount); + } + + createFreezePane(spreadsheet, table, GENERAL_END_COLUMN, headerLineCount); + } + + private static void setColumnWidth(OdfTable table, int column, int width) { + table.getColumnByIndex(column) + .getOdfElement() + .setProperty(OdfTableColumnProperties.ColumnWidth, (width / 100) + "mm"); + + // table.getColumnByIndex(column).getOdfElement().setProperty(OdfTableColumnProperties.ColumnWidth, + // "001.2000in"); + // table.getColumnByIndex(column).setWidth(width); + } + + private static void createFreezePane( + OdfSpreadsheetDocument spreadsheet, OdfTable table, int column, int lineCount) { + // TODO: Implement + + final OdfSettingsDom settingsDom; + try { + settingsDom = spreadsheet.getSettingsDom(); + + // NodeList childNodes = settingsDom.getChildNodes(); + // for (int i = 0; i < childNodes.getLength(); i++) { + // Node node = childNodes.item(i); + // System.out.println(node); + // + // System.out.println(node.getChildNodes()); + // } + // System.out.println(childNodes); + } catch (Exception e) { + throw new RuntimeException(e); + } + + NodeList childNodes = settingsDom.getFirstChild().getFirstChild().getChildNodes(); + for (int i = 0; i < childNodes.getLength(); i++) { + Node child = childNodes.item(i); + if ("config:config-item-set".equals(child.getNodeName()) + && "ooo:view-settings".equals(((Element) child).getAttribute("config:name"))) { + + NodeList subChilds = child.getChildNodes(); + for (int j = 0; j < subChilds.getLength(); j++) { + Node subChild = subChilds.item(j); + if ("config:config-item-map-indexed".equals(subChild.getNodeName()) + && "Views".equals(((Element) subChild).getAttribute("config:name"))) { + + break; + } + } + break; + } + } + + XPath xpath = settingsDom.getXPath(); + NodeList list; + try { + list = (NodeList) xpath.evaluate( + "/office:document-settings/" + "office:settings/" + + "config:config-item-set/" + + "config:config-item-map-indexed/" + + "config:config-item-map-entry/" + + "config:config-item-map-named/" + + "config:config-item-map-entry", + // "/config:config-item-set[@config:name=\"ooo:view-settings\"]" + + settingsDom, + XPathConstants.NODE); + + /* + 2 + 2 + 1 + 4 + 3 + + 0 + 1 + 0 + 3 + */ + if (list instanceof ConfigConfigItemMapEntryElement) { + ConfigConfigItemMapEntryElement entryElement = (ConfigConfigItemMapEntryElement) list; + + appendConfigItemElement(entryElement, "HorizontalSplitMode", "short", "2"); + appendConfigItemElement(entryElement, "VerticalSplitMode", "short", "2"); + + appendConfigItemElement(entryElement, "HorizontalSplitPosition", "int", "1"); + appendConfigItemElement(entryElement, "VerticalSplitPosition", "int", "3"); + + appendConfigItemElement(entryElement, "ActiveSplitRange", "short", "3"); + + appendConfigItemElement(entryElement, "PositionLeft", "int", "0"); + appendConfigItemElement(entryElement, "PositionRight", "int", "1"); + appendConfigItemElement(entryElement, "PositionTop", "int", "0"); + appendConfigItemElement(entryElement, "PositionBottom", "int", "3"); + + appendConfigItemElement(entryElement, "ShowGrid", "boolean", "true"); + appendConfigItemElement(entryElement, "AnchoredTextOverflowLegacy", "boolean", "false"); + } + } catch (XPathExpressionException e) { + throw new RuntimeException(e); + } + } + + private static void appendConfigItemElement( + ConfigConfigItemMapEntryElement entryElement, String configName, String configType, String nodeValue) { + ConfigConfigItemElement horizontalSplitMode = null; + if (entryElement.hasChildNodes()) { + NodeList nodeList = entryElement.getChildNodes(); + for (int i = 0; i < nodeList.getLength(); i++) { + Node node = nodeList.item(i); + if (node instanceof ConfigConfigItemElement) { + ConfigConfigItemElement itemElement = (ConfigConfigItemElement) node; + if (configName.equals(itemElement.getConfigNameAttribute())) { + horizontalSplitMode = (ConfigConfigItemElement) node; + break; + } + } + } + } + if (horizontalSplitMode == null) { + horizontalSplitMode = entryElement.newConfigConfigItemElement(configName, configType); + } else { + if (horizontalSplitMode.hasChildNodes()) { + // Find text node and set new value if found. + for (int i = 0; i < horizontalSplitMode.getLength(); i++) { + Node child = horizontalSplitMode.item(i); + if (child.getNodeType() == Node.TEXT_NODE) { + child.setNodeValue(nodeValue); + return; + } + } + } + } + horizontalSplitMode.newTextNode(nodeValue); + } + + private static void createHeaderStyle(OdfSpreadsheetDocument spreadsheet) { + OdfOfficeStyles styles = spreadsheet.getOrCreateDocumentStyles(); + OdfStyle headerStyle = styles.newStyle(HEADER_CELL_STYLE, OdfStyleFamily.TableCell); + + headerStyle.setProperty(StyleTextPropertiesElement.FontFamily, "Arial"); + headerStyle.setProperty(StyleTextPropertiesElement.FontWeight, "bold"); + headerStyle.setProperty(StyleTableCellPropertiesElement.BackgroundColor, "#CCFFCC"); + headerStyle.setProperty(StyleParagraphPropertiesElement.TextAlign, "center"); + headerStyle.setProperty(StyleTableCellPropertiesElement.VerticalAlign, "middle"); + headerStyle.setProperty(StyleTableCellPropertiesElement.Border, "1.0pt solid #000000"); + } + + // TODO: Clean this method up. Too many parameters, too complicated parameters/DTO pattern. But keep it still + // threadsafe. + private static void writeData( + List projectLicenseInfos, + OdfSpreadsheetDocument wb, + OdfTable table, + Color alternatingRowsColor) { + final int firstRowIndex = 3; + int currentRowIndex = firstRowIndex; + final Map rowMap = new HashMap<>(); + boolean hasExtendedInfo = false; + + final OdfStyle hyperlinkStyleNormal = createHyperlinkStyle(wb, HYPERLINK_NORMAL_STYLE, null); + final OdfStyle hyperlinkStyleGray = createHyperlinkStyle(wb, HYPERLINK_GRAY_STYLE, alternatingRowsColor); + + boolean grayBackground = false; + OdfOfficeStyles officeStyles = wb.getOrCreateDocumentStyles(); + OdfStyle styleGray = officeStyles.newStyle(GRAY_CELL_STYLE, OdfStyleFamily.TableCell); + styleGray.setProperty(StyleTableCellPropertiesElement.BackgroundColor, alternatingRowsColor.toString()); + styleGray.setProperty(OdfTableColumnProperties.UseOptimalColumnWidth, String.valueOf(true)); + + /* Set own, empty style, instead of leaving the style out, + because otherwise it copies the style of the row above. */ + OdfStyle styleNormal = officeStyles.newStyle(NORMAL_CELL_STYLE, OdfStyleFamily.TableCell); + styleNormal.setProperty(OdfTableColumnProperties.UseOptimalColumnWidth, String.valueOf(true)); + + for (ProjectLicenseInfo projectInfo : projectLicenseInfos) { + final OdfStyle cellStyle, hyperlinkStyle; + if (grayBackground) { + cellStyle = styleGray; + hyperlinkStyle = hyperlinkStyleGray; + } else { + cellStyle = styleNormal; + hyperlinkStyle = hyperlinkStyleNormal; + } + grayBackground = !grayBackground; + + int extraRows = 0; + OdfTableRow currentRow = table.appendRow(); + rowMap.put(currentRowIndex, currentRow); + // Plugin ID + createDataCellsInRow( + currentRow, + PLUGIN_ID_START_COLUMN, + cellStyle, + projectInfo.getGroupId(), + projectInfo.getArtifactId(), + projectInfo.getVersion()); + // Licenses + final CellListParameter cellListParameter = new CellListParameter(table, rowMap, cellStyle); + CurrentRowData currentRowData = new CurrentRowData(currentRowIndex, extraRows, hasExtendedInfo); + extraRows = addList( + cellListParameter, + currentRowData, + LICENSES_START_COLUMN, + LICENSES_COLUMNS, + projectInfo.getLicenses(), + (OdfTableRow licenseRow, ProjectLicense license) -> { + OdfTableCell[] licenses = createDataCellsInRow( + licenseRow, + LICENSES_START_COLUMN, + cellStyle, + license.getName(), + license.getUrl(), + license.getDistribution(), + license.getComments(), + license.getFile()); + addHyperlinkIfExists(table, licenses[1], hyperlinkStyle); + }); + + final ExtendedInfo extendedInfo = projectInfo.getExtendedInfo(); + if (extendedInfo != null) { + hasExtendedInfo = true; + // General + createDataCellsInRow(currentRow, GENERAL_START_COLUMN, cellStyle, extendedInfo.getName()); + // Developers + currentRowData = new CurrentRowData(currentRowIndex, extraRows, hasExtendedInfo); + extraRows = addList( + cellListParameter, + currentRowData, + DEVELOPERS_START_COLUMN, + DEVELOPERS_COLUMNS, + extendedInfo.getDevelopers(), + (OdfTableRow developerRow, Developer developer) -> { + OdfTableCell[] licenses = createDataCellsInRow( + developerRow, + DEVELOPERS_START_COLUMN, + cellStyle, + developer.getId(), + developer.getEmail(), + developer.getName(), + developer.getOrganization(), + developer.getOrganizationUrl(), + developer.getUrl(), + developer.getTimezone()); + addHyperlinkIfExists(table, licenses[1], hyperlinkStyle, true); + addHyperlinkIfExists(table, licenses[4], hyperlinkStyle); + addHyperlinkIfExists(table, licenses[5], hyperlinkStyle); + }); + // Miscellaneous + OdfTableCell[] miscCells = createDataCellsInRow( + currentRow, + MISC_START_COLUMN, + cellStyle, + extendedInfo.getInceptionYear(), + Optional.ofNullable(extendedInfo.getOrganization()) + .map(Organization::getName) + .orElse(null), + Optional.ofNullable(extendedInfo.getScm()) + .map(Scm::getUrl) + .orElse(null), + extendedInfo.getUrl()); + addHyperlinkIfExists(table, miscCells[2], hyperlinkStyle); + addHyperlinkIfExists(table, miscCells[3], hyperlinkStyle); + + // MANIFEST.MF + createDataCellsInRow( + currentRow, + MANIFEST_START_COLUMN, + cellStyle, + extendedInfo.getBundleLicense(), + extendedInfo.getBundleVendor(), + extendedInfo.getImplementationVendor()); + + // Info files + if (!CollectionUtils.isEmpty(extendedInfo.getInfoFiles())) { + // Sort all info files by type into 3 different lists, each list for each of the 3 types. + List notices = new ArrayList<>(); + List licenses = new ArrayList<>(); + List spdxs = new ArrayList<>(); + extendedInfo.getInfoFiles().forEach(infoFile -> { + switch (infoFile.getType()) { + case LICENSE: + licenses.add(infoFile); + break; + case NOTICE: + notices.add(infoFile); + break; + case SPDX_LICENSE: + spdxs.add(infoFile); + break; + default: + break; + } + }); + // InfoFile notices text file + currentRowData = new CurrentRowData(currentRowIndex, extraRows, hasExtendedInfo); + extraRows = addInfoFileList( + cellListParameter, + currentRowData, + INFO_NOTICES_START_COLUMN, + INFO_NOTICES_COLUMNS, + notices); + // InfoFile licenses text file + currentRowData = new CurrentRowData(currentRowIndex, extraRows, hasExtendedInfo); + extraRows = addInfoFileList( + cellListParameter, + currentRowData, + INFO_LICENSES_START_COLUMN, + INFO_LICENSES_COLUMNS, + licenses); + // InfoFile spdx licenses text file + currentRowData = new CurrentRowData(currentRowIndex, extraRows, hasExtendedInfo); + extraRows = addInfoFileList( + cellListParameter, currentRowData, INFO_SPDX_START_COLUMN, INFO_SPDX_COLUMNS, spdxs); + } else if (cellListParameter.cellStyle != null) { + setStyleOnEmptyCells( + cellListParameter, currentRowData, INFO_NOTICES_START_COLUMN, INFO_NOTICES_COLUMNS); + setStyleOnEmptyCells( + cellListParameter, currentRowData, INFO_LICENSES_START_COLUMN, INFO_LICENSES_COLUMNS); + setStyleOnEmptyCells(cellListParameter, currentRowData, INFO_SPDX_START_COLUMN, INFO_SPDX_COLUMNS); + } + } else { + createDataCellsInRow(currentRow, GENERAL_START_COLUMN, cellStyle, 1); + createDataCellsInRow(currentRow, DEVELOPERS_START_COLUMN, cellStyle, DEVELOPERS_COLUMNS); + createDataCellsInRow(currentRow, MISC_START_COLUMN, cellStyle, MISC_COLUMNS); + } + currentRowIndex += extraRows + 1; + } + + autosizeColumns(table, hasExtendedInfo, currentRowIndex); + } + + private static OdfStyle createHyperlinkStyle( + OdfSpreadsheetDocument wb, String name, @Nullable Color backgroundColor) { + OdfOfficeStyles styles = wb.getOrCreateDocumentStyles(); + OdfStyle hyperlinkStyle = styles.newStyle(name, OdfStyleFamily.TableCell); + + hyperlinkStyle.setProperty(StyleTextPropertiesElement.FontFamily, "Arial"); + hyperlinkStyle.setProperty(StyleTextPropertiesElement.Color, Color.BLUE.toString()); + hyperlinkStyle.setProperty(StyleParagraphPropertiesElement.TextAlign, "center"); + hyperlinkStyle.setProperty(StyleTableCellPropertiesElement.VerticalAlign, "middle"); + + if (backgroundColor != null) { + hyperlinkStyle.setProperty(StyleTableCellPropertiesElement.BackgroundColor, backgroundColor.toString()); + } + return hyperlinkStyle; + } + + private static void autosizeColumns(OdfTable table, boolean hasExtendedInfo, int rows) { + autosizeColumns( + table, + rows, + new ImmutablePair<>(GENERAL_START_COLUMN, GENERAL_END_COLUMN), + new ImmutablePair<>(PLUGIN_ID_START_COLUMN, PLUGIN_ID_END_COLUMN), + new ImmutablePair<>(LICENSES_START_COLUMN, LICENSES_END_COLUMN), + new ImmutablePair<>(DEVELOPERS_START_COLUMN, DEVELOPERS_END_COLUMN - 1), + new ImmutablePair<>(MISC_START_COLUMN + 1, MISC_END_COLUMN)); + // The column header widths are most likely wider than the actual cells content. + setColumnWidth(table, DEVELOPERS_END_COLUMN - 1, TIMEZONE_WIDTH); + setColumnWidth(table, MISC_START_COLUMN, INCEPTION_YEAR_WIDTH); + if (hasExtendedInfo) { + autosizeColumns( + table, + rows, + new ImmutablePair<>(MANIFEST_START_COLUMN, MANIFEST_END_COLUMN), + new ImmutablePair<>(INFO_NOTICES_START_COLUMN + 2, INFO_NOTICES_END_COLUMN), + new ImmutablePair<>(INFO_LICENSES_START_COLUMN + 2, INFO_LICENSES_END_COLUMN), + new ImmutablePair<>(INFO_SPDX_START_COLUMN + 2, INFO_SPDX_END_COLUMN)); + } + } + + @SafeVarargs + private static void autosizeColumns(OdfTable sheet, int rows, Pair... ranges) { + for (Pair range : ranges) { + for (int i = range.getLeft(); i < range.getRight(); i++) { + final float sizeFactor = 2.0f; + float size = 25; + // Get max width by taking the max string length multiplied by sizeFactor. + for (int row = 0; row < rows; row++) { + OdfTableCell cell = sheet.getCellByPosition(i, row); + if ("string".equals(cell.getValueType())) { + String stringValue = cell.getStringValue(); + size = Math.max(stringValue.length() * sizeFactor, size); + } + } + final OdfTableColumn column = sheet.getColumnByIndex(i); + // The attribute is ignored by LibreOffice Calc, set it for other applications. + column.setUseOptimalWidth(true); + + column.setWidth((long) size); + } + } + } + + private static int addInfoFileList( + CellListParameter cellListParameter, + CurrentRowData currentRowData, + int startColumn, + int columnsToFill, + List infoFiles) { + return addList( + cellListParameter, + currentRowData, + startColumn, + columnsToFill, + infoFiles, + (OdfTableRow infoFileRow, InfoFile infoFile) -> { + final String copyrightLines = Optional.ofNullable(infoFile.getExtractedCopyrightLines()) + .map(strings -> String.join(COPYRIGHT_JOIN_SEPARATOR, strings)) + .orElse(null); + createDataCellsInRow( + infoFileRow, + startColumn, + cellListParameter.getCellStyle(), + infoFile.getContent(), + copyrightLines, + infoFile.getFileName()); + }); + } + + private static int addList( + CellListParameter cellListParameter, + CurrentRowData currentRowData, + int startColumn, + int columnsToFill, + List list, + BiConsumer biConsumer) { + if (!CollectionUtils.isEmpty(list)) { + for (int i = 0; i < list.size(); i++) { + T type = list.get(i); + Integer index = currentRowData.getCurrentRowIndex() + i; + OdfTableRow row = cellListParameter.getRows().get(index); + if (row == null) { + row = cellListParameter.getSheet().appendRow(); + cellListParameter.getRows().put(index, row); + if (cellListParameter.getCellStyle() != null) { + // Style all empty left cells, in the columns left from this + createAndStyleCells( + row, + cellListParameter.getCellStyle(), + new ImmutablePair<>(GENERAL_START_COLUMN, GENERAL_END_COLUMN), + new ImmutablePair<>(PLUGIN_ID_START_COLUMN, PLUGIN_ID_END_COLUMN), + new ImmutablePair<>(LICENSES_START_COLUMN, LICENSES_END_COLUMN)); + if (currentRowData.isHasExtendedInfo()) { + createAndStyleCells( + row, + cellListParameter.getCellStyle(), + new ImmutablePair<>(DEVELOPERS_START_COLUMN, DEVELOPERS_END_COLUMN), + new ImmutablePair<>(MISC_START_COLUMN, MISC_END_COLUMN), + // JAR + new ImmutablePair<>(MANIFEST_START_COLUMN, MANIFEST_END_COLUMN), + new ImmutablePair<>(INFO_LICENSES_START_COLUMN, INFO_LICENSES_END_COLUMN), + new ImmutablePair<>(INFO_NOTICES_START_COLUMN, INFO_NOTICES_END_COLUMN), + new ImmutablePair<>(INFO_SPDX_START_COLUMN, INFO_SPDX_END_COLUMN)); + } + } + currentRowData.setExtraRows(currentRowData.getExtraRows() + 1); + } + biConsumer.accept(row, type); + } + } else if (cellListParameter.cellStyle != null) { + setStyleOnEmptyCells(cellListParameter, currentRowData, startColumn, columnsToFill); + } + return currentRowData.getExtraRows(); + } + + /** + * If no cells are set, color at least the background, + * to color concatenated blocks with the same background color. + * + * @param cellListParameter Passes data about sheet, row, cell style. + * @param currentRowData Passes data about the current indices for rows and columns. + * @param startColumn Column where to start setting the style. + * @param columnsToFill How many columns to set the style on, starting from 'startColumn'. + */ + private static void setStyleOnEmptyCells( + CellListParameter cellListParameter, CurrentRowData currentRowData, int startColumn, int columnsToFill) { + OdfTableRow row = cellListParameter.getRows().get(currentRowData.getCurrentRowIndex()); + for (int i = 0; i < columnsToFill; i++) { + OdfTableCell cell = row.getCellByIndex(startColumn + i); + cell.setValueType("string"); + cell.getOdfElement().setStyleName(getCellStyleName(cellListParameter.getCellStyle())); + } + } + + @SafeVarargs + private static void createAndStyleCells(OdfTableRow row, OdfStyle cellStyle, Pair... ranges) { + for (Pair range : ranges) { + for (int i = range.getLeft(); i < range.getRight(); i++) { + OdfTableCell cell = row.getCellByIndex(i); + cell.setValueType("string"); + cell.getOdfElement().setStyleName(getCellStyleName(cellStyle)); + } + } + } + + public static void applyHyperlink(OdfTable table, OdfTableCell cell, String hyperlink, boolean isEmail) { + + TextAElement aElement; + aElement = ((OdfContentDom) (table.getOdfElement().getOwnerDocument())).newOdfElement(TextAElement.class); + aElement.setXlinkTypeAttribute("simple"); + hyperlink = hyperlink.trim().replace(" dot ", "."); + if (isEmail) { + hyperlink = hyperlink.replace(" at ", "@"); + if (hyperlink.contains("@") && hyperlink.matches(".*\\s[a-zA-Z]{2,3}$")) { + hyperlink = hyperlink.replaceAll(" ", "."); + } + } + aElement.setXlinkHrefAttribute(isEmail ? "mailto:" + hyperlink : hyperlink); + aElement.setTextContent(hyperlink); + Node node = cell.getOdfElement().getFirstChild(); + + node.appendChild(aElement); + } + + private static void addHyperlinkIfExists( + OdfTable table, OdfTableCell cell, OdfStyle hyperlinkStyle) { + addHyperlinkIfExists(table, cell, hyperlinkStyle, false); + } + + private static void addHyperlinkIfExists( + OdfTable table, + OdfTableCell cell, + OdfStyle hyperlinkStyle, + boolean isEmail) { + if (!StringUtils.isEmpty(cell.getStringValue())) { + try { + cell.getOdfElement().setStyleName(getCellStyleName(hyperlinkStyle)); + + String content = cell.getStringValue(); + cell.setStringValue(""); + + applyHyperlink(table, cell, content, isEmail); + } catch (IllegalArgumentException e) { + LOG.debug( + "Can't set Hyperlink for cell value " + cell.getStringValue() + " it gets rejected as URI", e); + } + } + } + + /** + * Create data cells in row. + * + * @param row Row. + * @param startColumn Starting column. + * @param cellStyle Cell style. + * @param names Name of cell values. + * @return Array of created table cells. + */ + private static OdfTableCell[] createDataCellsInRow( + OdfTableRow row, int startColumn, OdfStyle cellStyle, String... names) { + OdfTableCell[] result = new OdfTableCell[names.length]; + for (int i = 0; i < names.length; i++) { + OdfTableCell cell = row.getCellByIndex(startColumn + i); + cell.setValueType("string"); + if (cellStyle != null) { + cell.getOdfElement().setStyleName(getCellStyleName(cellStyle)); + } + if (!StringUtils.isEmpty(names[i])) { + final String value; + final int maxCellStringLength = Short.MAX_VALUE; + if (names[i].length() > maxCellStringLength) { + value = names[i].substring(0, maxCellStringLength - 3) + "..."; + } else { + value = names[i]; + } + cell.setStringValue(value); + } + result[i] = cell; + } + return result; + } + + /** + * Fills cells with empty strings, so they get created and don't copy the previous rows content and style, + * like the header's background color and bold border. + * + * @param row Row. + * @param startColumn Starting column (inclusive). + * @param cellStyle Cell style. + * @param count Number of columns to set. + */ + private static void createDataCellsInRow( + OdfTableRow row, int startColumn, OdfStyle cellStyle, int count) { + for (int i = 0; i < count; i++) { + OdfTableCell cell = row.getCellByIndex(startColumn + i); + cell.setValueType("string"); + if (cellStyle != null) { + cell.getOdfElement().setStyleName(getCellStyleName(cellStyle)); + } + cell.setStringValue(""); + } + } + + private static String getCellStyleName(OdfStyle cellStyle) { + return cellStyle.getAttributes().item(1).getNodeValue(); + } + + /** + * Create cells for InfoFile content. + * + * @param row The row to insert cells into. + * @param styleName Name of the style. + * @param startPositions The start position of the 3 columns for an InfoFile. + */ + private static void createInfoFileCellsInRow(OdfTableRow row, String styleName, int... startPositions) { + for (int startPosition : startPositions) { + createCellsInRow(row, startPosition, styleName, "Content", "Extracted copyright lines", "File"); + } + } + + private static void createCellsInRow(OdfTableRow row, int startColumn, String styleName, String... names) { + for (int i = 0; i < names.length; i++) { + OdfTableCell cell = row.getCellByIndex(startColumn + i); + cell.setValueType("string"); + cell.getOdfElement().setStyleName(styleName); + cell.setStringValue(names[i]); + } + } + + private static void createMergedCellsInRow( + OdfTable table, + int startColumn, + int endColumn, + OdfTableRow row, + String cellValue, + int rowIndex, + String styleName) { + OdfTableCell cell = createCellsInRow(startColumn, endColumn, row); + final boolean merge = endColumn - 1 > startColumn; + + if (merge) { + OdfTableCellRange cellRange = table.getCellRangeByPosition(startColumn, rowIndex, endColumn - 1, rowIndex); + cellRange.merge(); + } + + // Set value and style only after merge + cell.setStringValue(cellValue); + cell.getOdfElement().setStyleName(styleName); + + // TODO: Add grouping correct with a hierarchy. + // if (merge) { + // TableTableColumnGroupElement groupElement = table.getOdfElement().newTableTableColumnGroupElement(); + // for (int i = startColumn; i < endColumn - 1; i++) { + // TableTableColumnElement columnElement = groupElement.newTableTableColumnElement(); + // // Add style to "columnElement"? + // } + // } + } + + private static String convertIndexToLetter(int column) { + return String.valueOf((char) ('A' + column)); + } + + private static OdfTableCell createCellsInRow(int startColumn, int exclusiveEndColumn, OdfTableRow inRow) { + OdfTableCell firstCell = null; + for (int i = startColumn; i < exclusiveEndColumn; i++) { + OdfTableCell cell = inRow.getCellByIndex(i); + if (i == startColumn) { + firstCell = cell; + } + } + return firstCell; + } + + /** + * Parameters for cells which apply to all cells in each loop iteration. + */ + private static class CellListParameter { + private final OdfTable sheet; + private final Map rows; + private final OdfStyle cellStyle; + + private CellListParameter(OdfTable sheet, Map rows, OdfStyle cellStyle) { + this.sheet = sheet; + this.rows = rows; + this.cellStyle = cellStyle; + } + + OdfTable getSheet() { + return sheet; + } + + Map getRows() { + return rows; + } + + OdfStyle getCellStyle() { + return cellStyle; + } + } +} diff --git a/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/ExcelFileWriter.java b/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/ExcelFileWriter.java index 09d4c7c64..fee3059f9 100644 --- a/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/ExcelFileWriter.java +++ b/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/ExcelFileWriter.java @@ -22,11 +22,10 @@ * #L% */ -import java.awt.Color; import java.io.File; -import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; +import java.nio.file.Files; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -73,71 +72,8 @@ * Writes project license infos into Excel file. */ public class ExcelFileWriter { - private static final Logger LOG = LoggerFactory.getLogger(ExcelFileWriter.class); - - // Columns values for Maven data, including separator gaps for data grouping. - private static final int GENERAL_START_COLUMN = 0, - GENERAL_COLUMNS = 1, - GENERAL_END_COLUMN = GENERAL_START_COLUMN + GENERAL_COLUMNS; - private static final int PLUGIN_ID_START_COLUMN = GENERAL_END_COLUMN + 1, - PLUGIN_ID_COLUMNS = 3, - PLUGIN_ID_END_COLUMN = PLUGIN_ID_START_COLUMN + PLUGIN_ID_COLUMNS; - // "Start" column are the actual start columns, they are inclusive. - // "End" columns point just one column behind the last one, it's the exclusive column index. - private static final int LICENSES_START_COLUMN = PLUGIN_ID_END_COLUMN + 1, - LICENSES_COLUMNS = 5, - LICENSES_END_COLUMN = LICENSES_START_COLUMN + LICENSES_COLUMNS; - private static final int DEVELOPERS_START_COLUMN = LICENSES_END_COLUMN + 1, - DEVELOPERS_COLUMNS = 7, - DEVELOPERS_END_COLUMN = DEVELOPERS_START_COLUMN + DEVELOPERS_COLUMNS; - private static final int MISC_START_COLUMN = DEVELOPERS_END_COLUMN + 1, - MISC_COLUMNS = 4, - MISC_END_COLUMN = MISC_START_COLUMN + MISC_COLUMNS; - private static final int - MAVEN_DATA_COLUMNS = - GENERAL_COLUMNS + PLUGIN_ID_COLUMNS + LICENSES_COLUMNS + DEVELOPERS_COLUMNS + MISC_COLUMNS, - MAVEN_COLUMN_GROUPING_GAPS = 4; - private static final int MAVEN_START_COLUMN = 0, - MAVEN_COLUMNS = MAVEN_DATA_COLUMNS + MAVEN_COLUMN_GROUPING_GAPS, - MAVEN_END_COLUMN = MAVEN_START_COLUMN + MAVEN_COLUMNS; - - // Columns values for JAR data, including separator gaps for data grouping. - private static final int INFO_FILES_GAPS = 2, MANIFEST_GAPS = 1; - private static final int MANIFEST_START_COLUMN = MAVEN_COLUMNS + 1, - MANIFEST_COLUMNS = 3, - MANIFEST_END_COLUMN = MANIFEST_START_COLUMN + MANIFEST_COLUMNS; - private static final int INFO_NOTICES_START_COLUMN = MANIFEST_END_COLUMN + 1, - INFO_NOTICES_COLUMNS = 3, - INFO_NOTICES_END_COLUMN = INFO_NOTICES_START_COLUMN + INFO_NOTICES_COLUMNS; - private static final int INFO_LICENSES_START_COLUMN = INFO_NOTICES_END_COLUMN + 1, - INFO_LICENSES_COLUMNS = 3, - INFO_LICENSES_END_COLUMN = INFO_LICENSES_START_COLUMN + INFO_LICENSES_COLUMNS; - private static final int INFO_SPDX_START_COLUMN = INFO_LICENSES_END_COLUMN + 1, - INFO_SPDX_COLUMNS = 3, - INFO_SPDX_END_COLUMN = INFO_SPDX_START_COLUMN + INFO_SPDX_COLUMNS; - private static final int EXTENDED_INFO_START_COLUMN = MAVEN_END_COLUMN + 1, - EXTENDED_INFO_COLUMNS = - MANIFEST_COLUMNS - + INFO_NOTICES_COLUMNS - + INFO_LICENSES_COLUMNS - + INFO_SPDX_COLUMNS - + INFO_FILES_GAPS - + MANIFEST_GAPS, - EXTENDED_INFO_END_COLUMN = EXTENDED_INFO_START_COLUMN + EXTENDED_INFO_COLUMNS; - - // Width of gap columns - private static final int EXCEL_WIDTH_SCALE = 256; - private static final int GAP_WIDTH = 3 * EXCEL_WIDTH_SCALE; private static final BorderStyle HEADER_CELLS_BORDER_STYLE = BorderStyle.MEDIUM; - private static final int TIMEZONE_WIDTH = " Timezone ".length() * EXCEL_WIDTH_SCALE, - INCEPTION_YEAR_WIDTH = " Inception Year ".length() * EXCEL_WIDTH_SCALE; - /** - * Color must be dark enough for low contrast monitors. - *
If you get a compile error here, make sure you're using Java 8, not higher. - */ - private static final Color ALTERNATING_ROWS_COLOR = new Color(220, 220, 220); - - private static final String COPYRIGHT_JOIN_SEPARATOR = "§"; + private static final Logger LOG = LoggerFactory.getLogger(ExcelFileWriter.class); /** * Writes list of projects into excel file. @@ -155,13 +91,13 @@ public static void write(List projectLicenseInfos, final Fil final Sheet sheet = wb.createSheet(WorkbookUtil.createSafeSheetName("License information")); final IndexedColorMap colorMap = wb.getStylesSource().getIndexedColors(); - final XSSFColor alternatingRowsColor = new XSSFColor(ALTERNATING_ROWS_COLOR, colorMap); + final XSSFColor alternatingRowsColor = new XSSFColor(SpreadsheetUtil.ALTERNATING_ROWS_COLOR, colorMap); createHeader(projectLicenseInfos, wb, sheet); writeData(projectLicenseInfos, wb, sheet, alternatingRowsColor); - try (OutputStream fileOut = new FileOutputStream(licensesExcelOutputFile)) { + try (OutputStream fileOut = Files.newOutputStream(licensesExcelOutputFile.toPath())) { wb.write(fileOut); } catch (IOException e) { LOG.error("Error on storing Excel file with license and other information", e); @@ -192,18 +128,24 @@ private static void createHeader(List projectLicenseInfos, W // Create Maven header cell createMergedCellsInRow( - sheet, MAVEN_START_COLUMN, MAVEN_END_COLUMN, headerCellStyle, mavenJarRow, "Maven information", 0); + sheet, + SpreadsheetUtil.MAVEN_START_COLUMN, + SpreadsheetUtil.MAVEN_END_COLUMN, + headerCellStyle, + mavenJarRow, + "Maven information", + 0); if (hasExtendedInfo) { // Create JAR header cell createMergedCellsInRow( - sheet, - EXTENDED_INFO_START_COLUMN, - EXTENDED_INFO_END_COLUMN, - headerCellStyle, - mavenJarRow, - "JAR Content", - 0); + sheet, + SpreadsheetUtil.EXTENDED_INFO_START_COLUMN, + SpreadsheetUtil.EXTENDED_INFO_END_COLUMN, + headerCellStyle, + mavenJarRow, + "JAR Content", + 0); } // Create 2nd header row @@ -211,90 +153,114 @@ private static void createHeader(List projectLicenseInfos, W // Create Maven "General" header createMergedCellsInRow( - sheet, GENERAL_START_COLUMN, GENERAL_END_COLUMN, headerCellStyle, secondHeaderRow, "General", 1); + sheet, + SpreadsheetUtil.GENERAL_START_COLUMN, + SpreadsheetUtil.GENERAL_END_COLUMN, + headerCellStyle, + secondHeaderRow, + "General", + 1); // Create Maven "Plugin ID" header createMergedCellsInRow( - sheet, PLUGIN_ID_START_COLUMN, PLUGIN_ID_END_COLUMN, headerCellStyle, secondHeaderRow, "Plugin ID", 1); + sheet, + SpreadsheetUtil.PLUGIN_ID_START_COLUMN, + SpreadsheetUtil.PLUGIN_ID_END_COLUMN, + headerCellStyle, + secondHeaderRow, + "Plugin ID", + 1); // Gap "General" <-> "Plugin ID". - sheet.setColumnWidth(GENERAL_END_COLUMN, GAP_WIDTH); + sheet.setColumnWidth(SpreadsheetUtil.GENERAL_END_COLUMN, SpreadsheetUtil.GAP_WIDTH); // Create Maven "Licenses" header createMergedCellsInRow( - sheet, LICENSES_START_COLUMN, LICENSES_END_COLUMN, headerCellStyle, secondHeaderRow, "Licenses", 1); + sheet, + SpreadsheetUtil.LICENSES_START_COLUMN, + SpreadsheetUtil.LICENSES_END_COLUMN, + headerCellStyle, + secondHeaderRow, + "Licenses", + 1); // Gap "Plugin ID" <-> "Licenses". - sheet.setColumnWidth(PLUGIN_ID_END_COLUMN, GAP_WIDTH); + sheet.setColumnWidth(SpreadsheetUtil.PLUGIN_ID_END_COLUMN, SpreadsheetUtil.GAP_WIDTH); // Create Maven "Developers" header createMergedCellsInRow( - sheet, - DEVELOPERS_START_COLUMN, - DEVELOPERS_END_COLUMN, - headerCellStyle, - secondHeaderRow, - "Developers", - 1); + sheet, + SpreadsheetUtil.DEVELOPERS_START_COLUMN, + SpreadsheetUtil.DEVELOPERS_END_COLUMN, + headerCellStyle, + secondHeaderRow, + "Developers", + 1); // Gap "Licenses" <-> "Developers". - sheet.setColumnWidth(LICENSES_END_COLUMN, GAP_WIDTH); + sheet.setColumnWidth(SpreadsheetUtil.LICENSES_END_COLUMN, SpreadsheetUtil.GAP_WIDTH); // Create Maven "Miscellaneous" header createMergedCellsInRow( - sheet, MISC_START_COLUMN, MISC_END_COLUMN, headerCellStyle, secondHeaderRow, "Miscellaneous", 1); + sheet, + SpreadsheetUtil.MISC_START_COLUMN, + SpreadsheetUtil.MISC_END_COLUMN, + headerCellStyle, + secondHeaderRow, + "Miscellaneous", + 1); // Gap "Developers" <-> "Miscellaneous". - sheet.setColumnWidth(DEVELOPERS_END_COLUMN, GAP_WIDTH); + sheet.setColumnWidth(SpreadsheetUtil.DEVELOPERS_END_COLUMN, SpreadsheetUtil.GAP_WIDTH); if (hasExtendedInfo) { createMergedCellsInRow( - sheet, - MANIFEST_START_COLUMN, - MANIFEST_END_COLUMN, - headerCellStyle, - secondHeaderRow, - "MANIFEST.MF", - 1); + sheet, + SpreadsheetUtil.MANIFEST_START_COLUMN, + SpreadsheetUtil.MANIFEST_END_COLUMN, + headerCellStyle, + secondHeaderRow, + "MANIFEST.MF", + 1); // Gap "Miscellaneous" <-> "MANIFEST.MF". - sheet.setColumnWidth(DEVELOPERS_END_COLUMN, GAP_WIDTH); + sheet.setColumnWidth(SpreadsheetUtil.DEVELOPERS_END_COLUMN, SpreadsheetUtil.GAP_WIDTH); createMergedCellsInRow( - sheet, - INFO_NOTICES_START_COLUMN, - INFO_NOTICES_END_COLUMN, - headerCellStyle, - secondHeaderRow, - "Notices text files", - 1); + sheet, + SpreadsheetUtil.INFO_NOTICES_START_COLUMN, + SpreadsheetUtil.INFO_NOTICES_END_COLUMN, + headerCellStyle, + secondHeaderRow, + "Notices text files", + 1); // Gap "MANIFEST.MF" <-> "Notice text files". - sheet.setColumnWidth(MANIFEST_END_COLUMN, GAP_WIDTH); + sheet.setColumnWidth(SpreadsheetUtil.MANIFEST_END_COLUMN, SpreadsheetUtil.GAP_WIDTH); createMergedCellsInRow( - sheet, - INFO_LICENSES_START_COLUMN, - INFO_LICENSES_END_COLUMN, - headerCellStyle, - secondHeaderRow, - "License text files", - 1); + sheet, + SpreadsheetUtil.INFO_LICENSES_START_COLUMN, + SpreadsheetUtil.INFO_LICENSES_END_COLUMN, + headerCellStyle, + secondHeaderRow, + "License text files", + 1); // Gap "Notice text files" <-> "License text files". - sheet.setColumnWidth(INFO_NOTICES_END_COLUMN, GAP_WIDTH); + sheet.setColumnWidth(SpreadsheetUtil.INFO_NOTICES_END_COLUMN, SpreadsheetUtil.GAP_WIDTH); createMergedCellsInRow( - sheet, - INFO_SPDX_START_COLUMN, - INFO_SPDX_END_COLUMN, - headerCellStyle, - secondHeaderRow, - "SPDX license id matched", - 1); + sheet, + SpreadsheetUtil.INFO_SPDX_START_COLUMN, + SpreadsheetUtil.INFO_SPDX_END_COLUMN, + headerCellStyle, + secondHeaderRow, + "SPDX license id matched", + 1); // Gap "License text files" <-> "SPDX license matches". - sheet.setColumnWidth(INFO_LICENSES_END_COLUMN, GAP_WIDTH); + sheet.setColumnWidth(SpreadsheetUtil.INFO_LICENSES_END_COLUMN, SpreadsheetUtil.GAP_WIDTH); } // sheet.setColumnGroupCollapsed(); @@ -302,69 +268,81 @@ private static void createHeader(List projectLicenseInfos, W Row thirdHeaderRow = sheet.createRow(2); // General - createCellsInRow(thirdHeaderRow, GENERAL_START_COLUMN, headerCellStyle, "Name"); + createCellsInRow(thirdHeaderRow, SpreadsheetUtil.GENERAL_START_COLUMN, headerCellStyle, "Name"); // Plugin ID - createCellsInRow(thirdHeaderRow, PLUGIN_ID_START_COLUMN, headerCellStyle, "Group ID", "Artifact ID", "Version"); + createCellsInRow( + thirdHeaderRow, + SpreadsheetUtil.PLUGIN_ID_START_COLUMN, + headerCellStyle, + "Group ID", + "Artifact ID", + "Version"); // Licenses createCellsInRow( - thirdHeaderRow, - LICENSES_START_COLUMN, - headerCellStyle, - "Name", - "URL", - "Distribution", - "Comments", - "File"); + thirdHeaderRow, + SpreadsheetUtil.LICENSES_START_COLUMN, + headerCellStyle, + "Name", + "URL", + "Distribution", + "Comments", + "File"); // Developers createCellsInRow( - thirdHeaderRow, - DEVELOPERS_START_COLUMN, - headerCellStyle, - "Id", - "Email", - "Name", - "Organization", - "Organization URL", - "URL", - "Timezone"); + thirdHeaderRow, + SpreadsheetUtil.DEVELOPERS_START_COLUMN, + headerCellStyle, + "Id", + "Email", + "Name", + "Organization", + "Organization URL", + "URL", + "Timezone"); // Miscellaneous createCellsInRow( - thirdHeaderRow, MISC_START_COLUMN, headerCellStyle, "Inception Year", "Organization", "SCM", "URL"); + thirdHeaderRow, + SpreadsheetUtil.MISC_START_COLUMN, + headerCellStyle, + "Inception Year", + "Organization", + "SCM", + "URL"); int headerLineCount = 3; if (hasExtendedInfo) { // MANIFEST.MF createCellsInRow( - thirdHeaderRow, - MANIFEST_START_COLUMN, - headerCellStyle, - "Bundle license", - "Bundle vendor", - "Implementation vendor"); + thirdHeaderRow, + SpreadsheetUtil.MANIFEST_START_COLUMN, + headerCellStyle, + "Bundle license", + "Bundle vendor", + "Implementation vendor"); // 3 InfoFile groups: Notices, Licenses and SPDX-Licenses. createInfoFileCellsInRow( - thirdHeaderRow, - headerCellStyle, - INFO_NOTICES_START_COLUMN, - INFO_LICENSES_START_COLUMN, - INFO_SPDX_START_COLUMN); + thirdHeaderRow, + headerCellStyle, + SpreadsheetUtil.INFO_NOTICES_START_COLUMN, + SpreadsheetUtil.INFO_LICENSES_START_COLUMN, + SpreadsheetUtil.INFO_SPDX_START_COLUMN); - sheet.createFreezePane(EXTENDED_INFO_END_COLUMN, headerLineCount); + sheet.createFreezePane(SpreadsheetUtil.EXTENDED_INFO_END_COLUMN, headerLineCount); } else { - sheet.createFreezePane(MAVEN_END_COLUMN, headerLineCount); + sheet.createFreezePane(SpreadsheetUtil.MAVEN_END_COLUMN, headerLineCount); } - sheet.createFreezePane(GENERAL_END_COLUMN, headerLineCount); + sheet.createFreezePane(SpreadsheetUtil.GENERAL_END_COLUMN, headerLineCount); } // TODO: Clean this method up. Too many parameters, too complicated parameters/DTO pattern. But keep it still // threadsafe. private static void writeData( - List projectLicenseInfos, - XSSFWorkbook wb, - Sheet sheet, - XSSFColor alternatingRowsColor) { + List projectLicenseInfos, + XSSFWorkbook wb, + Sheet sheet, + XSSFColor alternatingRowsColor) { final int firstRowIndex = 3; int currentRowIndex = firstRowIndex; final Map rowMap = new HashMap<>(); @@ -394,87 +372,89 @@ private static void writeData( rowMap.put(currentRowIndex, currentRow); // Plugin ID createDataCellsInRow( - currentRow, - PLUGIN_ID_START_COLUMN, - cellStyle, - projectInfo.getGroupId(), - projectInfo.getArtifactId(), - projectInfo.getVersion()); + currentRow, + SpreadsheetUtil.PLUGIN_ID_START_COLUMN, + cellStyle, + projectInfo.getGroupId(), + projectInfo.getArtifactId(), + projectInfo.getVersion()); // Licenses final CellListParameter cellListParameter = new CellListParameter(sheet, rowMap, cellStyle); - CurrentRowData currentRowData = new CurrentRowData(currentRowIndex, extraRows, hasExtendedInfo); + SpreadsheetUtil.CurrentRowData currentRowData = + new SpreadsheetUtil.CurrentRowData(currentRowIndex, extraRows, hasExtendedInfo); extraRows = addList( - cellListParameter, - currentRowData, - LICENSES_START_COLUMN, - LICENSES_COLUMNS, - projectInfo.getLicenses(), - (Row licenseRow, ProjectLicense license) -> { - Cell[] licenses = createDataCellsInRow( - licenseRow, - LICENSES_START_COLUMN, - cellStyle, - license.getName(), - license.getUrl(), - license.getDistribution(), - license.getComments(), - license.getFile()); - addHyperlinkIfExists(wb, licenses[1], hyperlinkStyle, HyperlinkType.URL); - }); + cellListParameter, + currentRowData, + SpreadsheetUtil.LICENSES_START_COLUMN, + SpreadsheetUtil.LICENSES_COLUMNS, + projectInfo.getLicenses(), + (Row licenseRow, ProjectLicense license) -> { + Cell[] licenses = createDataCellsInRow( + licenseRow, + SpreadsheetUtil.LICENSES_START_COLUMN, + cellStyle, + license.getName(), + license.getUrl(), + license.getDistribution(), + license.getComments(), + license.getFile()); + addHyperlinkIfExists(wb, licenses[1], hyperlinkStyle, HyperlinkType.URL); + }); final ExtendedInfo extendedInfo = projectInfo.getExtendedInfo(); if (extendedInfo != null) { hasExtendedInfo = true; // General - createDataCellsInRow(currentRow, GENERAL_START_COLUMN, cellStyle, extendedInfo.getName()); + createDataCellsInRow( + currentRow, SpreadsheetUtil.GENERAL_START_COLUMN, cellStyle, extendedInfo.getName()); // Developers - currentRowData = new CurrentRowData(currentRowIndex, extraRows, hasExtendedInfo); + currentRowData = new SpreadsheetUtil.CurrentRowData(currentRowIndex, extraRows, hasExtendedInfo); extraRows = addList( - cellListParameter, - currentRowData, - DEVELOPERS_START_COLUMN, - DEVELOPERS_COLUMNS, - extendedInfo.getDevelopers(), - (Row developerRow, Developer developer) -> { - Cell[] licenses = createDataCellsInRow( - developerRow, - DEVELOPERS_START_COLUMN, - cellStyle, - developer.getId(), - developer.getEmail(), - developer.getName(), - developer.getOrganization(), - developer.getOrganizationUrl(), - developer.getUrl(), - developer.getTimezone()); - addHyperlinkIfExists(wb, licenses[1], hyperlinkStyle, HyperlinkType.EMAIL); - addHyperlinkIfExists(wb, licenses[4], hyperlinkStyle, HyperlinkType.URL); - addHyperlinkIfExists(wb, licenses[5], hyperlinkStyle, HyperlinkType.URL); - }); + cellListParameter, + currentRowData, + SpreadsheetUtil.DEVELOPERS_START_COLUMN, + SpreadsheetUtil.DEVELOPERS_COLUMNS, + extendedInfo.getDevelopers(), + (Row developerRow, Developer developer) -> { + Cell[] licenses = createDataCellsInRow( + developerRow, + SpreadsheetUtil.DEVELOPERS_START_COLUMN, + cellStyle, + developer.getId(), + developer.getEmail(), + developer.getName(), + developer.getOrganization(), + developer.getOrganizationUrl(), + developer.getUrl(), + developer.getTimezone()); + addHyperlinkIfExists(wb, licenses[1], hyperlinkStyle, HyperlinkType.EMAIL); + addHyperlinkIfExists(wb, licenses[4], hyperlinkStyle, HyperlinkType.URL); + addHyperlinkIfExists(wb, licenses[5], hyperlinkStyle, HyperlinkType.URL); + }); // Miscellaneous Cell[] miscCells = createDataCellsInRow( - currentRow, - MISC_START_COLUMN, - cellStyle, - extendedInfo.getInceptionYear(), - Optional.ofNullable(extendedInfo.getOrganization()) - .map(Organization::getName) - .orElse(null), - Optional.ofNullable(extendedInfo.getScm()) - .map(Scm::getUrl) - .orElse(null), - extendedInfo.getUrl()); + currentRow, + SpreadsheetUtil.MISC_START_COLUMN, + cellStyle, + extendedInfo.getInceptionYear(), + Optional.ofNullable(extendedInfo.getOrganization()) + .map(Organization::getName) + .orElse(null), + Optional.ofNullable(extendedInfo.getScm()) + .map(Scm::getUrl) + .orElse(null), + extendedInfo.getUrl()); addHyperlinkIfExists(wb, miscCells[2], hyperlinkStyle, HyperlinkType.URL); addHyperlinkIfExists(wb, miscCells[3], hyperlinkStyle, HyperlinkType.URL); // MANIFEST.MF createDataCellsInRow( - currentRow, - MANIFEST_START_COLUMN, - cellStyle, - extendedInfo.getBundleLicense(), - extendedInfo.getBundleVendor(), - extendedInfo.getImplementationVendor()); + currentRow, + SpreadsheetUtil.MANIFEST_START_COLUMN, + cellStyle, + extendedInfo.getBundleLicense(), + extendedInfo.getBundleVendor(), + extendedInfo.getImplementationVendor()); // Info files if (!CollectionUtils.isEmpty(extendedInfo.getInfoFiles())) { @@ -498,31 +478,45 @@ private static void writeData( } }); // InfoFile notices text file - currentRowData = new CurrentRowData(currentRowIndex, extraRows, hasExtendedInfo); + currentRowData = new SpreadsheetUtil.CurrentRowData(currentRowIndex, extraRows, hasExtendedInfo); extraRows = addInfoFileList( - cellListParameter, - currentRowData, - INFO_NOTICES_START_COLUMN, - INFO_NOTICES_COLUMNS, - notices); + cellListParameter, + currentRowData, + SpreadsheetUtil.INFO_NOTICES_START_COLUMN, + SpreadsheetUtil.INFO_NOTICES_COLUMNS, + notices); // InfoFile licenses text file - currentRowData = new CurrentRowData(currentRowIndex, extraRows, hasExtendedInfo); + currentRowData = new SpreadsheetUtil.CurrentRowData(currentRowIndex, extraRows, hasExtendedInfo); extraRows = addInfoFileList( - cellListParameter, - currentRowData, - INFO_LICENSES_START_COLUMN, - INFO_LICENSES_COLUMNS, - licenses); + cellListParameter, + currentRowData, + SpreadsheetUtil.INFO_LICENSES_START_COLUMN, + SpreadsheetUtil.INFO_LICENSES_COLUMNS, + licenses); // InfoFile spdx licenses text file - currentRowData = new CurrentRowData(currentRowIndex, extraRows, hasExtendedInfo); + currentRowData = new SpreadsheetUtil.CurrentRowData(currentRowIndex, extraRows, hasExtendedInfo); extraRows = addInfoFileList( - cellListParameter, currentRowData, INFO_SPDX_START_COLUMN, INFO_SPDX_COLUMNS, spdxs); + cellListParameter, + currentRowData, + SpreadsheetUtil.INFO_SPDX_START_COLUMN, + SpreadsheetUtil.INFO_SPDX_COLUMNS, + spdxs); } else if (cellListParameter.cellStyle != null) { setStyleOnEmptyCells( - cellListParameter, currentRowData, INFO_NOTICES_START_COLUMN, INFO_NOTICES_COLUMNS); + cellListParameter, + currentRowData, + SpreadsheetUtil.INFO_NOTICES_START_COLUMN, + SpreadsheetUtil.INFO_NOTICES_COLUMNS); setStyleOnEmptyCells( - cellListParameter, currentRowData, INFO_LICENSES_START_COLUMN, INFO_LICENSES_COLUMNS); - setStyleOnEmptyCells(cellListParameter, currentRowData, INFO_SPDX_START_COLUMN, INFO_SPDX_COLUMNS); + cellListParameter, + currentRowData, + SpreadsheetUtil.INFO_LICENSES_START_COLUMN, + SpreadsheetUtil.INFO_LICENSES_COLUMNS); + setStyleOnEmptyCells( + cellListParameter, + currentRowData, + SpreadsheetUtil.INFO_SPDX_START_COLUMN, + SpreadsheetUtil.INFO_SPDX_COLUMNS); } } currentRowIndex += extraRows + 1; @@ -546,22 +540,25 @@ private static CellStyle createHyperlinkStyle(XSSFWorkbook wb, XSSFColor backgro private static void autosizeColumns(Sheet sheet, boolean hasExtendedInfo) { autosizeColumns( - sheet, - new ImmutablePair<>(GENERAL_START_COLUMN, GENERAL_END_COLUMN), - new ImmutablePair<>(PLUGIN_ID_START_COLUMN, PLUGIN_ID_END_COLUMN), - new ImmutablePair<>(LICENSES_START_COLUMN, LICENSES_END_COLUMN), - new ImmutablePair<>(DEVELOPERS_START_COLUMN, DEVELOPERS_END_COLUMN - 1), - new ImmutablePair<>(MISC_START_COLUMN + 1, MISC_END_COLUMN)); + sheet, + new ImmutablePair<>(SpreadsheetUtil.GENERAL_START_COLUMN, SpreadsheetUtil.GENERAL_END_COLUMN), + new ImmutablePair<>(SpreadsheetUtil.PLUGIN_ID_START_COLUMN, SpreadsheetUtil.PLUGIN_ID_END_COLUMN), + new ImmutablePair<>(SpreadsheetUtil.LICENSES_START_COLUMN, SpreadsheetUtil.LICENSES_END_COLUMN), + new ImmutablePair<>(SpreadsheetUtil.DEVELOPERS_START_COLUMN, SpreadsheetUtil.DEVELOPERS_END_COLUMN - 1), + new ImmutablePair<>(SpreadsheetUtil.MISC_START_COLUMN + 1, SpreadsheetUtil.MISC_END_COLUMN)); // The column header widths are most likely wider than the actual cells content. - sheet.setColumnWidth(DEVELOPERS_END_COLUMN - 1, TIMEZONE_WIDTH); - sheet.setColumnWidth(MISC_START_COLUMN, INCEPTION_YEAR_WIDTH); + sheet.setColumnWidth(SpreadsheetUtil.DEVELOPERS_END_COLUMN - 1, SpreadsheetUtil.TIMEZONE_WIDTH); + sheet.setColumnWidth(SpreadsheetUtil.MISC_START_COLUMN, SpreadsheetUtil.INCEPTION_YEAR_WIDTH); if (hasExtendedInfo) { autosizeColumns( - sheet, - new ImmutablePair<>(MANIFEST_START_COLUMN, MANIFEST_END_COLUMN), - new ImmutablePair<>(INFO_NOTICES_START_COLUMN + 2, INFO_NOTICES_END_COLUMN), - new ImmutablePair<>(INFO_LICENSES_START_COLUMN + 2, INFO_LICENSES_END_COLUMN), - new ImmutablePair<>(INFO_SPDX_START_COLUMN + 2, INFO_SPDX_END_COLUMN)); + sheet, + new ImmutablePair<>(SpreadsheetUtil.MANIFEST_START_COLUMN, SpreadsheetUtil.MANIFEST_END_COLUMN), + new ImmutablePair<>( + SpreadsheetUtil.INFO_NOTICES_START_COLUMN + 2, SpreadsheetUtil.INFO_NOTICES_END_COLUMN), + new ImmutablePair<>( + SpreadsheetUtil.INFO_LICENSES_START_COLUMN + 2, SpreadsheetUtil.INFO_LICENSES_END_COLUMN), + new ImmutablePair<>( + SpreadsheetUtil.INFO_SPDX_START_COLUMN + 2, SpreadsheetUtil.INFO_SPDX_END_COLUMN)); } } @@ -575,38 +572,38 @@ private static void autosizeColumns(Sheet sheet, Pair... range } private static int addInfoFileList( - CellListParameter cellListParameter, - CurrentRowData currentRowData, - int startColumn, - int columnsToFill, - List infoFiles) { + CellListParameter cellListParameter, + SpreadsheetUtil.CurrentRowData currentRowData, + int startColumn, + int columnsToFill, + List infoFiles) { return addList( - cellListParameter, - currentRowData, - startColumn, - columnsToFill, - infoFiles, - (Row infoFileRow, InfoFile infoFile) -> { - final String copyrightLines = Optional.ofNullable(infoFile.getExtractedCopyrightLines()) - .map(strings -> String.join(COPYRIGHT_JOIN_SEPARATOR, strings)) - .orElse(null); - createDataCellsInRow( - infoFileRow, - startColumn, - cellListParameter.getCellStyle(), - infoFile.getContent(), - copyrightLines, - infoFile.getFileName()); - }); + cellListParameter, + currentRowData, + startColumn, + columnsToFill, + infoFiles, + (Row infoFileRow, InfoFile infoFile) -> { + final String copyrightLines = Optional.ofNullable(infoFile.getExtractedCopyrightLines()) + .map(strings -> String.join(SpreadsheetUtil.COPYRIGHT_JOIN_SEPARATOR, strings)) + .orElse(null); + createDataCellsInRow( + infoFileRow, + startColumn, + cellListParameter.getCellStyle(), + infoFile.getContent(), + copyrightLines, + infoFile.getFileName()); + }); } private static int addList( - CellListParameter cellListParameter, - CurrentRowData currentRowData, - int startColumn, - int columnsToFill, - List list, - BiConsumer biConsumer) { + CellListParameter cellListParameter, + SpreadsheetUtil.CurrentRowData currentRowData, + int startColumn, + int columnsToFill, + List list, + BiConsumer biConsumer) { if (!CollectionUtils.isEmpty(list)) { for (int i = 0; i < list.size(); i++) { T type = list.get(i); @@ -618,22 +615,35 @@ private static int addList( if (cellListParameter.getCellStyle() != null) { // Style all empty left cells, in the columns left from this createAndStyleCells( - row, - cellListParameter.getCellStyle(), - new ImmutablePair<>(GENERAL_START_COLUMN, GENERAL_END_COLUMN), - new ImmutablePair<>(PLUGIN_ID_START_COLUMN, PLUGIN_ID_END_COLUMN), - new ImmutablePair<>(LICENSES_START_COLUMN, LICENSES_END_COLUMN)); + row, + cellListParameter.getCellStyle(), + new ImmutablePair<>( + SpreadsheetUtil.GENERAL_START_COLUMN, SpreadsheetUtil.GENERAL_END_COLUMN), + new ImmutablePair<>( + SpreadsheetUtil.PLUGIN_ID_START_COLUMN, SpreadsheetUtil.PLUGIN_ID_END_COLUMN), + new ImmutablePair<>( + SpreadsheetUtil.LICENSES_START_COLUMN, SpreadsheetUtil.LICENSES_END_COLUMN)); if (currentRowData.isHasExtendedInfo()) { createAndStyleCells( - row, - cellListParameter.getCellStyle(), - new ImmutablePair<>(DEVELOPERS_START_COLUMN, DEVELOPERS_END_COLUMN), - new ImmutablePair<>(MISC_START_COLUMN, MISC_END_COLUMN), - // JAR - new ImmutablePair<>(MANIFEST_START_COLUMN, MANIFEST_END_COLUMN), - new ImmutablePair<>(INFO_LICENSES_START_COLUMN, INFO_LICENSES_END_COLUMN), - new ImmutablePair<>(INFO_NOTICES_START_COLUMN, INFO_NOTICES_END_COLUMN), - new ImmutablePair<>(INFO_SPDX_START_COLUMN, INFO_SPDX_END_COLUMN)); + row, + cellListParameter.getCellStyle(), + new ImmutablePair<>( + SpreadsheetUtil.DEVELOPERS_START_COLUMN, + SpreadsheetUtil.DEVELOPERS_END_COLUMN), + new ImmutablePair<>( + SpreadsheetUtil.MISC_START_COLUMN, SpreadsheetUtil.MISC_END_COLUMN), + // JAR + new ImmutablePair<>( + SpreadsheetUtil.MANIFEST_START_COLUMN, SpreadsheetUtil.MANIFEST_END_COLUMN), + new ImmutablePair<>( + SpreadsheetUtil.INFO_LICENSES_START_COLUMN, + SpreadsheetUtil.INFO_LICENSES_END_COLUMN), + new ImmutablePair<>( + SpreadsheetUtil.INFO_NOTICES_START_COLUMN, + SpreadsheetUtil.INFO_NOTICES_END_COLUMN), + new ImmutablePair<>( + SpreadsheetUtil.INFO_SPDX_START_COLUMN, + SpreadsheetUtil.INFO_SPDX_END_COLUMN)); } } currentRowData.setExtraRows(currentRowData.getExtraRows() + 1); @@ -651,12 +661,15 @@ private static int addList( * to color concatenated blocks with the same background color. * * @param cellListParameter Passes data about sheet, row, cell style. - * @param currentRowData Passes data about the current indices for rows and columns. - * @param startColumn Column where to start setting the style. - * @param columnsToFill How many columns to set the style on, starting from 'startColumn'. + * @param currentRowData Passes data about the current indices for rows and columns. + * @param startColumn Column where to start setting the style. + * @param columnsToFill How many columns to set the style on, starting from 'startColumn'. */ private static void setStyleOnEmptyCells( - CellListParameter cellListParameter, CurrentRowData currentRowData, int startColumn, int columnsToFill) { + CellListParameter cellListParameter, + SpreadsheetUtil.CurrentRowData currentRowData, + int startColumn, + int columnsToFill) { Row row = cellListParameter.getRows().get(currentRowData.getCurrentRowIndex()); for (int i = 0; i < columnsToFill; i++) { Cell cell = row.createCell(startColumn + i, CellType.STRING); @@ -675,21 +688,48 @@ private static void createAndStyleCells(Row row, CellStyle cellStyle, Pair startColumn; CellRangeAddress mergeAddress = null; @@ -752,7 +792,7 @@ private static void createMergedCellsInRow( } private static void setBorderAroundRegion( - Sheet sheet, CellRangeAddress licensesHeaderAddress, BorderStyle borderStyle) { + Sheet sheet, CellRangeAddress licensesHeaderAddress, BorderStyle borderStyle) { RegionUtil.setBorderLeft(borderStyle, licensesHeaderAddress, sheet); RegionUtil.setBorderTop(borderStyle, licensesHeaderAddress, sheet); RegionUtil.setBorderRight(borderStyle, licensesHeaderAddress, sheet); @@ -803,35 +843,4 @@ CellStyle getCellStyle() { return cellStyle; } } - - /** - * Parameters which may change constantly. - */ - private static class CurrentRowData { - private final int currentRowIndex; - private int extraRows; - private final boolean hasExtendedInfo; - - CurrentRowData(int currentRowIndex, int extraRows, boolean hasExtendedInfo) { - this.currentRowIndex = currentRowIndex; - this.extraRows = extraRows; - this.hasExtendedInfo = hasExtendedInfo; - } - - int getCurrentRowIndex() { - return currentRowIndex; - } - - int getExtraRows() { - return extraRows; - } - - void setExtraRows(int extraRows) { - this.extraRows = extraRows; - } - - boolean isHasExtendedInfo() { - return hasExtendedInfo; - } - } } diff --git a/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/SpreadsheetUtil.java b/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/SpreadsheetUtil.java new file mode 100644 index 000000000..588120f01 --- /dev/null +++ b/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/SpreadsheetUtil.java @@ -0,0 +1,99 @@ +package org.codehaus.mojo.license.extended.spreadsheet; + +import java.awt.Color; + +/** + * Utility class to build spreadsheets. + */ +class SpreadsheetUtil { + // Columns values for Maven data, including separator gaps for data grouping. + static final int GENERAL_START_COLUMN = 0; + private static final int GENERAL_COLUMNS = 1; + static final int GENERAL_END_COLUMN = GENERAL_START_COLUMN + GENERAL_COLUMNS; + static final int PLUGIN_ID_START_COLUMN = GENERAL_END_COLUMN + 1; + private static final int PLUGIN_ID_COLUMNS = 3; + static final int PLUGIN_ID_END_COLUMN = PLUGIN_ID_START_COLUMN + PLUGIN_ID_COLUMNS; + // "Start" column are the actual start columns, they are inclusive. + // "End" columns point just one column behind the last one, it's the exclusive column index. + static final int LICENSES_START_COLUMN = PLUGIN_ID_END_COLUMN + 1; + static final int LICENSES_COLUMNS = 5; + static final int LICENSES_END_COLUMN = LICENSES_START_COLUMN + LICENSES_COLUMNS; + static final int DEVELOPERS_START_COLUMN = LICENSES_END_COLUMN + 1; + static final int DEVELOPERS_COLUMNS = 7; + static final int DEVELOPERS_END_COLUMN = DEVELOPERS_START_COLUMN + DEVELOPERS_COLUMNS; + static final int MISC_START_COLUMN = DEVELOPERS_END_COLUMN + 1; + static final int MISC_COLUMNS = 4; + private static final int MAVEN_DATA_COLUMNS = + GENERAL_COLUMNS + PLUGIN_ID_COLUMNS + LICENSES_COLUMNS + DEVELOPERS_COLUMNS + MISC_COLUMNS; + static final int MISC_END_COLUMN = MISC_START_COLUMN + MISC_COLUMNS; + private static final int MAVEN_COLUMN_GROUPING_GAPS = 4; + private static final int MAVEN_COLUMNS = MAVEN_DATA_COLUMNS + MAVEN_COLUMN_GROUPING_GAPS; + static final int MANIFEST_START_COLUMN = MAVEN_COLUMNS + 1; + static final int MAVEN_START_COLUMN = 0; + static final int MAVEN_END_COLUMN = MAVEN_START_COLUMN + MAVEN_COLUMNS; + static final int EXTENDED_INFO_START_COLUMN = MAVEN_END_COLUMN + 1; + // Columns values for JAR data, including separator gaps for data grouping. + private static final int INFO_FILES_GAPS = 2; + private static final int MANIFEST_GAPS = 1; + private static final int MANIFEST_COLUMNS = 3; + static final int MANIFEST_END_COLUMN = MANIFEST_START_COLUMN + MANIFEST_COLUMNS; + static final int INFO_NOTICES_START_COLUMN = MANIFEST_END_COLUMN + 1; + static final int INFO_NOTICES_COLUMNS = 3; + static final int INFO_NOTICES_END_COLUMN = INFO_NOTICES_START_COLUMN + INFO_NOTICES_COLUMNS; + static final int INFO_LICENSES_START_COLUMN = INFO_NOTICES_END_COLUMN + 1; + static final int INFO_LICENSES_COLUMNS = 3; + static final int INFO_LICENSES_END_COLUMN = INFO_LICENSES_START_COLUMN + INFO_LICENSES_COLUMNS; + static final int INFO_SPDX_START_COLUMN = INFO_LICENSES_END_COLUMN + 1; + static final int INFO_SPDX_COLUMNS = 3; + private static final int EXTENDED_INFO_COLUMNS = MANIFEST_COLUMNS + + INFO_NOTICES_COLUMNS + + INFO_LICENSES_COLUMNS + + INFO_SPDX_COLUMNS + + INFO_FILES_GAPS + + MANIFEST_GAPS; + static final int EXTENDED_INFO_END_COLUMN = EXTENDED_INFO_START_COLUMN + EXTENDED_INFO_COLUMNS; + static final int INFO_SPDX_END_COLUMN = INFO_SPDX_START_COLUMN + INFO_SPDX_COLUMNS; + // Width of gap columns + private static final int EXCEL_WIDTH_SCALE = 256; + static final int INCEPTION_YEAR_WIDTH = " Inception Year ".length() * EXCEL_WIDTH_SCALE; + static final int TIMEZONE_WIDTH = " Timezone ".length() * EXCEL_WIDTH_SCALE; + static final int GAP_WIDTH = 3 * EXCEL_WIDTH_SCALE; + /** + * Color must be dark enough for low contrast monitors. + *
If you get a compile error here, make sure you're using Java 8, not higher. + */ + static final java.awt.Color ALTERNATING_ROWS_COLOR = new Color(220, 220, 220); + + static final String COPYRIGHT_JOIN_SEPARATOR = "§"; + + /** + * Parameters which may change constantly. + */ + static class CurrentRowData { + private final int currentRowIndex; + private int extraRows; + private final boolean hasExtendedInfo; + + CurrentRowData(int currentRowIndex, int extraRows, boolean hasExtendedInfo) { + this.currentRowIndex = currentRowIndex; + this.extraRows = extraRows; + this.hasExtendedInfo = hasExtendedInfo; + } + + int getCurrentRowIndex() { + return currentRowIndex; + } + + int getExtraRows() { + return extraRows; + } + + void setExtraRows(int extraRows) { + this.extraRows = extraRows; + } + + boolean isHasExtendedInfo() { + return hasExtendedInfo; + } + } +} diff --git a/src/main/java/org/codehaus/mojo/license/utils/StringToList.java b/src/main/java/org/codehaus/mojo/license/utils/StringToList.java index a34ef6bee..dc6446929 100644 --- a/src/main/java/org/codehaus/mojo/license/utils/StringToList.java +++ b/src/main/java/org/codehaus/mojo/license/utils/StringToList.java @@ -37,6 +37,10 @@ * @since 1.4 */ public class StringToList { + /** + * Regular expression to split license list. + */ + public static final String LIST_OF_LICENSES_REG_EX = "\\s*\\|\\s*"; /** * List of data. @@ -53,7 +57,7 @@ public StringToList() { public StringToList(String data) throws MojoExecutionException { this(); if (!UrlRequester.isStringUrl(data)) { - for (String s : data.split("\\s*\\|\\s*")) { + for (String s : data.split(LIST_OF_LICENSES_REG_EX)) { addEntryToList(s); } } else { diff --git a/src/test/java/org/codehaus/mojo/license/download/LicenseSummaryTest.java b/src/test/java/org/codehaus/mojo/license/download/LicenseSummaryTest.java index 5e46616e5..6fb12a7be 100644 --- a/src/test/java/org/codehaus/mojo/license/download/LicenseSummaryTest.java +++ b/src/test/java/org/codehaus/mojo/license/download/LicenseSummaryTest.java @@ -21,6 +21,7 @@ import org.codehaus.mojo.license.Eol; import org.codehaus.mojo.license.extended.ExtendedInfo; import org.codehaus.mojo.license.extended.InfoFile; +import org.codehaus.mojo.license.extended.spreadsheet.CalcFileWriter; import org.codehaus.mojo.license.extended.spreadsheet.ExcelFileWriter; import org.junit.Assert; import org.junit.Test; @@ -137,6 +138,9 @@ public void testWriteReadLicenseSummary() File licensesExcelOutputFile = File.createTempFile("licExcel", ".xlsx"); ExcelFileWriter.write(licSummary, licensesExcelOutputFile); + + File licensesCalcOutputFile = File.createTempFile("licCalc", ".ods"); + CalcFileWriter.write(licSummary, licensesCalcOutputFile); } private static ExtendedInfo buildExtendedInfo(int suffix) { From f52d6e678cc362f53dc0bf8e6b7ed1a9fac3eea0 Mon Sep 17 00:00:00 2001 From: Jan Diederich Date: Sat, 28 Oct 2023 12:13:20 +0200 Subject: [PATCH 23/34] Fixed removal of Nullable / NotNull annotations from maven dependencies By removing it from source code. --- .../download/LicensedArtifactResolver.java | 5 +- .../extended/spreadsheet/CalcFileWriter.java | 15 +- .../extended/spreadsheet/ExcelFileWriter.java | 578 +++++++++--------- 3 files changed, 295 insertions(+), 303 deletions(-) diff --git a/src/main/java/org/codehaus/mojo/license/download/LicensedArtifactResolver.java b/src/main/java/org/codehaus/mojo/license/download/LicensedArtifactResolver.java index dd1c1b979..bbdf3c106 100644 --- a/src/main/java/org/codehaus/mojo/license/download/LicensedArtifactResolver.java +++ b/src/main/java/org/codehaus/mojo/license/download/LicensedArtifactResolver.java @@ -32,8 +32,6 @@ import java.util.Map; import java.util.Set; -import org.apache.maven.api.annotations.Nonnull; -import org.apache.maven.api.annotations.Nullable; import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.repository.ArtifactRepository; import org.apache.maven.execution.MavenSession; @@ -216,8 +214,7 @@ public void loadProjectDependencies( } // CHECKSTYLE_ON: MethodLength - @Nonnull - private static Map buildMergedLicenses(@Nullable List licenseMerges) { + private static Map buildMergedLicenses(List licenseMerges) { final Map mergedLicenses = new HashMap<>(); if (licenseMerges != null) { for (String licenseMerge : licenseMerges) { diff --git a/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/CalcFileWriter.java b/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/CalcFileWriter.java index 5e8a1012e..3768ae420 100644 --- a/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/CalcFileWriter.java +++ b/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/CalcFileWriter.java @@ -15,7 +15,6 @@ import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; -import org.apache.maven.api.annotations.Nullable; import org.apache.maven.model.Developer; import org.apache.maven.model.Organization; import org.apache.maven.model.Scm; @@ -617,8 +616,7 @@ private static void writeData( autosizeColumns(table, hasExtendedInfo, currentRowIndex); } - private static OdfStyle createHyperlinkStyle( - OdfSpreadsheetDocument wb, String name, @Nullable Color backgroundColor) { + private static OdfStyle createHyperlinkStyle(OdfSpreadsheetDocument wb, String name, Color backgroundColor) { OdfOfficeStyles styles = wb.getOrCreateDocumentStyles(); OdfStyle hyperlinkStyle = styles.newStyle(name, OdfStyleFamily.TableCell); @@ -800,16 +798,12 @@ public static void applyHyperlink(OdfTable table, OdfTableCell cell, String hype node.appendChild(aElement); } - private static void addHyperlinkIfExists( - OdfTable table, OdfTableCell cell, OdfStyle hyperlinkStyle) { + private static void addHyperlinkIfExists(OdfTable table, OdfTableCell cell, OdfStyle hyperlinkStyle) { addHyperlinkIfExists(table, cell, hyperlinkStyle, false); } private static void addHyperlinkIfExists( - OdfTable table, - OdfTableCell cell, - OdfStyle hyperlinkStyle, - boolean isEmail) { + OdfTable table, OdfTableCell cell, OdfStyle hyperlinkStyle, boolean isEmail) { if (!StringUtils.isEmpty(cell.getStringValue())) { try { cell.getOdfElement().setStyleName(getCellStyleName(hyperlinkStyle)); @@ -867,8 +861,7 @@ private static OdfTableCell[] createDataCellsInRow( * @param cellStyle Cell style. * @param count Number of columns to set. */ - private static void createDataCellsInRow( - OdfTableRow row, int startColumn, OdfStyle cellStyle, int count) { + private static void createDataCellsInRow(OdfTableRow row, int startColumn, OdfStyle cellStyle, int count) { for (int i = 0; i < count; i++) { OdfTableCell cell = row.getCellByIndex(startColumn + i); cell.setValueType("string"); diff --git a/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/ExcelFileWriter.java b/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/ExcelFileWriter.java index fee3059f9..8a3d04126 100644 --- a/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/ExcelFileWriter.java +++ b/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/ExcelFileWriter.java @@ -128,24 +128,24 @@ private static void createHeader(List projectLicenseInfos, W // Create Maven header cell createMergedCellsInRow( - sheet, - SpreadsheetUtil.MAVEN_START_COLUMN, - SpreadsheetUtil.MAVEN_END_COLUMN, - headerCellStyle, - mavenJarRow, - "Maven information", - 0); - - if (hasExtendedInfo) { - // Create JAR header cell - createMergedCellsInRow( sheet, - SpreadsheetUtil.EXTENDED_INFO_START_COLUMN, - SpreadsheetUtil.EXTENDED_INFO_END_COLUMN, + SpreadsheetUtil.MAVEN_START_COLUMN, + SpreadsheetUtil.MAVEN_END_COLUMN, headerCellStyle, mavenJarRow, - "JAR Content", + "Maven information", 0); + + if (hasExtendedInfo) { + // Create JAR header cell + createMergedCellsInRow( + sheet, + SpreadsheetUtil.EXTENDED_INFO_START_COLUMN, + SpreadsheetUtil.EXTENDED_INFO_END_COLUMN, + headerCellStyle, + mavenJarRow, + "JAR Content", + 0); } // Create 2nd header row @@ -153,111 +153,111 @@ private static void createHeader(List projectLicenseInfos, W // Create Maven "General" header createMergedCellsInRow( - sheet, - SpreadsheetUtil.GENERAL_START_COLUMN, - SpreadsheetUtil.GENERAL_END_COLUMN, - headerCellStyle, - secondHeaderRow, - "General", - 1); + sheet, + SpreadsheetUtil.GENERAL_START_COLUMN, + SpreadsheetUtil.GENERAL_END_COLUMN, + headerCellStyle, + secondHeaderRow, + "General", + 1); // Create Maven "Plugin ID" header createMergedCellsInRow( - sheet, - SpreadsheetUtil.PLUGIN_ID_START_COLUMN, - SpreadsheetUtil.PLUGIN_ID_END_COLUMN, - headerCellStyle, - secondHeaderRow, - "Plugin ID", - 1); + sheet, + SpreadsheetUtil.PLUGIN_ID_START_COLUMN, + SpreadsheetUtil.PLUGIN_ID_END_COLUMN, + headerCellStyle, + secondHeaderRow, + "Plugin ID", + 1); // Gap "General" <-> "Plugin ID". sheet.setColumnWidth(SpreadsheetUtil.GENERAL_END_COLUMN, SpreadsheetUtil.GAP_WIDTH); // Create Maven "Licenses" header createMergedCellsInRow( - sheet, - SpreadsheetUtil.LICENSES_START_COLUMN, - SpreadsheetUtil.LICENSES_END_COLUMN, - headerCellStyle, - secondHeaderRow, - "Licenses", - 1); + sheet, + SpreadsheetUtil.LICENSES_START_COLUMN, + SpreadsheetUtil.LICENSES_END_COLUMN, + headerCellStyle, + secondHeaderRow, + "Licenses", + 1); // Gap "Plugin ID" <-> "Licenses". sheet.setColumnWidth(SpreadsheetUtil.PLUGIN_ID_END_COLUMN, SpreadsheetUtil.GAP_WIDTH); // Create Maven "Developers" header createMergedCellsInRow( - sheet, - SpreadsheetUtil.DEVELOPERS_START_COLUMN, - SpreadsheetUtil.DEVELOPERS_END_COLUMN, - headerCellStyle, - secondHeaderRow, - "Developers", - 1); + sheet, + SpreadsheetUtil.DEVELOPERS_START_COLUMN, + SpreadsheetUtil.DEVELOPERS_END_COLUMN, + headerCellStyle, + secondHeaderRow, + "Developers", + 1); // Gap "Licenses" <-> "Developers". sheet.setColumnWidth(SpreadsheetUtil.LICENSES_END_COLUMN, SpreadsheetUtil.GAP_WIDTH); // Create Maven "Miscellaneous" header createMergedCellsInRow( - sheet, - SpreadsheetUtil.MISC_START_COLUMN, - SpreadsheetUtil.MISC_END_COLUMN, - headerCellStyle, - secondHeaderRow, - "Miscellaneous", - 1); + sheet, + SpreadsheetUtil.MISC_START_COLUMN, + SpreadsheetUtil.MISC_END_COLUMN, + headerCellStyle, + secondHeaderRow, + "Miscellaneous", + 1); // Gap "Developers" <-> "Miscellaneous". sheet.setColumnWidth(SpreadsheetUtil.DEVELOPERS_END_COLUMN, SpreadsheetUtil.GAP_WIDTH); if (hasExtendedInfo) { createMergedCellsInRow( - sheet, - SpreadsheetUtil.MANIFEST_START_COLUMN, - SpreadsheetUtil.MANIFEST_END_COLUMN, - headerCellStyle, - secondHeaderRow, - "MANIFEST.MF", - 1); + sheet, + SpreadsheetUtil.MANIFEST_START_COLUMN, + SpreadsheetUtil.MANIFEST_END_COLUMN, + headerCellStyle, + secondHeaderRow, + "MANIFEST.MF", + 1); // Gap "Miscellaneous" <-> "MANIFEST.MF". sheet.setColumnWidth(SpreadsheetUtil.DEVELOPERS_END_COLUMN, SpreadsheetUtil.GAP_WIDTH); createMergedCellsInRow( - sheet, - SpreadsheetUtil.INFO_NOTICES_START_COLUMN, - SpreadsheetUtil.INFO_NOTICES_END_COLUMN, - headerCellStyle, - secondHeaderRow, - "Notices text files", - 1); + sheet, + SpreadsheetUtil.INFO_NOTICES_START_COLUMN, + SpreadsheetUtil.INFO_NOTICES_END_COLUMN, + headerCellStyle, + secondHeaderRow, + "Notices text files", + 1); // Gap "MANIFEST.MF" <-> "Notice text files". sheet.setColumnWidth(SpreadsheetUtil.MANIFEST_END_COLUMN, SpreadsheetUtil.GAP_WIDTH); createMergedCellsInRow( - sheet, - SpreadsheetUtil.INFO_LICENSES_START_COLUMN, - SpreadsheetUtil.INFO_LICENSES_END_COLUMN, - headerCellStyle, - secondHeaderRow, - "License text files", - 1); + sheet, + SpreadsheetUtil.INFO_LICENSES_START_COLUMN, + SpreadsheetUtil.INFO_LICENSES_END_COLUMN, + headerCellStyle, + secondHeaderRow, + "License text files", + 1); // Gap "Notice text files" <-> "License text files". sheet.setColumnWidth(SpreadsheetUtil.INFO_NOTICES_END_COLUMN, SpreadsheetUtil.GAP_WIDTH); createMergedCellsInRow( - sheet, - SpreadsheetUtil.INFO_SPDX_START_COLUMN, - SpreadsheetUtil.INFO_SPDX_END_COLUMN, - headerCellStyle, - secondHeaderRow, - "SPDX license id matched", - 1); + sheet, + SpreadsheetUtil.INFO_SPDX_START_COLUMN, + SpreadsheetUtil.INFO_SPDX_END_COLUMN, + headerCellStyle, + secondHeaderRow, + "SPDX license id matched", + 1); // Gap "License text files" <-> "SPDX license matches". sheet.setColumnWidth(SpreadsheetUtil.INFO_LICENSES_END_COLUMN, SpreadsheetUtil.GAP_WIDTH); @@ -271,62 +271,62 @@ private static void createHeader(List projectLicenseInfos, W createCellsInRow(thirdHeaderRow, SpreadsheetUtil.GENERAL_START_COLUMN, headerCellStyle, "Name"); // Plugin ID createCellsInRow( - thirdHeaderRow, - SpreadsheetUtil.PLUGIN_ID_START_COLUMN, - headerCellStyle, - "Group ID", - "Artifact ID", - "Version"); + thirdHeaderRow, + SpreadsheetUtil.PLUGIN_ID_START_COLUMN, + headerCellStyle, + "Group ID", + "Artifact ID", + "Version"); // Licenses createCellsInRow( - thirdHeaderRow, - SpreadsheetUtil.LICENSES_START_COLUMN, - headerCellStyle, - "Name", - "URL", - "Distribution", - "Comments", - "File"); + thirdHeaderRow, + SpreadsheetUtil.LICENSES_START_COLUMN, + headerCellStyle, + "Name", + "URL", + "Distribution", + "Comments", + "File"); // Developers createCellsInRow( - thirdHeaderRow, - SpreadsheetUtil.DEVELOPERS_START_COLUMN, - headerCellStyle, - "Id", - "Email", - "Name", - "Organization", - "Organization URL", - "URL", - "Timezone"); + thirdHeaderRow, + SpreadsheetUtil.DEVELOPERS_START_COLUMN, + headerCellStyle, + "Id", + "Email", + "Name", + "Organization", + "Organization URL", + "URL", + "Timezone"); // Miscellaneous createCellsInRow( - thirdHeaderRow, - SpreadsheetUtil.MISC_START_COLUMN, - headerCellStyle, - "Inception Year", - "Organization", - "SCM", - "URL"); + thirdHeaderRow, + SpreadsheetUtil.MISC_START_COLUMN, + headerCellStyle, + "Inception Year", + "Organization", + "SCM", + "URL"); int headerLineCount = 3; if (hasExtendedInfo) { // MANIFEST.MF createCellsInRow( - thirdHeaderRow, - SpreadsheetUtil.MANIFEST_START_COLUMN, - headerCellStyle, - "Bundle license", - "Bundle vendor", - "Implementation vendor"); + thirdHeaderRow, + SpreadsheetUtil.MANIFEST_START_COLUMN, + headerCellStyle, + "Bundle license", + "Bundle vendor", + "Implementation vendor"); // 3 InfoFile groups: Notices, Licenses and SPDX-Licenses. createInfoFileCellsInRow( - thirdHeaderRow, - headerCellStyle, - SpreadsheetUtil.INFO_NOTICES_START_COLUMN, - SpreadsheetUtil.INFO_LICENSES_START_COLUMN, - SpreadsheetUtil.INFO_SPDX_START_COLUMN); + thirdHeaderRow, + headerCellStyle, + SpreadsheetUtil.INFO_NOTICES_START_COLUMN, + SpreadsheetUtil.INFO_LICENSES_START_COLUMN, + SpreadsheetUtil.INFO_SPDX_START_COLUMN); sheet.createFreezePane(SpreadsheetUtil.EXTENDED_INFO_END_COLUMN, headerLineCount); } else { @@ -339,10 +339,10 @@ private static void createHeader(List projectLicenseInfos, W // TODO: Clean this method up. Too many parameters, too complicated parameters/DTO pattern. But keep it still // threadsafe. private static void writeData( - List projectLicenseInfos, - XSSFWorkbook wb, - Sheet sheet, - XSSFColor alternatingRowsColor) { + List projectLicenseInfos, + XSSFWorkbook wb, + Sheet sheet, + XSSFColor alternatingRowsColor) { final int firstRowIndex = 3; int currentRowIndex = firstRowIndex; final Map rowMap = new HashMap<>(); @@ -372,89 +372,89 @@ private static void writeData( rowMap.put(currentRowIndex, currentRow); // Plugin ID createDataCellsInRow( - currentRow, - SpreadsheetUtil.PLUGIN_ID_START_COLUMN, - cellStyle, - projectInfo.getGroupId(), - projectInfo.getArtifactId(), - projectInfo.getVersion()); + currentRow, + SpreadsheetUtil.PLUGIN_ID_START_COLUMN, + cellStyle, + projectInfo.getGroupId(), + projectInfo.getArtifactId(), + projectInfo.getVersion()); // Licenses final CellListParameter cellListParameter = new CellListParameter(sheet, rowMap, cellStyle); SpreadsheetUtil.CurrentRowData currentRowData = - new SpreadsheetUtil.CurrentRowData(currentRowIndex, extraRows, hasExtendedInfo); + new SpreadsheetUtil.CurrentRowData(currentRowIndex, extraRows, hasExtendedInfo); extraRows = addList( - cellListParameter, - currentRowData, - SpreadsheetUtil.LICENSES_START_COLUMN, - SpreadsheetUtil.LICENSES_COLUMNS, - projectInfo.getLicenses(), - (Row licenseRow, ProjectLicense license) -> { - Cell[] licenses = createDataCellsInRow( - licenseRow, - SpreadsheetUtil.LICENSES_START_COLUMN, - cellStyle, - license.getName(), - license.getUrl(), - license.getDistribution(), - license.getComments(), - license.getFile()); - addHyperlinkIfExists(wb, licenses[1], hyperlinkStyle, HyperlinkType.URL); - }); + cellListParameter, + currentRowData, + SpreadsheetUtil.LICENSES_START_COLUMN, + SpreadsheetUtil.LICENSES_COLUMNS, + projectInfo.getLicenses(), + (Row licenseRow, ProjectLicense license) -> { + Cell[] licenses = createDataCellsInRow( + licenseRow, + SpreadsheetUtil.LICENSES_START_COLUMN, + cellStyle, + license.getName(), + license.getUrl(), + license.getDistribution(), + license.getComments(), + license.getFile()); + addHyperlinkIfExists(wb, licenses[1], hyperlinkStyle, HyperlinkType.URL); + }); final ExtendedInfo extendedInfo = projectInfo.getExtendedInfo(); if (extendedInfo != null) { hasExtendedInfo = true; // General createDataCellsInRow( - currentRow, SpreadsheetUtil.GENERAL_START_COLUMN, cellStyle, extendedInfo.getName()); + currentRow, SpreadsheetUtil.GENERAL_START_COLUMN, cellStyle, extendedInfo.getName()); // Developers currentRowData = new SpreadsheetUtil.CurrentRowData(currentRowIndex, extraRows, hasExtendedInfo); extraRows = addList( - cellListParameter, - currentRowData, - SpreadsheetUtil.DEVELOPERS_START_COLUMN, - SpreadsheetUtil.DEVELOPERS_COLUMNS, - extendedInfo.getDevelopers(), - (Row developerRow, Developer developer) -> { - Cell[] licenses = createDataCellsInRow( - developerRow, - SpreadsheetUtil.DEVELOPERS_START_COLUMN, - cellStyle, - developer.getId(), - developer.getEmail(), - developer.getName(), - developer.getOrganization(), - developer.getOrganizationUrl(), - developer.getUrl(), - developer.getTimezone()); - addHyperlinkIfExists(wb, licenses[1], hyperlinkStyle, HyperlinkType.EMAIL); - addHyperlinkIfExists(wb, licenses[4], hyperlinkStyle, HyperlinkType.URL); - addHyperlinkIfExists(wb, licenses[5], hyperlinkStyle, HyperlinkType.URL); - }); + cellListParameter, + currentRowData, + SpreadsheetUtil.DEVELOPERS_START_COLUMN, + SpreadsheetUtil.DEVELOPERS_COLUMNS, + extendedInfo.getDevelopers(), + (Row developerRow, Developer developer) -> { + Cell[] licenses = createDataCellsInRow( + developerRow, + SpreadsheetUtil.DEVELOPERS_START_COLUMN, + cellStyle, + developer.getId(), + developer.getEmail(), + developer.getName(), + developer.getOrganization(), + developer.getOrganizationUrl(), + developer.getUrl(), + developer.getTimezone()); + addHyperlinkIfExists(wb, licenses[1], hyperlinkStyle, HyperlinkType.EMAIL); + addHyperlinkIfExists(wb, licenses[4], hyperlinkStyle, HyperlinkType.URL); + addHyperlinkIfExists(wb, licenses[5], hyperlinkStyle, HyperlinkType.URL); + }); // Miscellaneous Cell[] miscCells = createDataCellsInRow( - currentRow, - SpreadsheetUtil.MISC_START_COLUMN, - cellStyle, - extendedInfo.getInceptionYear(), - Optional.ofNullable(extendedInfo.getOrganization()) - .map(Organization::getName) - .orElse(null), - Optional.ofNullable(extendedInfo.getScm()) - .map(Scm::getUrl) - .orElse(null), - extendedInfo.getUrl()); + currentRow, + SpreadsheetUtil.MISC_START_COLUMN, + cellStyle, + extendedInfo.getInceptionYear(), + Optional.ofNullable(extendedInfo.getOrganization()) + .map(Organization::getName) + .orElse(null), + Optional.ofNullable(extendedInfo.getScm()) + .map(Scm::getUrl) + .orElse(null), + extendedInfo.getUrl()); addHyperlinkIfExists(wb, miscCells[2], hyperlinkStyle, HyperlinkType.URL); addHyperlinkIfExists(wb, miscCells[3], hyperlinkStyle, HyperlinkType.URL); // MANIFEST.MF createDataCellsInRow( - currentRow, - SpreadsheetUtil.MANIFEST_START_COLUMN, - cellStyle, - extendedInfo.getBundleLicense(), - extendedInfo.getBundleVendor(), - extendedInfo.getImplementationVendor()); + currentRow, + SpreadsheetUtil.MANIFEST_START_COLUMN, + cellStyle, + extendedInfo.getBundleLicense(), + extendedInfo.getBundleVendor(), + extendedInfo.getImplementationVendor()); // Info files if (!CollectionUtils.isEmpty(extendedInfo.getInfoFiles())) { @@ -480,43 +480,43 @@ private static void writeData( // InfoFile notices text file currentRowData = new SpreadsheetUtil.CurrentRowData(currentRowIndex, extraRows, hasExtendedInfo); extraRows = addInfoFileList( - cellListParameter, - currentRowData, - SpreadsheetUtil.INFO_NOTICES_START_COLUMN, - SpreadsheetUtil.INFO_NOTICES_COLUMNS, - notices); + cellListParameter, + currentRowData, + SpreadsheetUtil.INFO_NOTICES_START_COLUMN, + SpreadsheetUtil.INFO_NOTICES_COLUMNS, + notices); // InfoFile licenses text file currentRowData = new SpreadsheetUtil.CurrentRowData(currentRowIndex, extraRows, hasExtendedInfo); extraRows = addInfoFileList( - cellListParameter, - currentRowData, - SpreadsheetUtil.INFO_LICENSES_START_COLUMN, - SpreadsheetUtil.INFO_LICENSES_COLUMNS, - licenses); + cellListParameter, + currentRowData, + SpreadsheetUtil.INFO_LICENSES_START_COLUMN, + SpreadsheetUtil.INFO_LICENSES_COLUMNS, + licenses); // InfoFile spdx licenses text file currentRowData = new SpreadsheetUtil.CurrentRowData(currentRowIndex, extraRows, hasExtendedInfo); extraRows = addInfoFileList( - cellListParameter, - currentRowData, - SpreadsheetUtil.INFO_SPDX_START_COLUMN, - SpreadsheetUtil.INFO_SPDX_COLUMNS, - spdxs); + cellListParameter, + currentRowData, + SpreadsheetUtil.INFO_SPDX_START_COLUMN, + SpreadsheetUtil.INFO_SPDX_COLUMNS, + spdxs); } else if (cellListParameter.cellStyle != null) { setStyleOnEmptyCells( - cellListParameter, - currentRowData, - SpreadsheetUtil.INFO_NOTICES_START_COLUMN, - SpreadsheetUtil.INFO_NOTICES_COLUMNS); + cellListParameter, + currentRowData, + SpreadsheetUtil.INFO_NOTICES_START_COLUMN, + SpreadsheetUtil.INFO_NOTICES_COLUMNS); setStyleOnEmptyCells( - cellListParameter, - currentRowData, - SpreadsheetUtil.INFO_LICENSES_START_COLUMN, - SpreadsheetUtil.INFO_LICENSES_COLUMNS); + cellListParameter, + currentRowData, + SpreadsheetUtil.INFO_LICENSES_START_COLUMN, + SpreadsheetUtil.INFO_LICENSES_COLUMNS); setStyleOnEmptyCells( - cellListParameter, - currentRowData, - SpreadsheetUtil.INFO_SPDX_START_COLUMN, - SpreadsheetUtil.INFO_SPDX_COLUMNS); + cellListParameter, + currentRowData, + SpreadsheetUtil.INFO_SPDX_START_COLUMN, + SpreadsheetUtil.INFO_SPDX_COLUMNS); } } currentRowIndex += extraRows + 1; @@ -540,25 +540,25 @@ private static CellStyle createHyperlinkStyle(XSSFWorkbook wb, XSSFColor backgro private static void autosizeColumns(Sheet sheet, boolean hasExtendedInfo) { autosizeColumns( - sheet, - new ImmutablePair<>(SpreadsheetUtil.GENERAL_START_COLUMN, SpreadsheetUtil.GENERAL_END_COLUMN), - new ImmutablePair<>(SpreadsheetUtil.PLUGIN_ID_START_COLUMN, SpreadsheetUtil.PLUGIN_ID_END_COLUMN), - new ImmutablePair<>(SpreadsheetUtil.LICENSES_START_COLUMN, SpreadsheetUtil.LICENSES_END_COLUMN), - new ImmutablePair<>(SpreadsheetUtil.DEVELOPERS_START_COLUMN, SpreadsheetUtil.DEVELOPERS_END_COLUMN - 1), - new ImmutablePair<>(SpreadsheetUtil.MISC_START_COLUMN + 1, SpreadsheetUtil.MISC_END_COLUMN)); + sheet, + new ImmutablePair<>(SpreadsheetUtil.GENERAL_START_COLUMN, SpreadsheetUtil.GENERAL_END_COLUMN), + new ImmutablePair<>(SpreadsheetUtil.PLUGIN_ID_START_COLUMN, SpreadsheetUtil.PLUGIN_ID_END_COLUMN), + new ImmutablePair<>(SpreadsheetUtil.LICENSES_START_COLUMN, SpreadsheetUtil.LICENSES_END_COLUMN), + new ImmutablePair<>(SpreadsheetUtil.DEVELOPERS_START_COLUMN, SpreadsheetUtil.DEVELOPERS_END_COLUMN - 1), + new ImmutablePair<>(SpreadsheetUtil.MISC_START_COLUMN + 1, SpreadsheetUtil.MISC_END_COLUMN)); // The column header widths are most likely wider than the actual cells content. sheet.setColumnWidth(SpreadsheetUtil.DEVELOPERS_END_COLUMN - 1, SpreadsheetUtil.TIMEZONE_WIDTH); sheet.setColumnWidth(SpreadsheetUtil.MISC_START_COLUMN, SpreadsheetUtil.INCEPTION_YEAR_WIDTH); if (hasExtendedInfo) { autosizeColumns( - sheet, - new ImmutablePair<>(SpreadsheetUtil.MANIFEST_START_COLUMN, SpreadsheetUtil.MANIFEST_END_COLUMN), - new ImmutablePair<>( - SpreadsheetUtil.INFO_NOTICES_START_COLUMN + 2, SpreadsheetUtil.INFO_NOTICES_END_COLUMN), - new ImmutablePair<>( - SpreadsheetUtil.INFO_LICENSES_START_COLUMN + 2, SpreadsheetUtil.INFO_LICENSES_END_COLUMN), - new ImmutablePair<>( - SpreadsheetUtil.INFO_SPDX_START_COLUMN + 2, SpreadsheetUtil.INFO_SPDX_END_COLUMN)); + sheet, + new ImmutablePair<>(SpreadsheetUtil.MANIFEST_START_COLUMN, SpreadsheetUtil.MANIFEST_END_COLUMN), + new ImmutablePair<>( + SpreadsheetUtil.INFO_NOTICES_START_COLUMN + 2, SpreadsheetUtil.INFO_NOTICES_END_COLUMN), + new ImmutablePair<>( + SpreadsheetUtil.INFO_LICENSES_START_COLUMN + 2, SpreadsheetUtil.INFO_LICENSES_END_COLUMN), + new ImmutablePair<>( + SpreadsheetUtil.INFO_SPDX_START_COLUMN + 2, SpreadsheetUtil.INFO_SPDX_END_COLUMN)); } } @@ -572,38 +572,38 @@ private static void autosizeColumns(Sheet sheet, Pair... range } private static int addInfoFileList( - CellListParameter cellListParameter, - SpreadsheetUtil.CurrentRowData currentRowData, - int startColumn, - int columnsToFill, - List infoFiles) { + CellListParameter cellListParameter, + SpreadsheetUtil.CurrentRowData currentRowData, + int startColumn, + int columnsToFill, + List infoFiles) { return addList( - cellListParameter, - currentRowData, - startColumn, - columnsToFill, - infoFiles, - (Row infoFileRow, InfoFile infoFile) -> { - final String copyrightLines = Optional.ofNullable(infoFile.getExtractedCopyrightLines()) - .map(strings -> String.join(SpreadsheetUtil.COPYRIGHT_JOIN_SEPARATOR, strings)) - .orElse(null); - createDataCellsInRow( - infoFileRow, - startColumn, - cellListParameter.getCellStyle(), - infoFile.getContent(), - copyrightLines, - infoFile.getFileName()); - }); + cellListParameter, + currentRowData, + startColumn, + columnsToFill, + infoFiles, + (Row infoFileRow, InfoFile infoFile) -> { + final String copyrightLines = Optional.ofNullable(infoFile.getExtractedCopyrightLines()) + .map(strings -> String.join(SpreadsheetUtil.COPYRIGHT_JOIN_SEPARATOR, strings)) + .orElse(null); + createDataCellsInRow( + infoFileRow, + startColumn, + cellListParameter.getCellStyle(), + infoFile.getContent(), + copyrightLines, + infoFile.getFileName()); + }); } private static int addList( - CellListParameter cellListParameter, - SpreadsheetUtil.CurrentRowData currentRowData, - int startColumn, - int columnsToFill, - List list, - BiConsumer biConsumer) { + CellListParameter cellListParameter, + SpreadsheetUtil.CurrentRowData currentRowData, + int startColumn, + int columnsToFill, + List list, + BiConsumer biConsumer) { if (!CollectionUtils.isEmpty(list)) { for (int i = 0; i < list.size(); i++) { T type = list.get(i); @@ -615,35 +615,35 @@ private static int addList( if (cellListParameter.getCellStyle() != null) { // Style all empty left cells, in the columns left from this createAndStyleCells( - row, - cellListParameter.getCellStyle(), - new ImmutablePair<>( - SpreadsheetUtil.GENERAL_START_COLUMN, SpreadsheetUtil.GENERAL_END_COLUMN), - new ImmutablePair<>( - SpreadsheetUtil.PLUGIN_ID_START_COLUMN, SpreadsheetUtil.PLUGIN_ID_END_COLUMN), - new ImmutablePair<>( - SpreadsheetUtil.LICENSES_START_COLUMN, SpreadsheetUtil.LICENSES_END_COLUMN)); - if (currentRowData.isHasExtendedInfo()) { - createAndStyleCells( row, cellListParameter.getCellStyle(), new ImmutablePair<>( - SpreadsheetUtil.DEVELOPERS_START_COLUMN, - SpreadsheetUtil.DEVELOPERS_END_COLUMN), - new ImmutablePair<>( - SpreadsheetUtil.MISC_START_COLUMN, SpreadsheetUtil.MISC_END_COLUMN), - // JAR - new ImmutablePair<>( - SpreadsheetUtil.MANIFEST_START_COLUMN, SpreadsheetUtil.MANIFEST_END_COLUMN), + SpreadsheetUtil.GENERAL_START_COLUMN, SpreadsheetUtil.GENERAL_END_COLUMN), new ImmutablePair<>( - SpreadsheetUtil.INFO_LICENSES_START_COLUMN, - SpreadsheetUtil.INFO_LICENSES_END_COLUMN), + SpreadsheetUtil.PLUGIN_ID_START_COLUMN, SpreadsheetUtil.PLUGIN_ID_END_COLUMN), new ImmutablePair<>( - SpreadsheetUtil.INFO_NOTICES_START_COLUMN, - SpreadsheetUtil.INFO_NOTICES_END_COLUMN), - new ImmutablePair<>( - SpreadsheetUtil.INFO_SPDX_START_COLUMN, - SpreadsheetUtil.INFO_SPDX_END_COLUMN)); + SpreadsheetUtil.LICENSES_START_COLUMN, SpreadsheetUtil.LICENSES_END_COLUMN)); + if (currentRowData.isHasExtendedInfo()) { + createAndStyleCells( + row, + cellListParameter.getCellStyle(), + new ImmutablePair<>( + SpreadsheetUtil.DEVELOPERS_START_COLUMN, + SpreadsheetUtil.DEVELOPERS_END_COLUMN), + new ImmutablePair<>( + SpreadsheetUtil.MISC_START_COLUMN, SpreadsheetUtil.MISC_END_COLUMN), + // JAR + new ImmutablePair<>( + SpreadsheetUtil.MANIFEST_START_COLUMN, SpreadsheetUtil.MANIFEST_END_COLUMN), + new ImmutablePair<>( + SpreadsheetUtil.INFO_LICENSES_START_COLUMN, + SpreadsheetUtil.INFO_LICENSES_END_COLUMN), + new ImmutablePair<>( + SpreadsheetUtil.INFO_NOTICES_START_COLUMN, + SpreadsheetUtil.INFO_NOTICES_END_COLUMN), + new ImmutablePair<>( + SpreadsheetUtil.INFO_SPDX_START_COLUMN, + SpreadsheetUtil.INFO_SPDX_END_COLUMN)); } } currentRowData.setExtraRows(currentRowData.getExtraRows() + 1); @@ -666,10 +666,10 @@ private static int addList( * @param columnsToFill How many columns to set the style on, starting from 'startColumn'. */ private static void setStyleOnEmptyCells( - CellListParameter cellListParameter, - SpreadsheetUtil.CurrentRowData currentRowData, - int startColumn, - int columnsToFill) { + CellListParameter cellListParameter, + SpreadsheetUtil.CurrentRowData currentRowData, + int startColumn, + int columnsToFill) { Row row = cellListParameter.getRows().get(currentRowData.getCurrentRowIndex()); for (int i = 0; i < columnsToFill; i++) { Cell cell = row.createCell(startColumn + i, CellType.STRING); @@ -688,7 +688,7 @@ private static void createAndStyleCells(Row row, CellStyle cellStyle, Pair startColumn; CellRangeAddress mergeAddress = null; @@ -792,7 +794,7 @@ private static void createMergedCellsInRow( } private static void setBorderAroundRegion( - Sheet sheet, CellRangeAddress licensesHeaderAddress, BorderStyle borderStyle) { + Sheet sheet, CellRangeAddress licensesHeaderAddress, BorderStyle borderStyle) { RegionUtil.setBorderLeft(borderStyle, licensesHeaderAddress, sheet); RegionUtil.setBorderTop(borderStyle, licensesHeaderAddress, sheet); RegionUtil.setBorderRight(borderStyle, licensesHeaderAddress, sheet); From 0fc2871c0b840287462b2642fa3ddfc24f6b0d1d Mon Sep 17 00:00:00 2001 From: Jan Diederich Date: Sat, 28 Oct 2023 19:40:05 +0200 Subject: [PATCH 24/34] Fixed and added error reports to Excel and Calc export --- pom.xml | 5 +- .../postbuild.groovy | 13 ++-- .../license/AbstractDownloadLicensesMojo.java | 49 +++++++++---- .../mojo/license/AbstractLicensesXmlMojo.java | 2 +- .../AggregateDownloadLicensesMojo.java | 8 +-- .../download/LicensedArtifactResolver.java | 3 +- .../extended/spreadsheet/CalcFileWriter.java | 71 ++++++++++--------- .../extended/spreadsheet/ExcelFileWriter.java | 57 +++++++++++---- .../extended/spreadsheet/SpreadsheetUtil.java | 22 ++++-- .../license/download/LicenseSummaryTest.java | 9 +++ 10 files changed, 158 insertions(+), 81 deletions(-) diff --git a/pom.xml b/pom.xml index b6158bba8..7f0220bfc 100644 --- a/pom.xml +++ b/pom.xml @@ -385,7 +385,7 @@ org.codehaus.mojo.signature - java17 + java18 1.0 @@ -594,8 +594,7 @@ one-integration-test - install - run + integration-test true diff --git a/src/it/aggregate-download-licenses-extended-spreadsheet/postbuild.groovy b/src/it/aggregate-download-licenses-extended-spreadsheet/postbuild.groovy index 86b24a7ab..446836b93 100644 --- a/src/it/aggregate-download-licenses-extended-spreadsheet/postbuild.groovy +++ b/src/it/aggregate-download-licenses-extended-spreadsheet/postbuild.groovy @@ -30,11 +30,12 @@ import org.apache.poi.ss.usermodel.Cell import org.apache.poi.ss.usermodel.CellType import org.apache.poi.ss.usermodel.Row import org.apache.poi.ss.usermodel.Sheet +import org.apache.poi.ss.usermodel.Workbook import org.apache.poi.ss.usermodel.WorkbookFactory log = Logger.getLogger("test-aggregate-download-licenses-extended-spreadsheet") -static boolean searchText(Sheet sheet, String searchText) { +static boolean searchTextInExcel(Sheet sheet, String searchText) { def log2 = Logger.getLogger("test-aggregate-download-licenses-extended-spreadsheet-search") for (Iterator rowIterator = sheet.rowIterator(); rowIterator.hasNext();) { @@ -63,12 +64,12 @@ assert excelFile.length() > 100 try (InputStream input = new FileInputStream(excelFile)) { // So it can be easily opened and inspected manually. In a modern IDE it's just a (double-)click in the log output. log.log(Level.FINE, "Excel export at: {}", excelFile.absolutePath) - workbook = WorkbookFactory.create(input) + Workbook workbook = WorkbookFactory.create(input) Sheet sheet = workbook.getSheetAt(0) - assert searchText(sheet, "Maven information") - assert searchText(sheet, "The Apache Software License, Version 2.0") - assert searchText(sheet, "The Apache Software Foundation") + assert searchTextInExcel(sheet, "Maven information") + assert searchTextInExcel(sheet, "The Apache Software License, Version 2.0") + assert searchTextInExcel(sheet, "The Apache Software Foundation") } // -------------- Calc ----------------- @@ -78,6 +79,8 @@ assert calcFile.exists() assert calcFile.length() > 100 try (OdfSpreadsheetDocument spreadsheet = OdfSpreadsheetDocument.loadDocument(calcFile)) { + // So it can be easily opened and inspected manually. In a modern IDE it's just a (double-)click in the log output. + log.log(Level.FINE, "Calc export at: {}", calcFile.absolutePath) List tableList = spreadsheet.getTableList() OdfTable table = tableList.get(0) assert table.getRowCount() >= 3 diff --git a/src/main/java/org/codehaus/mojo/license/AbstractDownloadLicensesMojo.java b/src/main/java/org/codehaus/mojo/license/AbstractDownloadLicensesMojo.java index b1fbad58b..01414bd55 100644 --- a/src/main/java/org/codehaus/mojo/license/AbstractDownloadLicensesMojo.java +++ b/src/main/java/org/codehaus/mojo/license/AbstractDownloadLicensesMojo.java @@ -254,6 +254,19 @@ public abstract class AbstractDownloadLicensesMojo extends AbstractLicensesXmlMo defaultValue = "${project.build.directory}/generated-resources/licenses-errors.xlsx") private File licensesExcelErrorFile; + /** + * A file containing dependencies whose licenses could not be downloaded for some reason. The format is similar to + * {@link #licensesCalcOutputFile} but the entries in {@link #licensesCalcErrorFile} have + * {@code } elements attached to them. Those should explain what kind of error happened during + * the processing of the given dependency. + * + * @since 2.1 + */ + @Parameter( + property = "license.licensesCalcErrorFile", + defaultValue = "${project.build.directory}/generated-resources/licenses-errors.ods") + private File licensesCalcErrorFile; + /** * A filter to exclude some scopes. * @@ -683,7 +696,7 @@ public abstract class AbstractDownloadLicensesMojo extends AbstractLicensesXmlMo /** * Write Microsoft Office Excel file (XLSX) for goal license:aggregate-download-licenses. * - * @since 2.2.1 + * @since 2.3.1 */ @Parameter(property = "license.writeExcelFile", defaultValue = "false") private boolean writeExcelFile; @@ -691,9 +704,9 @@ public abstract class AbstractDownloadLicensesMojo extends AbstractLicensesXmlMo /** * Write LibreOffice Calc file (ODS) for goal license:aggregate-download-licenses. * - * @since 2.2.1 + * @since 2.3.1 */ - @Parameter(property = "license.writeExcelFile", defaultValue = "false") + @Parameter(property = "license.writeCalcFile", defaultValue = "false") private boolean writeCalcFile; /** @@ -716,29 +729,29 @@ public abstract class AbstractDownloadLicensesMojo extends AbstractLicensesXmlMo /** * The Excel output file used if {@link #writeExcelFile} is true, - * containing a mapping between each dependency and it's license information. + * containing a mapping between each dependency and its license information. * With extended information, if available. * * @see AbstractDownloadLicensesMojo#writeExcelFile * @see AggregateDownloadLicensesMojo#extendedInfo - * @since 2.2.1 + * @since 2.3.1 */ @Parameter( - property = "licensesExcelOutputFile", + property = "license.licensesExcelOutputFile", defaultValue = "${project.build.directory}/generated-resources/licenses.xlsx") protected File licensesExcelOutputFile; /** * The Calc output file used if {@link #writeCalcFile} is true, - * containing a mapping between each dependency and it's license information. + * containing a mapping between each dependency and its license information. * With extended information, if available. * * @see AbstractDownloadLicensesMojo#writeCalcFile * @see AggregateDownloadLicensesMojo#extendedInfo - * @since 2.2.1 + * @since 2.3.1 */ @Parameter( - property = "licensesCalcOutputFile", + property = "license.licensesCalcOutputFile", defaultValue = "${project.build.directory}/generated-resources/licenses.ods") protected File licensesCalcOutputFile; @@ -874,9 +887,14 @@ public void execute() throws MojoExecutionException, MojoFailureException { } List depProjectLicensesWithErrors = filterErrors(depProjectLicenses); - writeLicenseSummaries(depProjectLicenses); + writeLicenseSummaries( + depProjectLicenses, licensesOutputFile, licensesExcelOutputFile, licensesCalcOutputFile); if (!CollectionUtils.isEmpty(depProjectLicensesWithErrors)) { - writeLicenseSummaries(depProjectLicensesWithErrors); + writeLicenseSummaries( + depProjectLicensesWithErrors, + licensesErrorsFile, + licensesExcelErrorFile, + licensesCalcErrorFile); } removeOrphanFiles(depProjectLicenses); @@ -903,14 +921,15 @@ public void execute() throws MojoExecutionException, MojoFailureException { } } - private void writeLicenseSummaries(List depProjectLicenses) + private void writeLicenseSummaries( + List depProjectLicenses, File outputFile, File excelOutputFile, File calcOutputFile) throws ParserConfigurationException, TransformerException, IOException { - writeLicenseSummary(depProjectLicenses, licensesOutputFile, writeVersions); + writeLicenseSummary(depProjectLicenses, outputFile, writeVersions); if (writeExcelFile) { - ExcelFileWriter.write(depProjectLicenses, licensesExcelOutputFile); + ExcelFileWriter.write(depProjectLicenses, excelOutputFile); } if (writeCalcFile) { - CalcFileWriter.write(depProjectLicenses, licensesCalcOutputFile); + CalcFileWriter.write(depProjectLicenses, calcOutputFile); } } diff --git a/src/main/java/org/codehaus/mojo/license/AbstractLicensesXmlMojo.java b/src/main/java/org/codehaus/mojo/license/AbstractLicensesXmlMojo.java index cd20e2de2..b77b007d4 100644 --- a/src/main/java/org/codehaus/mojo/license/AbstractLicensesXmlMojo.java +++ b/src/main/java/org/codehaus/mojo/license/AbstractLicensesXmlMojo.java @@ -53,7 +53,7 @@ public abstract class AbstractLicensesXmlMojo extends AbstractMojo { private static final Logger LOG = LoggerFactory.getLogger(AbstractLicensesXmlMojo.class); /** - * The output file containing a mapping between each dependency and it's license information. + * The output file containing a mapping between each dependency and its license information. * * @since 1.0 */ diff --git a/src/main/java/org/codehaus/mojo/license/AggregateDownloadLicensesMojo.java b/src/main/java/org/codehaus/mojo/license/AggregateDownloadLicensesMojo.java index 39b5d0792..ef1d855fa 100644 --- a/src/main/java/org/codehaus/mojo/license/AggregateDownloadLicensesMojo.java +++ b/src/main/java/org/codehaus/mojo/license/AggregateDownloadLicensesMojo.java @@ -98,12 +98,12 @@ public class AggregateDownloadLicensesMojo extends AbstractDownloadLicensesMojo private List reactorProjects; /** - * Extract and use non maven data for license, copyright and vendor information, - * including the plugins archive file content. + * Extract and use non-maven data for license, copyright and vendor information, + * including the plugins' archive file content. *

- * This means it will read infos from the JAR's MANIFEST.MF file, look for NOTICE.txt and similar files. + * This means it will read info from the JAR's MANIFEST.MF file, look for NOTICE.txt and similar files. * - * @since 2.2.1 + * @since 2.3.1 */ @Parameter(property = "license.extendedInfo", defaultValue = "false") private boolean extendedInfo; diff --git a/src/main/java/org/codehaus/mojo/license/download/LicensedArtifactResolver.java b/src/main/java/org/codehaus/mojo/license/download/LicensedArtifactResolver.java index bbdf3c106..f733ec012 100644 --- a/src/main/java/org/codehaus/mojo/license/download/LicensedArtifactResolver.java +++ b/src/main/java/org/codehaus/mojo/license/download/LicensedArtifactResolver.java @@ -83,8 +83,7 @@ public class LicensedArtifactResolver { * @param configuration the configuration * @param remoteRepositories remote repositories used to resolve dependencies * @param result Map with Key/Value = PluginID/LicensedArtifact - * @param licenseMerges - * @return the map of resolved dependencies indexed by their unique id. + * @param licenseMerges List of license names to merge. * @see MavenProjectDependenciesConfigurator */ public void loadProjectDependencies( diff --git a/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/CalcFileWriter.java b/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/CalcFileWriter.java index 3768ae420..6eba7c40d 100644 --- a/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/CalcFileWriter.java +++ b/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/CalcFileWriter.java @@ -56,7 +56,7 @@ public class CalcFileWriter { private static final String HYPERLINK_GRAY_STYLE = "hyperlinkGrayStyle"; private static final String GRAY_CELL_STYLE = "grayCellStyle"; private static final String NORMAL_CELL_STYLE = "normalCellStyle"; - public static final String TABLE_NAME = "License information"; + private static final int DOWNLOAD_COLUMN_WIDTH = 6_000; public static void write(List projectLicenseInfos, final File licensesCalcOutputFile) { if (CollectionUtils.isEmpty(projectLicenseInfos)) { @@ -69,7 +69,6 @@ public static void write(List projectLicenseInfos, final Fil final OdfTable table; if (!tableList.isEmpty()) { table = tableList.get(0); - table.setTableName(TABLE_NAME); } else { table = OdfTable.newTable(spreadsheet); } @@ -92,8 +91,8 @@ public static void write(List projectLicenseInfos, final Fil } } - private static Color convertToOdfColor(java.awt.Color color) { - return new Color(color.getRed(), color.getGreen(), color.getBlue()); + private static Color convertToOdfColor(final int[] color) { + return new Color(color[0], color[1], color[2]); } private static void createHeader( @@ -231,6 +230,9 @@ private static void createHeader( } // sheet.setColumnGroupCollapsed(); + setColumnWidth(table, getDownloadColumn(hasExtendedInfo) - 1, GAP_WIDTH); + setColumnWidth(table, getDownloadColumn(hasExtendedInfo), DOWNLOAD_COLUMN_WIDTH); + // General createCellsInRow(thirdHeaderRow, GENERAL_START_COLUMN, HEADER_CELL_STYLE, "Name"); // Plugin ID @@ -281,9 +283,9 @@ private static void createHeader( INFO_LICENSES_START_COLUMN, INFO_SPDX_START_COLUMN); - createFreezePane(spreadsheet, table, EXTENDED_INFO_END_COLUMN, headerLineCount); + createFreezePane(spreadsheet, table, getDownloadColumn(true) - 1, headerLineCount); } else { - createFreezePane(spreadsheet, table, MAVEN_END_COLUMN, headerLineCount); + createFreezePane(spreadsheet, table, getDownloadColumn(false) - 1, headerLineCount); } createFreezePane(spreadsheet, table, GENERAL_END_COLUMN, headerLineCount); @@ -293,28 +295,15 @@ private static void setColumnWidth(OdfTable table, int column, int width) { table.getColumnByIndex(column) .getOdfElement() .setProperty(OdfTableColumnProperties.ColumnWidth, (width / 100) + "mm"); - - // table.getColumnByIndex(column).getOdfElement().setProperty(OdfTableColumnProperties.ColumnWidth, - // "001.2000in"); - // table.getColumnByIndex(column).setWidth(width); } private static void createFreezePane( OdfSpreadsheetDocument spreadsheet, OdfTable table, int column, int lineCount) { - // TODO: Implement + // TODO: Find out why this perfect XML is ignored. Use FreezePane function from ODFToolkit after they add it. final OdfSettingsDom settingsDom; try { settingsDom = spreadsheet.getSettingsDom(); - - // NodeList childNodes = settingsDom.getChildNodes(); - // for (int i = 0; i < childNodes.getLength(); i++) { - // Node node = childNodes.item(i); - // System.out.println(node); - // - // System.out.println(node.getChildNodes()); - // } - // System.out.println(childNodes); } catch (Exception e) { throw new RuntimeException(e); } @@ -433,8 +422,10 @@ private static void createHeaderStyle(OdfSpreadsheetDocument spreadsheet) { headerStyle.setProperty(StyleTableCellPropertiesElement.Border, "1.0pt solid #000000"); } - // TODO: Clean this method up. Too many parameters, too complicated parameters/DTO pattern. But keep it still - // threadsafe. + /* Improvement: Clean this method up. + Reduce parameters, complicated parameters/DTO pattern. + But keep it still threadsafe. + */ private static void writeData( List projectLicenseInfos, OdfSpreadsheetDocument wb, @@ -610,6 +601,29 @@ private static void writeData( createDataCellsInRow(currentRow, DEVELOPERS_START_COLUMN, cellStyle, DEVELOPERS_COLUMNS); createDataCellsInRow(currentRow, MISC_START_COLUMN, cellStyle, MISC_COLUMNS); } + + final int downloadColumn = getDownloadColumn(hasExtendedInfo); + if (CollectionUtils.isNotEmpty(projectInfo.getDownloaderMessages())) { + currentRowData = new SpreadsheetUtil.CurrentRowData(currentRowIndex, extraRows, hasExtendedInfo); + extraRows = addList( + cellListParameter, + currentRowData, + downloadColumn, + SpreadsheetUtil.DOWNLOAD_COLUMNS, + projectInfo.getDownloaderMessages(), + (OdfTableRow licenseRow, String message) -> { + OdfTableCell[] licenses = + createDataCellsInRow(licenseRow, downloadColumn, cellStyle, message); + if (message.matches(SpreadsheetUtil.VALID_LINK)) { + addHyperlinkIfExists(table, licenses[0], hyperlinkStyle); + } + }); + } else { + // Add empty cell, so it doesn't copy the previous row cell. + OdfTableCell cell = currentRow.getCellByIndex(downloadColumn); + cell.setValueType("string"); + cell.getOdfElement().setStyleName(getCellStyleName(cellStyle)); + } currentRowIndex += extraRows + 1; } @@ -918,18 +932,7 @@ private static void createMergedCellsInRow( cell.setStringValue(cellValue); cell.getOdfElement().setStyleName(styleName); - // TODO: Add grouping correct with a hierarchy. - // if (merge) { - // TableTableColumnGroupElement groupElement = table.getOdfElement().newTableTableColumnGroupElement(); - // for (int i = startColumn; i < endColumn - 1; i++) { - // TableTableColumnElement columnElement = groupElement.newTableTableColumnElement(); - // // Add style to "columnElement"? - // } - // } - } - - private static String convertIndexToLetter(int column) { - return String.valueOf((char) ('A' + column)); + // TODO: Add grouping, with a hierarchy, after ODFToolkit offers it. } private static OdfTableCell createCellsInRow(int startColumn, int exclusiveEndColumn, OdfTableRow inRow) { diff --git a/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/ExcelFileWriter.java b/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/ExcelFileWriter.java index 8a3d04126..63ca54052 100644 --- a/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/ExcelFileWriter.java +++ b/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/ExcelFileWriter.java @@ -26,11 +26,7 @@ import java.io.IOException; import java.io.OutputStream; import java.nio.file.Files; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; +import java.util.*; import java.util.function.BiConsumer; import org.apache.commons.collections4.CollectionUtils; @@ -68,6 +64,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import static org.codehaus.mojo.license.extended.spreadsheet.SpreadsheetUtil.GAP_WIDTH; +import static org.codehaus.mojo.license.extended.spreadsheet.SpreadsheetUtil.getDownloadColumn; + /** * Writes project license infos into Excel file. */ @@ -76,7 +75,7 @@ public class ExcelFileWriter { private static final Logger LOG = LoggerFactory.getLogger(ExcelFileWriter.class); /** - * Writes list of projects into excel file. + * Writes a list of projects into Excel file. * * @param projectLicenseInfos Project license infos to write. * @param licensesExcelOutputFile Excel output file in latest format (OOXML). @@ -88,10 +87,16 @@ public static void write(List projectLicenseInfos, final Fil } final XSSFWorkbook wb = new XSSFWorkbook(); - final Sheet sheet = wb.createSheet(WorkbookUtil.createSafeSheetName("License information")); + final Sheet sheet = wb.createSheet(WorkbookUtil.createSafeSheetName(SpreadsheetUtil.TABLE_NAME)); final IndexedColorMap colorMap = wb.getStylesSource().getIndexedColors(); - final XSSFColor alternatingRowsColor = new XSSFColor(SpreadsheetUtil.ALTERNATING_ROWS_COLOR, colorMap); + final XSSFColor alternatingRowsColor = new XSSFColor( + new byte[] { + (byte) SpreadsheetUtil.ALTERNATING_ROWS_COLOR[0], + (byte) SpreadsheetUtil.ALTERNATING_ROWS_COLOR[1], + (byte) SpreadsheetUtil.ALTERNATING_ROWS_COLOR[2] + }, + colorMap); createHeader(projectLicenseInfos, wb, sheet); @@ -264,6 +269,8 @@ private static void createHeader(List projectLicenseInfos, W } // sheet.setColumnGroupCollapsed(); + sheet.setColumnWidth(getDownloadColumn(hasExtendedInfo) - 1, GAP_WIDTH); + // Create 3rd header row Row thirdHeaderRow = sheet.createRow(2); @@ -328,16 +335,18 @@ private static void createHeader(List projectLicenseInfos, W SpreadsheetUtil.INFO_LICENSES_START_COLUMN, SpreadsheetUtil.INFO_SPDX_START_COLUMN); - sheet.createFreezePane(SpreadsheetUtil.EXTENDED_INFO_END_COLUMN, headerLineCount); + sheet.createFreezePane(getDownloadColumn(true) - 1, headerLineCount); } else { - sheet.createFreezePane(SpreadsheetUtil.MAVEN_END_COLUMN, headerLineCount); + sheet.createFreezePane(getDownloadColumn(false) - 1, headerLineCount); } sheet.createFreezePane(SpreadsheetUtil.GENERAL_END_COLUMN, headerLineCount); } - // TODO: Clean this method up. Too many parameters, too complicated parameters/DTO pattern. But keep it still - // threadsafe. + /* Possible improvement: + Clean this method up. + Reduce parameters, complicated parameters/DTO pattern. + But keep it still threadsafe. */ private static void writeData( List projectLicenseInfos, XSSFWorkbook wb, @@ -519,6 +528,25 @@ private static void writeData( SpreadsheetUtil.INFO_SPDX_COLUMNS); } } + if (CollectionUtils.isNotEmpty(projectInfo.getDownloaderMessages())) { + currentRowData = new SpreadsheetUtil.CurrentRowData(currentRowIndex, extraRows, hasExtendedInfo); + + int startColumn = hasExtendedInfo + ? SpreadsheetUtil.DOWNLOAD_EXTENDED_COLUMN + : SpreadsheetUtil.DOWNLOAD_NOT_EXTENDED_COLUMN; + extraRows = addList( + cellListParameter, + currentRowData, + startColumn, + SpreadsheetUtil.DOWNLOAD_COLUMNS, + projectInfo.getDownloaderMessages(), + (Row licenseRow, String message) -> { + Cell[] licenses = createDataCellsInRow(licenseRow, startColumn, cellStyle, message); + if (message.matches(SpreadsheetUtil.VALID_LINK)) { + addHyperlinkIfExists(wb, licenses[0], hyperlinkStyle, HyperlinkType.URL); + } + }); + } currentRowIndex += extraRows + 1; } @@ -560,6 +588,11 @@ private static void autosizeColumns(Sheet sheet, boolean hasExtendedInfo) { new ImmutablePair<>( SpreadsheetUtil.INFO_SPDX_START_COLUMN + 2, SpreadsheetUtil.INFO_SPDX_END_COLUMN)); } + autosizeColumns( + sheet, + new ImmutablePair<>( + getDownloadColumn(hasExtendedInfo), + getDownloadColumn(hasExtendedInfo) + SpreadsheetUtil.DOWNLOAD_COLUMNS)); } @SafeVarargs diff --git a/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/SpreadsheetUtil.java b/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/SpreadsheetUtil.java index 588120f01..eb5832fd2 100644 --- a/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/SpreadsheetUtil.java +++ b/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/SpreadsheetUtil.java @@ -1,11 +1,12 @@ package org.codehaus.mojo.license.extended.spreadsheet; -import java.awt.Color; - /** * Utility class to build spreadsheets. */ class SpreadsheetUtil { + static final String TABLE_NAME = "License information"; + static final String VALID_LINK = "\\bhttps?://\\S+"; + // Columns values for Maven data, including separator gaps for data grouping. static final int GENERAL_START_COLUMN = 0; private static final int GENERAL_COLUMNS = 1; @@ -53,19 +54,30 @@ class SpreadsheetUtil { + MANIFEST_GAPS; static final int EXTENDED_INFO_END_COLUMN = EXTENDED_INFO_START_COLUMN + EXTENDED_INFO_COLUMNS; static final int INFO_SPDX_END_COLUMN = INFO_SPDX_START_COLUMN + INFO_SPDX_COLUMNS; + + static final int DOWNLOAD_EXTENDED_COLUMN = INFO_SPDX_END_COLUMN + 1; + static final int DOWNLOAD_NOT_EXTENDED_COLUMN = MANIFEST_END_COLUMN + 1; + static final int DOWNLOAD_COLUMNS = 1; + // Width of gap columns private static final int EXCEL_WIDTH_SCALE = 256; static final int INCEPTION_YEAR_WIDTH = " Inception Year ".length() * EXCEL_WIDTH_SCALE; static final int TIMEZONE_WIDTH = " Timezone ".length() * EXCEL_WIDTH_SCALE; static final int GAP_WIDTH = 3 * EXCEL_WIDTH_SCALE; /** - * Color must be dark enough for low contrast monitors. - *
If you get a compile error here, make sure you're using Java 8, not higher. + * Color must be dark enough for low-contrast monitors. + *
If you get a compiler error here, make sure you're using Java 8, not higher. */ - static final java.awt.Color ALTERNATING_ROWS_COLOR = new Color(220, 220, 220); + static final int[] ALTERNATING_ROWS_COLOR = new int[] {220, 220, 220}; static final String COPYRIGHT_JOIN_SEPARATOR = "§"; + static int getDownloadColumn(boolean hasExtendedInfo) { + return hasExtendedInfo + ? SpreadsheetUtil.DOWNLOAD_EXTENDED_COLUMN + : SpreadsheetUtil.DOWNLOAD_NOT_EXTENDED_COLUMN; + } + /** * Parameters which may change constantly. */ diff --git a/src/test/java/org/codehaus/mojo/license/download/LicenseSummaryTest.java b/src/test/java/org/codehaus/mojo/license/download/LicenseSummaryTest.java index 6fb12a7be..2e0c684bf 100644 --- a/src/test/java/org/codehaus/mojo/license/download/LicenseSummaryTest.java +++ b/src/test/java/org/codehaus/mojo/license/download/LicenseSummaryTest.java @@ -78,6 +78,8 @@ public void testWriteReadLicenseSummary() List licSummary = new ArrayList<>(); ProjectLicenseInfo dep1 = new ProjectLicenseInfo("org.test", "test1", "1.0", buildExtendedInfo(1)); ProjectLicenseInfo dep2 = new ProjectLicenseInfo("org.test", "test2", "2.0", buildExtendedInfo(2)); + ProjectLicenseInfo dep3 = new ProjectLicenseInfo("com.test", "test3", "3.0", buildExtendedInfo(3)); + ProjectLicenseInfo dep4 = new ProjectLicenseInfo("dk.test", "test4", "4.0", buildExtendedInfo(4)); ProjectLicense lic = new ProjectLicense(); lic.setName("lgpl"); @@ -86,9 +88,16 @@ public void testWriteReadLicenseSummary() lic.setComments("lgpl version 3.0"); dep1.addLicense(lic); dep2.addLicense(lic); + dep3.addLicense(lic); + + dep2.addDownloaderMessage("There were server problems"); + // Skip dependency 3, to test correct empty cell filling of ODS export. + dep4.addDownloaderMessage("http://google.de"); licSummary.add(dep1); licSummary.add(dep2); + licSummary.add(dep3); + licSummary.add(dep4); { File licenseSummaryFile = File.createTempFile("licSummary", "tmp"); From 335fc21c0a5ee4be9ae68e62930a366d3b863843 Mon Sep 17 00:00:00 2001 From: Jan Diederich Date: Sat, 28 Oct 2023 20:44:18 +0200 Subject: [PATCH 25/34] Fixed error in Excel and Calc files, using the wrong column with disabled extended-info --- .../license/extended/spreadsheet/CalcFileWriter.java | 2 +- .../extended/spreadsheet/ExcelFileWriter.java | 8 ++++---- .../extended/spreadsheet/SpreadsheetUtil.java | 10 +++++----- .../mojo/license/download/LicenseSummaryTest.java | 12 ++++++++---- 4 files changed, 18 insertions(+), 14 deletions(-) diff --git a/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/CalcFileWriter.java b/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/CalcFileWriter.java index 6eba7c40d..b940b609b 100644 --- a/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/CalcFileWriter.java +++ b/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/CalcFileWriter.java @@ -609,7 +609,7 @@ private static void writeData( cellListParameter, currentRowData, downloadColumn, - SpreadsheetUtil.DOWNLOAD_COLUMNS, + SpreadsheetUtil.DOWNLOAD_MESSAGE_COLUMNS, projectInfo.getDownloaderMessages(), (OdfTableRow licenseRow, String message) -> { OdfTableCell[] licenses = diff --git a/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/ExcelFileWriter.java b/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/ExcelFileWriter.java index 63ca54052..be5a6e97f 100644 --- a/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/ExcelFileWriter.java +++ b/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/ExcelFileWriter.java @@ -532,13 +532,13 @@ private static void writeData( currentRowData = new SpreadsheetUtil.CurrentRowData(currentRowIndex, extraRows, hasExtendedInfo); int startColumn = hasExtendedInfo - ? SpreadsheetUtil.DOWNLOAD_EXTENDED_COLUMN - : SpreadsheetUtil.DOWNLOAD_NOT_EXTENDED_COLUMN; + ? SpreadsheetUtil.DOWNLOAD_MESSAGE_EXTENDED_COLUMN + : SpreadsheetUtil.DOWNLOAD_MESSAGE_NOT_EXTENDED_COLUMN; extraRows = addList( cellListParameter, currentRowData, startColumn, - SpreadsheetUtil.DOWNLOAD_COLUMNS, + SpreadsheetUtil.DOWNLOAD_MESSAGE_COLUMNS, projectInfo.getDownloaderMessages(), (Row licenseRow, String message) -> { Cell[] licenses = createDataCellsInRow(licenseRow, startColumn, cellStyle, message); @@ -592,7 +592,7 @@ private static void autosizeColumns(Sheet sheet, boolean hasExtendedInfo) { sheet, new ImmutablePair<>( getDownloadColumn(hasExtendedInfo), - getDownloadColumn(hasExtendedInfo) + SpreadsheetUtil.DOWNLOAD_COLUMNS)); + getDownloadColumn(hasExtendedInfo) + SpreadsheetUtil.DOWNLOAD_MESSAGE_COLUMNS)); } @SafeVarargs diff --git a/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/SpreadsheetUtil.java b/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/SpreadsheetUtil.java index eb5832fd2..fad3da3ca 100644 --- a/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/SpreadsheetUtil.java +++ b/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/SpreadsheetUtil.java @@ -55,9 +55,9 @@ class SpreadsheetUtil { static final int EXTENDED_INFO_END_COLUMN = EXTENDED_INFO_START_COLUMN + EXTENDED_INFO_COLUMNS; static final int INFO_SPDX_END_COLUMN = INFO_SPDX_START_COLUMN + INFO_SPDX_COLUMNS; - static final int DOWNLOAD_EXTENDED_COLUMN = INFO_SPDX_END_COLUMN + 1; - static final int DOWNLOAD_NOT_EXTENDED_COLUMN = MANIFEST_END_COLUMN + 1; - static final int DOWNLOAD_COLUMNS = 1; + static final int DOWNLOAD_MESSAGE_EXTENDED_COLUMN = INFO_SPDX_END_COLUMN + 1; + static final int DOWNLOAD_MESSAGE_NOT_EXTENDED_COLUMN = MANIFEST_START_COLUMN; + static final int DOWNLOAD_MESSAGE_COLUMNS = 1; // Width of gap columns private static final int EXCEL_WIDTH_SCALE = 256; @@ -74,8 +74,8 @@ class SpreadsheetUtil { static int getDownloadColumn(boolean hasExtendedInfo) { return hasExtendedInfo - ? SpreadsheetUtil.DOWNLOAD_EXTENDED_COLUMN - : SpreadsheetUtil.DOWNLOAD_NOT_EXTENDED_COLUMN; + ? SpreadsheetUtil.DOWNLOAD_MESSAGE_EXTENDED_COLUMN + : SpreadsheetUtil.DOWNLOAD_MESSAGE_NOT_EXTENDED_COLUMN; } /** diff --git a/src/test/java/org/codehaus/mojo/license/download/LicenseSummaryTest.java b/src/test/java/org/codehaus/mojo/license/download/LicenseSummaryTest.java index 2e0c684bf..200894b66 100644 --- a/src/test/java/org/codehaus/mojo/license/download/LicenseSummaryTest.java +++ b/src/test/java/org/codehaus/mojo/license/download/LicenseSummaryTest.java @@ -76,10 +76,14 @@ public void testWriteReadLicenseSummary() throws IOException, SAXException, ParserConfigurationException, TransformerFactoryConfigurationError, TransformerException { List licSummary = new ArrayList<>(); - ProjectLicenseInfo dep1 = new ProjectLicenseInfo("org.test", "test1", "1.0", buildExtendedInfo(1)); - ProjectLicenseInfo dep2 = new ProjectLicenseInfo("org.test", "test2", "2.0", buildExtendedInfo(2)); - ProjectLicenseInfo dep3 = new ProjectLicenseInfo("com.test", "test3", "3.0", buildExtendedInfo(3)); - ProjectLicenseInfo dep4 = new ProjectLicenseInfo("dk.test", "test4", "4.0", buildExtendedInfo(4)); + ProjectLicenseInfo dep1 = new ProjectLicenseInfo("org.test", "test1", "1.0", + buildExtendedInfo(1)); + ProjectLicenseInfo dep2 = new ProjectLicenseInfo("org.test", "test2", "2.0", + buildExtendedInfo(2)); + ProjectLicenseInfo dep3 = new ProjectLicenseInfo("com.test", "test3", "3.0", + buildExtendedInfo(3)); + ProjectLicenseInfo dep4 = new ProjectLicenseInfo("dk.test", "test4", "4.0", + buildExtendedInfo(4)); ProjectLicense lic = new ProjectLicense(); lic.setName("lgpl"); From ca02c09193af5a067727ebe1210873aba2395c6f Mon Sep 17 00:00:00 2001 From: Jan Diederich Date: Sat, 28 Oct 2023 21:18:42 +0200 Subject: [PATCH 26/34] Formatting in LicenseSummaryTest fixed --- .../mojo/license/download/LicenseSummaryTest.java | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/test/java/org/codehaus/mojo/license/download/LicenseSummaryTest.java b/src/test/java/org/codehaus/mojo/license/download/LicenseSummaryTest.java index 200894b66..2e0c684bf 100644 --- a/src/test/java/org/codehaus/mojo/license/download/LicenseSummaryTest.java +++ b/src/test/java/org/codehaus/mojo/license/download/LicenseSummaryTest.java @@ -76,14 +76,10 @@ public void testWriteReadLicenseSummary() throws IOException, SAXException, ParserConfigurationException, TransformerFactoryConfigurationError, TransformerException { List licSummary = new ArrayList<>(); - ProjectLicenseInfo dep1 = new ProjectLicenseInfo("org.test", "test1", "1.0", - buildExtendedInfo(1)); - ProjectLicenseInfo dep2 = new ProjectLicenseInfo("org.test", "test2", "2.0", - buildExtendedInfo(2)); - ProjectLicenseInfo dep3 = new ProjectLicenseInfo("com.test", "test3", "3.0", - buildExtendedInfo(3)); - ProjectLicenseInfo dep4 = new ProjectLicenseInfo("dk.test", "test4", "4.0", - buildExtendedInfo(4)); + ProjectLicenseInfo dep1 = new ProjectLicenseInfo("org.test", "test1", "1.0", buildExtendedInfo(1)); + ProjectLicenseInfo dep2 = new ProjectLicenseInfo("org.test", "test2", "2.0", buildExtendedInfo(2)); + ProjectLicenseInfo dep3 = new ProjectLicenseInfo("com.test", "test3", "3.0", buildExtendedInfo(3)); + ProjectLicenseInfo dep4 = new ProjectLicenseInfo("dk.test", "test4", "4.0", buildExtendedInfo(4)); ProjectLicense lic = new ProjectLicense(); lic.setName("lgpl"); From 6736ce8d39bc0a6212e715a57b5995ef402faa66 Mon Sep 17 00:00:00 2001 From: Jan Diederich Date: Sun, 29 Oct 2023 17:07:46 +0100 Subject: [PATCH 27/34] Converting form-feed control characters to newlines Newline control characters are valid XML, form-feed control characters are invalid XML (destroying .xml and .ods files) --- .../mojo/license/download/LicenseSummaryWriter.java | 2 +- .../license/extended/spreadsheet/CalcFileWriter.java | 11 ++++++++--- .../license/extended/spreadsheet/ExcelFileWriter.java | 6 +++++- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/codehaus/mojo/license/download/LicenseSummaryWriter.java b/src/main/java/org/codehaus/mojo/license/download/LicenseSummaryWriter.java index a3cebc666..bfa361cee 100644 --- a/src/main/java/org/codehaus/mojo/license/download/LicenseSummaryWriter.java +++ b/src/main/java/org/codehaus/mojo/license/download/LicenseSummaryWriter.java @@ -298,7 +298,7 @@ private static void addCdataIfSet(Document doc, Node parentNode, String elementN * @return The properly prepared string. */ private static String prepareCdata(String property) { - return property.replace("\r\n", "\n"); + return property.replace("\r\n", "\n").replace("\f", "\n"); } private static void addPropertyIfSet( diff --git a/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/CalcFileWriter.java b/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/CalcFileWriter.java index b940b609b..21643e84d 100644 --- a/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/CalcFileWriter.java +++ b/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/CalcFileWriter.java @@ -63,6 +63,7 @@ public static void write(List projectLicenseInfos, final Fil LOG.debug("Nothing to write to excel, no project data."); return; } + LOG.debug("Write LibreOffice Calc file " + licensesCalcOutputFile); try (OdfSpreadsheetDocument spreadsheet = OdfSpreadsheetDocument.newSpreadsheetDocument()) { List tableList = spreadsheet.getTableList(); @@ -83,11 +84,12 @@ public static void write(List projectLicenseInfos, final Fil try (OutputStream fileOut = Files.newOutputStream(licensesCalcOutputFile.toPath())) { spreadsheet.save(fileOut); + LOG.debug("Written LibreOffice Calc file " + licensesCalcOutputFile); } catch (IOException e) { - LOG.error("Error on storing Calc file with license and other information", e); + LOG.error("Error on storing LibreOffice Calc file with license and other information", e); } } catch (Exception e) { - throw new RuntimeException(e); + LOG.error("Error on creating LibreOffice Calc file with license and other information", e); } } @@ -452,6 +454,8 @@ private static void writeData( for (ProjectLicenseInfo projectInfo : projectLicenseInfos) { final OdfStyle cellStyle, hyperlinkStyle; + LOG.debug("Writing " + projectInfo.getGroupId() + ":" + projectInfo.getArtifactId() + + " into LibreOffice calc file"); if (grayBackground) { cellStyle = styleGray; hyperlinkStyle = hyperlinkStyleGray; @@ -711,7 +715,8 @@ private static int addInfoFileList( infoFileRow, startColumn, cellListParameter.getCellStyle(), - infoFile.getContent(), + // This would otherwise lead to invalid XML characters in the ODS file content. + infoFile.getContent().replace("\f", "\n"), copyrightLines, infoFile.getFileName()); }); diff --git a/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/ExcelFileWriter.java b/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/ExcelFileWriter.java index be5a6e97f..aeb965835 100644 --- a/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/ExcelFileWriter.java +++ b/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/ExcelFileWriter.java @@ -85,6 +85,7 @@ public static void write(List projectLicenseInfos, final Fil LOG.debug("Nothing to write to excel, no project data."); return; } + LOG.debug("Write Microsoft Excel file " + licensesExcelOutputFile); final XSSFWorkbook wb = new XSSFWorkbook(); final Sheet sheet = wb.createSheet(WorkbookUtil.createSafeSheetName(SpreadsheetUtil.TABLE_NAME)); @@ -104,8 +105,9 @@ public static void write(List projectLicenseInfos, final Fil try (OutputStream fileOut = Files.newOutputStream(licensesExcelOutputFile.toPath())) { wb.write(fileOut); + LOG.debug("Written Microsoft Excel file " + licensesExcelOutputFile); } catch (IOException e) { - LOG.error("Error on storing Excel file with license and other information", e); + LOG.error("Error on storing Microsoft Excel file with license and other information", e); } } @@ -367,6 +369,8 @@ private static void writeData( for (ProjectLicenseInfo projectInfo : projectLicenseInfos) { final CellStyle cellStyle, hyperlinkStyle; + LOG.debug("Writing " + projectInfo.getGroupId() + ":" + projectInfo.getArtifactId() + + " into Microsoft Excel file"); if (grayBackground) { cellStyle = styleGray; hyperlinkStyle = hyperlinkStyleGray; From 85315027152568ee9b4b4a3fc72daa94beef8a26 Mon Sep 17 00:00:00 2001 From: Jan Diederich Date: Sun, 29 Oct 2023 18:03:04 +0100 Subject: [PATCH 28/34] Updated the version number examples in the README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index e7009033e..301705064 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ and `writeExcelFile`): org.codehaus.mojo license-maven-plugin - 2.2.1-SNAPSHOT + 2.3.1-SNAPSHOT true @@ -80,7 +80,7 @@ solved, install it by adding: maven-install-plugin - 3.0.0-M1 + 3.1.1 true @@ -100,10 +100,10 @@ solved, install it by adding: install-file - ${third.party.dir}/license-maven-plugin-2.1.0-SNAPSHOT.jar + ${third.party.dir}/license-maven-plugin-2.3.1-SNAPSHOT.jar org.codehaus.mojo license-maven-plugin - 2.1.0-SNAPSHOT + 2.3.1-SNAPSHOT jar From 91afb4b9008e48a1c2e18d5422b6019f7de4a707 Mon Sep 17 00:00:00 2001 From: Jan Diederich Date: Sun, 29 Oct 2023 18:07:53 +0100 Subject: [PATCH 29/34] Removed tracking README.md from git for pull-request --- README.md | 118 ------------------------------------------------------ 1 file changed, 118 deletions(-) delete mode 100644 README.md diff --git a/README.md b/README.md deleted file mode 100644 index 301705064..000000000 --- a/README.md +++ /dev/null @@ -1,118 +0,0 @@ -# license-maven-plugin - -This is the [license-maven-plugin](http://www.mojohaus.org/license-maven-plugin/). It has been forked and extended with the option -to extract more license information from the dependencies. It can also write a report to an Excel file. - -Information about the source project (the license stays of course the same): - -[![GitHub CI](https://github.com/mojohaus/license-maven-plugin/actions/workflows/maven.yml/badge.svg)](https://github.com/mojohaus/license-maven-plugin/actions/workflows/maven.yml) -[![Maven Central](https://img.shields.io/maven-central/v/org.codehaus.mojo/license-maven-plugin.svg?label=Maven%20Central)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22org.codehaus.mojo%22%20a%3A%license-maven-plugin%22) -[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/mojohaus/license-maven-plugin?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -[![The GNU Lesser General Public License, Version 3.0](https://img.shields.io/badge/license-LGPL3-blue.svg)](http://www.gnu.org/licenses/lgpl-3.0.txt) - -## Releasing - -* Make sure `gpg-agent` is running. -* Execute `mvn -B release:prepare release:perform` - -For publishing the site do the following: - -``` -cd target/checkout -mvn verify site -DperformRelease scm-publish:publish-scm -``` - -## How to configure the extended Excel report - -The projects `pom.xml` must have the lines marked with "``" to use the new options (`extendedInfo` -and `writeExcelFile`): - -```xml - - - - - org.codehaus.mojo - license-maven-plugin - 2.3.1-SNAPSHOT - - - true - - true - - true - - - - - Apache License, Version 2.0|Apache 2.0|Apache 2|Apache License 2.0|The Apache - Software License, Version 2.0|Apache - License, version 2.0|AL 2.0|ASF 2.0 - - MIT License|The MIT License|The MIT License (MIT) - GNU Lesser General Public License|GNU Lesser General Public Licence|GNU LESSER - GENERAL PUBLIC LICENSE|GNU Lesser - Public License|Lesser General Public License (LGPL) - - GNU General Lesser Public License (LGPL) version 3.0|GNU LESSER GENERAL PUBLIC - LICENSE, version 3 (LGPL-3.0) - - - The BSD License|BSD License|BSD - The BSD 3-Clause License|The New BSD License|New BSD License - -``` -Since this hasn't been published to the official Maven repository yet, you must compile it yourself and install it to -your local repository. - -If you want to include it in your project and make sure all dependencies are packed together and -solved, install it by adding: -```xml - - - - - - - - - maven-install-plugin - 3.1.1 - - true - - - ... - - - - - maven-install-plugin - false - - - install-own-maven-license-plugin - validate - - install-file - - - ${third.party.dir}/license-maven-plugin-2.3.1-SNAPSHOT.jar - org.codehaus.mojo - license-maven-plugin - 2.3.1-SNAPSHOT - jar - - - - - ... -``` -Then, to install the plugin a `mvn validate` is enough. - -After that, generate the report with `mvn license:aggregate-download-licenses`. - -Under `./target/generated-resources/licenses.xlsx` is then the generated Excel-Report with the extended information. \ No newline at end of file From 7a818ae3dfbf4ba8d867064bbb6af40652077ba0 Mon Sep 17 00:00:00 2001 From: Jan Diederich Date: Sun, 29 Oct 2023 18:11:22 +0100 Subject: [PATCH 30/34] Replaced README.md with original file --- README.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 000000000..1d3f4bddf --- /dev/null +++ b/README.md @@ -0,0 +1,20 @@ +# license-maven-plugin + +This is the [license-maven-plugin](http://www.mojohaus.org/license-maven-plugin/). + +[![GitHub CI](https://github.com/mojohaus/license-maven-plugin/actions/workflows/maven.yml/badge.svg)](https://github.com/mojohaus/license-maven-plugin/actions/workflows/maven.yml) +[![Maven Central](https://img.shields.io/maven-central/v/org.codehaus.mojo/license-maven-plugin.svg?label=Maven%20Central)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22org.codehaus.mojo%22%20a%3A%license-maven-plugin%22) +[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/mojohaus/license-maven-plugin?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +[![The GNU Lesser General Public License, Version 3.0](https://img.shields.io/badge/license-LGPL3-blue.svg)](http://www.gnu.org/licenses/lgpl-3.0.txt) + +## Releasing + +* Make sure `gpg-agent` is running. +* Execute `mvn -B release:prepare release:perform` + +For publishing the site do the following: + +``` +cd target/checkout +mvn verify site -DperformRelease scm-publish:publish-scm +``` From b2b5e07f7fff7b5e1812eb2a339f6e9b7b76e553 Mon Sep 17 00:00:00 2001 From: Jan Diederich Date: Thu, 2 Nov 2023 12:03:25 +0100 Subject: [PATCH 31/34] Removed "run-one-it" profile, use "-P run-its -Dinvoker.test=" instead. See https://maven.apache.org/plugins/maven-invoker-plugin/integration-test-mojo.html --- pom.xml | 50 -------------------------------------------------- 1 file changed, 50 deletions(-) diff --git a/pom.xml b/pom.xml index 7f0220bfc..f7bf7e46b 100644 --- a/pom.xml +++ b/pom.xml @@ -559,56 +559,6 @@ - - run-one-it - - verify - - - maven-invoker-plugin - - ${project.build.directory}/it - src/it/settings.xml - ${project.build.directory}/local-repo - - - - - org.apache.poi - poi-ooxml - 5.2.4 - - - - org.odftoolkit - odfdom-java - 0.9.0 - - - commons-io - commons-io - 2.13.0 - - - - - one-integration-test - - integration-test - - - true - - ${itName}/pom.xml - - - - - - - - - mojo-release From a00f178396b52f70405f56bc1a4c3c3e7921f0cf Mon Sep 17 00:00:00 2001 From: Jan Diederich Date: Mon, 13 Nov 2023 23:42:53 +0100 Subject: [PATCH 32/34] Code cleanups, following https://github.com/mojohaus/license-maven-plugin/pull/527#pullrequestreview-1723457212 --- .gitattributes | 5 +- .../invoker.properties | 2 +- .../license/AbstractDownloadLicensesMojo.java | 23 ++--- .../AggregateDownloadLicensesMojo.java | 2 +- .../codehaus/mojo/license/download/Cache.java | 4 +- .../license/download/LicenseDownloader.java | 23 ++--- .../download/LicenseSummaryWriter.java | 60 +++++++------ .../download/LicensedArtifactResolver.java | 5 +- .../mojo/license/extended/InfoFile.java | 8 +- .../extended/spreadsheet/CalcFileWriter.java | 85 +++++++++++++++---- .../extended/spreadsheet/ExcelFileWriter.java | 23 +++-- .../license/download/LicenseSummaryTest.java | 14 +-- 12 files changed, 158 insertions(+), 96 deletions(-) diff --git a/.gitattributes b/.gitattributes index 4db9f210e..8151bc4fa 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,3 +1,2 @@ -* text eol=lf -*.cmd text eol=crlf -*.crlf.sh text eol=crlf \ No newline at end of file +* text eol=lf +*.cmd text eol=crlf diff --git a/src/it/aggregate-download-licenses-extended-spreadsheet/invoker.properties b/src/it/aggregate-download-licenses-extended-spreadsheet/invoker.properties index f12518fee..1821befda 100644 --- a/src/it/aggregate-download-licenses-extended-spreadsheet/invoker.properties +++ b/src/it/aggregate-download-licenses-extended-spreadsheet/invoker.properties @@ -20,4 +20,4 @@ # #L% ### invoker.goals=clean license:aggregate-download-licenses -invoker.failureBehavior=fail-fast \ No newline at end of file +invoker.failureBehavior=fail-fast diff --git a/src/main/java/org/codehaus/mojo/license/AbstractDownloadLicensesMojo.java b/src/main/java/org/codehaus/mojo/license/AbstractDownloadLicensesMojo.java index 01414bd55..ca741add0 100644 --- a/src/main/java/org/codehaus/mojo/license/AbstractDownloadLicensesMojo.java +++ b/src/main/java/org/codehaus/mojo/license/AbstractDownloadLicensesMojo.java @@ -247,7 +247,7 @@ public abstract class AbstractDownloadLicensesMojo extends AbstractLicensesXmlMo * {@code } elements attached to them. Those should explain what kind of error happened during * the processing of the given dependency. * - * @since 2.1 + * @since 2.4 */ @Parameter( property = "license.licensesExcelErrorFile", @@ -260,7 +260,7 @@ public abstract class AbstractDownloadLicensesMojo extends AbstractLicensesXmlMo * {@code } elements attached to them. Those should explain what kind of error happened during * the processing of the given dependency. * - * @since 2.1 + * @since 2.4 */ @Parameter( property = "license.licensesCalcErrorFile", @@ -696,7 +696,7 @@ public abstract class AbstractDownloadLicensesMojo extends AbstractLicensesXmlMo /** * Write Microsoft Office Excel file (XLSX) for goal license:aggregate-download-licenses. * - * @since 2.3.1 + * @since 2.4 */ @Parameter(property = "license.writeExcelFile", defaultValue = "false") private boolean writeExcelFile; @@ -704,7 +704,7 @@ public abstract class AbstractDownloadLicensesMojo extends AbstractLicensesXmlMo /** * Write LibreOffice Calc file (ODS) for goal license:aggregate-download-licenses. * - * @since 2.3.1 + * @since 2.4 */ @Parameter(property = "license.writeCalcFile", defaultValue = "false") private boolean writeCalcFile; @@ -734,7 +734,7 @@ public abstract class AbstractDownloadLicensesMojo extends AbstractLicensesXmlMo * * @see AbstractDownloadLicensesMojo#writeExcelFile * @see AggregateDownloadLicensesMojo#extendedInfo - * @since 2.3.1 + * @since 2.4 */ @Parameter( property = "license.licensesExcelOutputFile", @@ -748,7 +748,7 @@ public abstract class AbstractDownloadLicensesMojo extends AbstractLicensesXmlMo * * @see AbstractDownloadLicensesMojo#writeCalcFile * @see AggregateDownloadLicensesMojo#extendedInfo - * @since 2.3.1 + * @since 2.4 */ @Parameter( property = "license.licensesCalcOutputFile", @@ -848,7 +848,7 @@ public void execute() throws MojoExecutionException, MojoFailureException { contentSanitizers(), getCharset())) { for (LicensedArtifact artifact : dependencies.values()) { - LOG.debug("Checking licenses for project " + artifact); + LOG.debug("Checking licenses for project {}", artifact); final ProjectLicenseInfo depProject = createDependencyProject(artifact); matchers.replaceMatches(depProject); @@ -948,10 +948,11 @@ private void filterCopyrightLines(List depProjectLicenses) { } List infoFiles = projectLicenseInfo.getExtendedInfo().getInfoFiles(); for (InfoFile infoFile : infoFiles) { - if (cache.hasNormalizedContent(infoFile.getNormalizedContent())) { - LOG.debug("Removed extracted copyright lines for " - + projectLicenseInfo.getExtendedInfo().getName() - + " (" + projectLicenseInfo.toGavString() + ")"); + if (cache.hasNormalizedContentChecksum(infoFile.getContentChecksum())) { + LOG.debug( + "Removed extracted copyright lines for {} ({})", + projectLicenseInfo.getExtendedInfo().getName(), + projectLicenseInfo.toGavString()); infoFile.setExtractedCopyrightLines(null); } } diff --git a/src/main/java/org/codehaus/mojo/license/AggregateDownloadLicensesMojo.java b/src/main/java/org/codehaus/mojo/license/AggregateDownloadLicensesMojo.java index ef1d855fa..68ade2d08 100644 --- a/src/main/java/org/codehaus/mojo/license/AggregateDownloadLicensesMojo.java +++ b/src/main/java/org/codehaus/mojo/license/AggregateDownloadLicensesMojo.java @@ -103,7 +103,7 @@ public class AggregateDownloadLicensesMojo extends AbstractDownloadLicensesMojo *

* This means it will read info from the JAR's MANIFEST.MF file, look for NOTICE.txt and similar files. * - * @since 2.3.1 + * @since 2.4 */ @Parameter(property = "license.extendedInfo", defaultValue = "false") private boolean extendedInfo; diff --git a/src/main/java/org/codehaus/mojo/license/download/Cache.java b/src/main/java/org/codehaus/mojo/license/download/Cache.java index 3a0880b68..793163bec 100644 --- a/src/main/java/org/codehaus/mojo/license/download/Cache.java +++ b/src/main/java/org/codehaus/mojo/license/download/Cache.java @@ -65,10 +65,10 @@ public LicenseDownloadResult get(String url) { /** * If this cache has a normalized version of a license file. * - * @param normalizedContentChecksum Normalized file content. + * @param normalizedContentChecksum Normalized file content checksum. * @return If the cache has a license file with the same normalized content. */ - public boolean hasNormalizedContent(String normalizedContentChecksum) { + public boolean hasNormalizedContentChecksum(String normalizedContentChecksum) { return normalizedContentToFile.get(normalizedContentChecksum) != null; } diff --git a/src/main/java/org/codehaus/mojo/license/download/LicenseDownloader.java b/src/main/java/org/codehaus/mojo/license/download/LicenseDownloader.java index c22893101..a714c7ed9 100644 --- a/src/main/java/org/codehaus/mojo/license/download/LicenseDownloader.java +++ b/src/main/java/org/codehaus/mojo/license/download/LicenseDownloader.java @@ -24,7 +24,6 @@ import java.io.BufferedReader; import java.io.File; -import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; @@ -32,6 +31,7 @@ import java.net.URI; import java.net.URISyntaxException; import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -44,7 +44,6 @@ import org.apache.commons.codec.binary.Hex; import org.apache.commons.codec.digest.DigestUtils; -import org.apache.commons.io.IOUtils; import org.apache.http.HttpEntity; import org.apache.http.HttpException; import org.apache.http.HttpHost; @@ -306,10 +305,7 @@ public void close() throws IOException { */ public static class LicenseDownloadResult { public static LicenseDownloadResult success(File file, String sha1, boolean preferredFileName) { - final LicenseDownloadResult licenseDownloadResult = - new LicenseDownloadResult(file, sha1, preferredFileName, null); - licenseDownloadResult.calculateFileChecksum(); - return licenseDownloadResult; + return new LicenseDownloadResult(file, sha1, preferredFileName, null); } public static LicenseDownloadResult failure(String errorMessage) { @@ -322,6 +318,7 @@ private LicenseDownloadResult(File file, String sha1, boolean preferredFileName, this.errorMessage = errorMessage; this.sha1 = sha1; this.preferredFileName = preferredFileName; + this.normalizedContentChecksum = LicenseDownloader.calculateFileChecksum(file); } private final File file; @@ -338,7 +335,7 @@ private LicenseDownloadResult(File file, String sha1, boolean preferredFileName, *
* Normalized means: Removal of all newlines - in all formats, lines trimmed, all chars converted to lowercase. */ - private String normalizedContentChecksum; + private final String normalizedContentChecksum; private final boolean preferredFileName; @@ -375,10 +372,6 @@ public LicenseDownloadResult withFile(File otherFile) { return new LicenseDownloadResult(otherFile, sha1, preferredFileName, errorMessage); } - public void calculateFileChecksum() { - normalizedContentChecksum = LicenseDownloader.calculateFileChecksum(file); - } - @Override public String toString() { return "LicenseDownloadResult{" @@ -392,9 +385,11 @@ public String toString() { } private static String calculateFileChecksum(File file) { - try (InputStream inputStream = new FileInputStream(file)) { - byte[] content = IOUtils.readFully(inputStream, (int) file.length()); - String contentString = new String(content); + if (file == null) { + return null; + } + try { + String contentString = new String(Files.readAllBytes(file.toPath()), StandardCharsets.UTF_8); return calculateStringChecksum(contentString); } catch (IOException e) { LOG.error("Error reading license file and normalizing it ", e); diff --git a/src/main/java/org/codehaus/mojo/license/download/LicenseSummaryWriter.java b/src/main/java/org/codehaus/mojo/license/download/LicenseSummaryWriter.java index bfa361cee..d5917c4ff 100644 --- a/src/main/java/org/codehaus/mojo/license/download/LicenseSummaryWriter.java +++ b/src/main/java/org/codehaus/mojo/license/download/LicenseSummaryWriter.java @@ -127,6 +127,38 @@ public static Node createDependencyNode(Document doc, ProjectLicenseInfo dep, bo depNode.appendChild(matchLicensesNode); } + addExtendedInfo(doc, dep, depNode); + + Node licensesNode = doc.createElement("licenses"); + if (CollectionUtils.isEmpty(dep.getLicenses())) { + final String comment = hasDownloaderMessages + ? " Manually add license elements here: " + : " No license information available. "; + licensesNode.appendChild(doc.createComment(comment)); + } else { + if (hasDownloaderMessages) { + licensesNode.appendChild(doc.createComment(" Manually fix the existing license nodes: ")); + } + for (ProjectLicense lic : dep.getLicenses()) { + licensesNode.appendChild(createLicenseNode(doc, lic, false)); + } + } + depNode.appendChild(licensesNode); + + if (hasDownloaderMessages) { + final Node downloaderMessagesNode = doc.createElement("downloaderMessages"); + for (String msg : messages) { + final Node downloaderMessageNode = doc.createElement("downloaderMessage"); + downloaderMessageNode.appendChild(doc.createTextNode(msg)); + downloaderMessagesNode.appendChild(downloaderMessageNode); + } + depNode.appendChild(downloaderMessagesNode); + } + + return depNode; + } + + private static void addExtendedInfo(Document doc, ProjectLicenseInfo dep, Node depNode) { if (dep.getExtendedInfo() != null) { ExtendedInfo extendedInfo = dep.getExtendedInfo(); addTextPropertyIfSet(doc, depNode, "name", extendedInfo.getName()); @@ -162,34 +194,6 @@ public static Node createDependencyNode(Document doc, ProjectLicenseInfo dep, bo Optional.ofNullable(extendedInfo.getScm()).map(Scm::getUrl).orElse(null)); addTextPropertyIfSet(doc, depNode, "url", extendedInfo.getUrl()); } - - Node licensesNode = doc.createElement("licenses"); - if (CollectionUtils.isEmpty(dep.getLicenses())) { - final String comment = hasDownloaderMessages - ? " Manually add license elements here: " - : " No license information available. "; - licensesNode.appendChild(doc.createComment(comment)); - } else { - if (hasDownloaderMessages) { - licensesNode.appendChild(doc.createComment(" Manually fix the existing license nodes: ")); - } - for (ProjectLicense lic : dep.getLicenses()) { - licensesNode.appendChild(createLicenseNode(doc, lic, false)); - } - } - depNode.appendChild(licensesNode); - - if (hasDownloaderMessages) { - final Node downloaderMessagesNode = doc.createElement("downloaderMessages"); - for (String msg : messages) { - final Node downloaderMessageNode = doc.createElement("downloaderMessage"); - downloaderMessageNode.appendChild(doc.createTextNode(msg)); - downloaderMessagesNode.appendChild(downloaderMessageNode); - } - depNode.appendChild(downloaderMessagesNode); - } - - return depNode; } /** diff --git a/src/main/java/org/codehaus/mojo/license/download/LicensedArtifactResolver.java b/src/main/java/org/codehaus/mojo/license/download/LicensedArtifactResolver.java index f733ec012..0b595dc2b 100644 --- a/src/main/java/org/codehaus/mojo/license/download/LicensedArtifactResolver.java +++ b/src/main/java/org/codehaus/mojo/license/download/LicensedArtifactResolver.java @@ -41,7 +41,10 @@ import org.apache.maven.project.ProjectBuilder; import org.apache.maven.project.ProjectBuildingException; import org.apache.maven.project.ProjectBuildingRequest; -import org.codehaus.mojo.license.api.*; +import org.codehaus.mojo.license.api.ArtifactFilters; +import org.codehaus.mojo.license.api.DefaultThirdPartyTool; +import org.codehaus.mojo.license.api.MavenProjectDependenciesConfigurator; +import org.codehaus.mojo.license.api.ResolvedProjectDependencies; import org.codehaus.mojo.license.download.LicensedArtifact.Builder; import org.codehaus.mojo.license.utils.MojoHelper; import org.codehaus.mojo.license.utils.StringToList; diff --git a/src/main/java/org/codehaus/mojo/license/extended/InfoFile.java b/src/main/java/org/codehaus/mojo/license/extended/InfoFile.java index af7e59c5e..f4ce76cf4 100644 --- a/src/main/java/org/codehaus/mojo/license/extended/InfoFile.java +++ b/src/main/java/org/codehaus/mojo/license/extended/InfoFile.java @@ -54,7 +54,7 @@ public enum Type { private Set extractedCopyrightLines = new HashSet<>(); private Type type; - private String normalizedContent; + private String contentChecksum; public String getFileName() { return fileName; @@ -70,7 +70,7 @@ public String getContent() { public void setContent(String content) { this.content = content; - this.normalizedContent = LicenseDownloader.calculateStringChecksum(content); + this.contentChecksum = LicenseDownloader.calculateStringChecksum(content); } public Set getExtractedCopyrightLines() { @@ -89,7 +89,7 @@ public void setType(Type type) { this.type = type; } - public String getNormalizedContent() { - return normalizedContent; + public String getContentChecksum() { + return contentChecksum; } } diff --git a/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/CalcFileWriter.java b/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/CalcFileWriter.java index 21643e84d..5cce59b4f 100644 --- a/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/CalcFileWriter.java +++ b/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/CalcFileWriter.java @@ -8,7 +8,11 @@ import java.io.IOException; import java.io.OutputStream; import java.nio.file.Files; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; import java.util.function.BiConsumer; import org.apache.commons.collections4.CollectionUtils; @@ -23,7 +27,11 @@ import org.codehaus.mojo.license.extended.ExtendedInfo; import org.codehaus.mojo.license.extended.InfoFile; import org.odftoolkit.odfdom.doc.OdfSpreadsheetDocument; -import org.odftoolkit.odfdom.doc.table.*; +import org.odftoolkit.odfdom.doc.table.OdfTable; +import org.odftoolkit.odfdom.doc.table.OdfTableCell; +import org.odftoolkit.odfdom.doc.table.OdfTableCellRange; +import org.odftoolkit.odfdom.doc.table.OdfTableColumn; +import org.odftoolkit.odfdom.doc.table.OdfTableRow; import org.odftoolkit.odfdom.dom.OdfContentDom; import org.odftoolkit.odfdom.dom.OdfSettingsDom; import org.odftoolkit.odfdom.dom.element.config.ConfigConfigItemElement; @@ -43,7 +51,41 @@ import org.w3c.dom.Node; import org.w3c.dom.NodeList; -import static org.codehaus.mojo.license.extended.spreadsheet.SpreadsheetUtil.*; +import static org.codehaus.mojo.license.extended.spreadsheet.SpreadsheetUtil.COPYRIGHT_JOIN_SEPARATOR; +import static org.codehaus.mojo.license.extended.spreadsheet.SpreadsheetUtil.CurrentRowData; +import static org.codehaus.mojo.license.extended.spreadsheet.SpreadsheetUtil.DEVELOPERS_COLUMNS; +import static org.codehaus.mojo.license.extended.spreadsheet.SpreadsheetUtil.DEVELOPERS_END_COLUMN; +import static org.codehaus.mojo.license.extended.spreadsheet.SpreadsheetUtil.DEVELOPERS_START_COLUMN; +import static org.codehaus.mojo.license.extended.spreadsheet.SpreadsheetUtil.EXTENDED_INFO_END_COLUMN; +import static org.codehaus.mojo.license.extended.spreadsheet.SpreadsheetUtil.EXTENDED_INFO_START_COLUMN; +import static org.codehaus.mojo.license.extended.spreadsheet.SpreadsheetUtil.GAP_WIDTH; +import static org.codehaus.mojo.license.extended.spreadsheet.SpreadsheetUtil.GENERAL_END_COLUMN; +import static org.codehaus.mojo.license.extended.spreadsheet.SpreadsheetUtil.GENERAL_START_COLUMN; +import static org.codehaus.mojo.license.extended.spreadsheet.SpreadsheetUtil.INCEPTION_YEAR_WIDTH; +import static org.codehaus.mojo.license.extended.spreadsheet.SpreadsheetUtil.INFO_LICENSES_COLUMNS; +import static org.codehaus.mojo.license.extended.spreadsheet.SpreadsheetUtil.INFO_LICENSES_END_COLUMN; +import static org.codehaus.mojo.license.extended.spreadsheet.SpreadsheetUtil.INFO_LICENSES_START_COLUMN; +import static org.codehaus.mojo.license.extended.spreadsheet.SpreadsheetUtil.INFO_NOTICES_COLUMNS; +import static org.codehaus.mojo.license.extended.spreadsheet.SpreadsheetUtil.INFO_NOTICES_END_COLUMN; +import static org.codehaus.mojo.license.extended.spreadsheet.SpreadsheetUtil.INFO_NOTICES_START_COLUMN; +import static org.codehaus.mojo.license.extended.spreadsheet.SpreadsheetUtil.INFO_SPDX_COLUMNS; +import static org.codehaus.mojo.license.extended.spreadsheet.SpreadsheetUtil.INFO_SPDX_END_COLUMN; +import static org.codehaus.mojo.license.extended.spreadsheet.SpreadsheetUtil.INFO_SPDX_START_COLUMN; +import static org.codehaus.mojo.license.extended.spreadsheet.SpreadsheetUtil.LICENSES_COLUMNS; +import static org.codehaus.mojo.license.extended.spreadsheet.SpreadsheetUtil.LICENSES_END_COLUMN; +import static org.codehaus.mojo.license.extended.spreadsheet.SpreadsheetUtil.LICENSES_START_COLUMN; +import static org.codehaus.mojo.license.extended.spreadsheet.SpreadsheetUtil.MANIFEST_END_COLUMN; +import static org.codehaus.mojo.license.extended.spreadsheet.SpreadsheetUtil.MANIFEST_START_COLUMN; +import static org.codehaus.mojo.license.extended.spreadsheet.SpreadsheetUtil.MAVEN_END_COLUMN; +import static org.codehaus.mojo.license.extended.spreadsheet.SpreadsheetUtil.MAVEN_START_COLUMN; +import static org.codehaus.mojo.license.extended.spreadsheet.SpreadsheetUtil.MISC_COLUMNS; +import static org.codehaus.mojo.license.extended.spreadsheet.SpreadsheetUtil.MISC_END_COLUMN; +import static org.codehaus.mojo.license.extended.spreadsheet.SpreadsheetUtil.MISC_START_COLUMN; +import static org.codehaus.mojo.license.extended.spreadsheet.SpreadsheetUtil.PLUGIN_ID_END_COLUMN; +import static org.codehaus.mojo.license.extended.spreadsheet.SpreadsheetUtil.PLUGIN_ID_START_COLUMN; +import static org.codehaus.mojo.license.extended.spreadsheet.SpreadsheetUtil.TABLE_NAME; +import static org.codehaus.mojo.license.extended.spreadsheet.SpreadsheetUtil.TIMEZONE_WIDTH; +import static org.codehaus.mojo.license.extended.spreadsheet.SpreadsheetUtil.getDownloadColumn; /** * Writes LibreOffices Calc ODS file. @@ -57,13 +99,17 @@ public class CalcFileWriter { private static final String GRAY_CELL_STYLE = "grayCellStyle"; private static final String NORMAL_CELL_STYLE = "normalCellStyle"; private static final int DOWNLOAD_COLUMN_WIDTH = 6_000; + private static final String VALUE_TYPE_STRING = "string"; + private static final String CONFIG_TYPE_SHORT = "short"; + + private CalcFileWriter() {} public static void write(List projectLicenseInfos, final File licensesCalcOutputFile) { if (CollectionUtils.isEmpty(projectLicenseInfos)) { LOG.debug("Nothing to write to excel, no project data."); return; } - LOG.debug("Write LibreOffice Calc file " + licensesCalcOutputFile); + LOG.debug("Write LibreOffice Calc file {}", licensesCalcOutputFile); try (OdfSpreadsheetDocument spreadsheet = OdfSpreadsheetDocument.newSpreadsheetDocument()) { List tableList = spreadsheet.getTableList(); @@ -84,7 +130,7 @@ public static void write(List projectLicenseInfos, final Fil try (OutputStream fileOut = Files.newOutputStream(licensesCalcOutputFile.toPath())) { spreadsheet.save(fileOut); - LOG.debug("Written LibreOffice Calc file " + licensesCalcOutputFile); + LOG.debug("Written LibreOffice Calc file {}", licensesCalcOutputFile); } catch (IOException e) { LOG.error("Error on storing LibreOffice Calc file with license and other information", e); } @@ -358,13 +404,13 @@ private static void createFreezePane( if (list instanceof ConfigConfigItemMapEntryElement) { ConfigConfigItemMapEntryElement entryElement = (ConfigConfigItemMapEntryElement) list; - appendConfigItemElement(entryElement, "HorizontalSplitMode", "short", "2"); - appendConfigItemElement(entryElement, "VerticalSplitMode", "short", "2"); + appendConfigItemElement(entryElement, "HorizontalSplitMode", CONFIG_TYPE_SHORT, "2"); + appendConfigItemElement(entryElement, "VerticalSplitMode", CONFIG_TYPE_SHORT, "2"); appendConfigItemElement(entryElement, "HorizontalSplitPosition", "int", "1"); appendConfigItemElement(entryElement, "VerticalSplitPosition", "int", "3"); - appendConfigItemElement(entryElement, "ActiveSplitRange", "short", "3"); + appendConfigItemElement(entryElement, "ActiveSplitRange", CONFIG_TYPE_SHORT, "3"); appendConfigItemElement(entryElement, "PositionLeft", "int", "0"); appendConfigItemElement(entryElement, "PositionRight", "int", "1"); @@ -454,8 +500,8 @@ private static void writeData( for (ProjectLicenseInfo projectInfo : projectLicenseInfos) { final OdfStyle cellStyle, hyperlinkStyle; - LOG.debug("Writing " + projectInfo.getGroupId() + ":" + projectInfo.getArtifactId() - + " into LibreOffice calc file"); + LOG.debug( + "Writing {}:{} into LibreOffice calc file", projectInfo.getGroupId(), projectInfo.getArtifactId()); if (grayBackground) { cellStyle = styleGray; hyperlinkStyle = hyperlinkStyleGray; @@ -625,7 +671,7 @@ private static void writeData( } else { // Add empty cell, so it doesn't copy the previous row cell. OdfTableCell cell = currentRow.getCellByIndex(downloadColumn); - cell.setValueType("string"); + cell.setValueType(VALUE_TYPE_STRING); cell.getOdfElement().setStyleName(getCellStyleName(cellStyle)); } currentRowIndex += extraRows + 1; @@ -681,7 +727,7 @@ private static void autosizeColumns(OdfTable sheet, int rows, Pair range : ranges) { for (int i = range.getLeft(); i < range.getRight(); i++) { OdfTableCell cell = row.getCellByIndex(i); - cell.setValueType("string"); + cell.setValueType(VALUE_TYPE_STRING); cell.getOdfElement().setStyleName(getCellStyleName(cellStyle)); } } @@ -807,7 +853,7 @@ public static void applyHyperlink(OdfTable table, OdfTableCell cell, String hype if (isEmail) { hyperlink = hyperlink.replace(" at ", "@"); if (hyperlink.contains("@") && hyperlink.matches(".*\\s[a-zA-Z]{2,3}$")) { - hyperlink = hyperlink.replaceAll(" ", "."); + hyperlink = hyperlink.replace(" ", "."); } } aElement.setXlinkHrefAttribute(isEmail ? "mailto:" + hyperlink : hyperlink); @@ -852,7 +898,7 @@ private static OdfTableCell[] createDataCellsInRow( OdfTableCell[] result = new OdfTableCell[names.length]; for (int i = 0; i < names.length; i++) { OdfTableCell cell = row.getCellByIndex(startColumn + i); - cell.setValueType("string"); + cell.setValueType(VALUE_TYPE_STRING); if (cellStyle != null) { cell.getOdfElement().setStyleName(getCellStyleName(cellStyle)); } @@ -883,7 +929,7 @@ private static OdfTableCell[] createDataCellsInRow( private static void createDataCellsInRow(OdfTableRow row, int startColumn, OdfStyle cellStyle, int count) { for (int i = 0; i < count; i++) { OdfTableCell cell = row.getCellByIndex(startColumn + i); - cell.setValueType("string"); + cell.setValueType(VALUE_TYPE_STRING); if (cellStyle != null) { cell.getOdfElement().setStyleName(getCellStyleName(cellStyle)); } @@ -911,7 +957,7 @@ private static void createInfoFileCellsInRow(OdfTableRow row, String styleName, private static void createCellsInRow(OdfTableRow row, int startColumn, String styleName, String... names) { for (int i = 0; i < names.length; i++) { OdfTableCell cell = row.getCellByIndex(startColumn + i); - cell.setValueType("string"); + cell.setValueType(VALUE_TYPE_STRING); cell.getOdfElement().setStyleName(styleName); cell.setStringValue(names[i]); } @@ -926,6 +972,9 @@ private static void createMergedCellsInRow( int rowIndex, String styleName) { OdfTableCell cell = createCellsInRow(startColumn, endColumn, row); + if (cell == null) { + return; + } final boolean merge = endColumn - 1 > startColumn; if (merge) { diff --git a/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/ExcelFileWriter.java b/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/ExcelFileWriter.java index aeb965835..eaba69c72 100644 --- a/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/ExcelFileWriter.java +++ b/src/main/java/org/codehaus/mojo/license/extended/spreadsheet/ExcelFileWriter.java @@ -26,7 +26,11 @@ import java.io.IOException; import java.io.OutputStream; import java.nio.file.Files; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; import java.util.function.BiConsumer; import org.apache.commons.collections4.CollectionUtils; @@ -55,7 +59,6 @@ import org.apache.poi.xssf.usermodel.IndexedColorMap; import org.apache.poi.xssf.usermodel.XSSFCellStyle; import org.apache.poi.xssf.usermodel.XSSFColor; -import org.apache.poi.xssf.usermodel.XSSFFont; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.codehaus.mojo.license.download.ProjectLicense; import org.codehaus.mojo.license.download.ProjectLicenseInfo; @@ -74,6 +77,8 @@ public class ExcelFileWriter { private static final BorderStyle HEADER_CELLS_BORDER_STYLE = BorderStyle.MEDIUM; private static final Logger LOG = LoggerFactory.getLogger(ExcelFileWriter.class); + private ExcelFileWriter() {} + /** * Writes a list of projects into Excel file. * @@ -85,7 +90,7 @@ public static void write(List projectLicenseInfos, final Fil LOG.debug("Nothing to write to excel, no project data."); return; } - LOG.debug("Write Microsoft Excel file " + licensesExcelOutputFile); + LOG.debug("Write Microsoft Excel file {}", licensesExcelOutputFile); final XSSFWorkbook wb = new XSSFWorkbook(); final Sheet sheet = wb.createSheet(WorkbookUtil.createSafeSheetName(SpreadsheetUtil.TABLE_NAME)); @@ -105,7 +110,7 @@ public static void write(List projectLicenseInfos, final Fil try (OutputStream fileOut = Files.newOutputStream(licensesExcelOutputFile.toPath())) { wb.write(fileOut); - LOG.debug("Written Microsoft Excel file " + licensesExcelOutputFile); + LOG.debug("Written Microsoft Excel file {}", licensesExcelOutputFile); } catch (IOException e) { LOG.error("Error on storing Microsoft Excel file with license and other information", e); } @@ -369,8 +374,7 @@ private static void writeData( for (ProjectLicenseInfo projectInfo : projectLicenseInfos) { final CellStyle cellStyle, hyperlinkStyle; - LOG.debug("Writing " + projectInfo.getGroupId() + ":" + projectInfo.getArtifactId() - + " into Microsoft Excel file"); + LOG.debug("Writing {}:{} into Microsoft Excel file", projectInfo.getGroupId(), projectInfo.getArtifactId()); if (grayBackground) { cellStyle = styleGray; hyperlinkStyle = hyperlinkStyleGray; @@ -559,7 +563,7 @@ private static void writeData( private static CellStyle createHyperlinkStyle(XSSFWorkbook wb, XSSFColor backgroundColor) { Font hyperlinkFont = wb.createFont(); - hyperlinkFont.setUnderline(XSSFFont.U_SINGLE); + hyperlinkFont.setUnderline(Font.U_SINGLE); hyperlinkFont.setColor(IndexedColors.BLUE.getIndex()); XSSFCellStyle hyperlinkStyle = wb.createCellStyle(); if (backgroundColor != null) { @@ -757,7 +761,7 @@ private static String prefixedHyperlink(HyperlinkType hyperlinkType, String link // Replace all "bla com" with "bla.com". link = link.replace(" at ", "@"); if (link.contains("@") && link.matches(".*\\s[a-zA-Z]{2,3}$")) { - modifiedLink = link.replaceAll(" ", "."); + modifiedLink = link.replace(" ", "."); } else { modifiedLink = link; } @@ -815,6 +819,9 @@ private static void createCellsInRow(Row row, int startColumn, CellStyle cellSty private static void createMergedCellsInRow( Sheet sheet, int startColumn, int endColumn, CellStyle cellStyle, Row row, String cellValue, int rowIndex) { Cell cell = createCellsInRow(startColumn, endColumn, row); + if (cell == null) { + return; + } final boolean merge = endColumn - 1 > startColumn; CellRangeAddress mergeAddress = null; if (merge) { diff --git a/src/test/java/org/codehaus/mojo/license/download/LicenseSummaryTest.java b/src/test/java/org/codehaus/mojo/license/download/LicenseSummaryTest.java index 2e0c684bf..5e46109cf 100644 --- a/src/test/java/org/codehaus/mojo/license/download/LicenseSummaryTest.java +++ b/src/test/java/org/codehaus/mojo/license/download/LicenseSummaryTest.java @@ -10,7 +10,11 @@ import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.nio.file.Files; -import java.util.*; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.DefaultArtifact; @@ -145,11 +149,11 @@ public void testWriteReadLicenseSummary() Assert.assertEquals("lgpl version 3.0", lic0.getComments()); } - File licensesExcelOutputFile = File.createTempFile("licExcel", ".xlsx"); - ExcelFileWriter.write(licSummary, licensesExcelOutputFile); + Path licensesExcelOutputFile = Files.createTempFile("licExcel", ".xlsx"); + ExcelFileWriter.write(licSummary, licensesExcelOutputFile.toFile()); - File licensesCalcOutputFile = File.createTempFile("licCalc", ".ods"); - CalcFileWriter.write(licSummary, licensesCalcOutputFile); + Path licensesCalcOutputFile = Files.createTempFile("licCalc", ".ods"); + CalcFileWriter.write(licSummary, licensesCalcOutputFile.toFile()); } private static ExtendedInfo buildExtendedInfo(int suffix) { From fd62d4f7191d91fcd08c1f62790ebe5c7fbf4066 Mon Sep 17 00:00:00 2001 From: Jan Diederich Date: Sun, 19 Nov 2023 12:44:51 +0100 Subject: [PATCH 33/34] licenses.xsd fixes and tests for it --- .../pom.xml | 1 + .../postbuild.groovy | 9 +- .../license/AbstractDownloadLicensesMojo.java | 11 +- .../mojo/license/AbstractLicensesXmlMojo.java | 5 +- .../LicensesXmlInsertVersionsMojo.java | 11 +- .../download/LicenseSummaryWriter.java | 41 ++- .../org/codehaus/mojo/license/licenses.xsd | 331 ++++++++++++------ .../license/download/LicenseSummaryTest.java | 54 ++- 8 files changed, 345 insertions(+), 118 deletions(-) diff --git a/src/it/aggregate-download-licenses-extended-spreadsheet/pom.xml b/src/it/aggregate-download-licenses-extended-spreadsheet/pom.xml index 440e75bf5..7cdc2d7bf 100644 --- a/src/it/aggregate-download-licenses-extended-spreadsheet/pom.xml +++ b/src/it/aggregate-download-licenses-extended-spreadsheet/pom.xml @@ -56,6 +56,7 @@ true true true + true The Apache Software License, Version 2.0|Apache License, Version 2.0|Apache Public License 2.0 diff --git a/src/it/aggregate-download-licenses-extended-spreadsheet/postbuild.groovy b/src/it/aggregate-download-licenses-extended-spreadsheet/postbuild.groovy index 446836b93..07fbbc443 100644 --- a/src/it/aggregate-download-licenses-extended-spreadsheet/postbuild.groovy +++ b/src/it/aggregate-download-licenses-extended-spreadsheet/postbuild.groovy @@ -47,7 +47,7 @@ static boolean searchTextInExcel(Sheet sheet, String searchText) { if (cellValue == searchText) { return true } else { - log2.log(Level.FINEST, "Cell Value: {}", cellValue) + log2.log(Level.FINEST, "Cell Value: {0}", cellValue) } } } @@ -56,7 +56,6 @@ static boolean searchTextInExcel(Sheet sheet, String searchText) { } // -------------- Excel ---------------------- - excelFile = new File(basedir, 'target/generated-resources/licenses.xlsx') assert excelFile.exists() assert excelFile.length() > 100 @@ -84,4 +83,8 @@ try (OdfSpreadsheetDocument spreadsheet = OdfSpreadsheetDocument.loadDocument(ca List tableList = spreadsheet.getTableList() OdfTable table = tableList.get(0) assert table.getRowCount() >= 3 -} \ No newline at end of file +} + +// ----------- Check for XSD file ---------------- +licensesXsd = new File(basedir, 'target/generated-resources/licenses.xsd') +assert licensesXsd.exists() \ No newline at end of file diff --git a/src/main/java/org/codehaus/mojo/license/AbstractDownloadLicensesMojo.java b/src/main/java/org/codehaus/mojo/license/AbstractDownloadLicensesMojo.java index ca741add0..07fde3bb2 100644 --- a/src/main/java/org/codehaus/mojo/license/AbstractDownloadLicensesMojo.java +++ b/src/main/java/org/codehaus/mojo/license/AbstractDownloadLicensesMojo.java @@ -614,6 +614,15 @@ public abstract class AbstractDownloadLicensesMojo extends AbstractLicensesXmlMo @Parameter(property = "license.writeVersions", defaultValue = "true") private boolean writeVersions; + /** + * If {@code true}, a licenses.xsd file will be written in the same directory as the + * XML file, and be referenced in the XML file. + * + * @since 2.4 + */ + @Parameter(property = "license.useXsd", defaultValue = "false") + private boolean useXsd; + /** * Connect timeout in milliseconds passed to the HTTP client when downloading licenses from remote URLs. * @@ -924,7 +933,7 @@ public void execute() throws MojoExecutionException, MojoFailureException { private void writeLicenseSummaries( List depProjectLicenses, File outputFile, File excelOutputFile, File calcOutputFile) throws ParserConfigurationException, TransformerException, IOException { - writeLicenseSummary(depProjectLicenses, outputFile, writeVersions); + writeLicenseSummary(depProjectLicenses, outputFile, writeVersions, useXsd); if (writeExcelFile) { ExcelFileWriter.write(depProjectLicenses, excelOutputFile); } diff --git a/src/main/java/org/codehaus/mojo/license/AbstractLicensesXmlMojo.java b/src/main/java/org/codehaus/mojo/license/AbstractLicensesXmlMojo.java index b77b007d4..212e53894 100644 --- a/src/main/java/org/codehaus/mojo/license/AbstractLicensesXmlMojo.java +++ b/src/main/java/org/codehaus/mojo/license/AbstractLicensesXmlMojo.java @@ -157,10 +157,11 @@ protected Path[] getAutodetectEolFiles() { return new Path[] {licensesOutputFile.toPath()}; } - protected void writeLicenseSummary(List deps, File licensesOutputFile, boolean writeVersions) + protected void writeLicenseSummary( + List deps, File licensesOutputFile, boolean writeVersions, boolean useXsd) throws ParserConfigurationException, TransformerException, IOException { initEncoding(); LicenseSummaryWriter.writeLicenseSummary( - deps, licensesOutputFile, charset, licensesOutputFileEol, writeVersions); + deps, licensesOutputFile, charset, licensesOutputFileEol, writeVersions, useXsd); } } diff --git a/src/main/java/org/codehaus/mojo/license/LicensesXmlInsertVersionsMojo.java b/src/main/java/org/codehaus/mojo/license/LicensesXmlInsertVersionsMojo.java index fe1fae60d..c9490b99c 100644 --- a/src/main/java/org/codehaus/mojo/license/LicensesXmlInsertVersionsMojo.java +++ b/src/main/java/org/codehaus/mojo/license/LicensesXmlInsertVersionsMojo.java @@ -76,6 +76,15 @@ public class LicensesXmlInsertVersionsMojo extends AbstractLicensesXmlMojo { @Parameter(property = "license.skipDownloadLicenses", defaultValue = "false") private boolean skipDownloadLicenses; + /** + * If {@code true}, a licenses.xsd file will be written in the same directory as the + * XML file, and be referenced in the XML file. + * + * @since 2.4 + */ + @Parameter(property = "license.useXsd", defaultValue = "false") + private boolean useXsd; + public void execute() throws MojoExecutionException, MojoFailureException { if (skipDownloadLicenses) { @@ -152,7 +161,7 @@ public ArtifactFilters getArtifactFilters() { dependencyLicenseInfo.setVersion(dependency.getVersion()); } - writeLicenseSummary(projectLicenseInfos, licensesOutputFile, true); + writeLicenseSummary(projectLicenseInfos, licensesOutputFile, true, useXsd); } catch (MojoFailureException e) { throw e; } catch (Exception e) { diff --git a/src/main/java/org/codehaus/mojo/license/download/LicenseSummaryWriter.java b/src/main/java/org/codehaus/mojo/license/download/LicenseSummaryWriter.java index d5917c4ff..70c1fff8c 100644 --- a/src/main/java/org/codehaus/mojo/license/download/LicenseSummaryWriter.java +++ b/src/main/java/org/codehaus/mojo/license/download/LicenseSummaryWriter.java @@ -34,9 +34,13 @@ import java.io.File; import java.io.IOException; +import java.io.InputStream; import java.io.StringWriter; import java.nio.charset.Charset; import java.nio.file.Files; +import java.nio.file.NoSuchFileException; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Collection; import java.util.List; import java.util.Optional; @@ -51,7 +55,10 @@ import org.codehaus.mojo.license.Eol; import org.codehaus.mojo.license.extended.ExtendedInfo; import org.codehaus.mojo.license.extended.InfoFile; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.w3c.dom.Document; +import org.w3c.dom.Element; import org.w3c.dom.Node; /** @@ -62,14 +69,44 @@ * @since 1.0 */ public class LicenseSummaryWriter { + + private static final Logger LOG = LoggerFactory.getLogger(LicenseSummaryWriter.class); + + static final String LICENSES_XSD_FILE = "licenses.xsd"; + private static final String LICENSE_FOLDER = "/org/codehaus/mojo/license/"; + static final String LICENSE_PATH = LICENSE_FOLDER + LICENSES_XSD_FILE; + public static void writeLicenseSummary( - List dependencies, File outputFile, Charset charset, Eol eol, boolean writeVersions) + List dependencies, + File outputFile, + Charset charset, + Eol eol, + boolean writeVersions, + boolean useXsd) throws ParserConfigurationException, TransformerException, IOException { DocumentBuilderFactory fact = DocumentBuilderFactory.newInstance(); DocumentBuilder parser = fact.newDocumentBuilder(); Document doc = parser.newDocument(); - Node root = doc.createElement("licenseSummary"); + Element root = doc.createElement("licenseSummary"); + + if (useXsd) { + root.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance"); + root.setAttribute("xsi:noNamespaceSchemaLocation", LICENSES_XSD_FILE); + Path targetXsd = Paths.get(outputFile.toPath().getParent().toFile().getAbsolutePath(), LICENSES_XSD_FILE); + File targetFile = targetXsd.toFile(); + if (targetFile.exists()) { + LOG.debug("Target XSD file {} already does exist", targetXsd); + } else { + try (InputStream inputStream = LicenseSummaryWriter.class.getResourceAsStream(LICENSE_PATH)) { + if (inputStream == null) { + throw new NoSuchFileException(LICENSE_PATH); + } + Files.copy(inputStream, targetXsd); + } + } + } + doc.appendChild(root); Node dependenciesNode = doc.createElement("dependencies"); root.appendChild(dependenciesNode); diff --git a/src/main/resources/org/codehaus/mojo/license/licenses.xsd b/src/main/resources/org/codehaus/mojo/license/licenses.xsd index 6157420fa..978433e65 100644 --- a/src/main/resources/org/codehaus/mojo/license/licenses.xsd +++ b/src/main/resources/org/codehaus/mojo/license/licenses.xsd @@ -22,109 +22,234 @@ --> - - - - - - - - - - - - - - - - - - - - - - - - - - - 1.0+ - - This element describes all of the licenses for this project. Each license is described by a - license element, which is then described by additional elements. Projects should - only list the license(s) that applies to the project and not the licenses that apply to - dependencies. If multiple licenses are listed, it is assumed that the user can select - any of them, not that they must accept all. - - - - - - - - - - 3.0.0+ - - - Describes the licenses for this project. This is used to generate - the license page of the project's web site, as well as being taken into - consideration in other reporting and - validation. The licenses listed for the project are that of the project itself, - and not of dependencies. - - - - - - - 3.0.0+ - The full legal name of - the license. - - - - - 3.0.0+ - The official url for - the license text. - - - - - 3.0.0+ - - - The primary method by which this project may be distributed. -

-
repo
-
may be downloaded from the Maven repository
-
manual
-
user must manually download and install the dependency.
-
- - - - - - - 3.0.0+ - A name of the license file - (without path) downloaded from {@link #url}. This path is - relative to the licenses.xml file. - - - - - 3.0.0+ - - Addendum information pertaining to this license. - - + elementFormDefault="qualified"> + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0+ + + This element describes all of the licenses for this project. Each license is described by a + license + element, which is then described by additional elements. Projects should + only list the license(s) that applies to the project and not the licenses that apply to + dependencies. If multiple licenses are listed, it is assumed that the user can select + any of them, not that they must accept all. + + + + + + + + + + 3.0.0+ + + + Describes the licenses for this project. This is used to generate + the license page of the project's web site, as well as being taken into + consideration in other reporting and + validation. The licenses listed for the project are that of the project itself, + and not of dependencies. + + + + + + + 3.0.0+ + The full legal name of + the license. + + + + + + 3.0.0+ + The official url for + the license text. + + + + + + 3.0.0+ + + + The primary method by which this project may be distributed. +
+
repo
+
may be downloaded from the Maven repository
+
manual
+
user must manually download and install the dependency.
+
+ +
+
+
+ + + 3.0.0+ + A name of the license file + (without path) downloaded from {@link #url}. This path is + relative to the licenses.xml file. + + + + + + 3.0.0+ + + Addendum information pertaining to this license. + + + +
+
+ + + + + + Downloader messages, probably errors + + + + + + + + + + + + + Information about the dependency developers + + + + + + + + + + + + + + Information about the dependency developer + + + + + + + + + + + + + + + + + + + Information extracted from files in the JAR. + + + + + + + + + + + + + + + + + + + + + Information extracted from a file in the JAR. + + + + + + + + + + + + + + + + Copyright lines extracted from the file in the JAR. + + + + + + + + + + + + + Organization info + + + + + + + + diff --git a/src/test/java/org/codehaus/mojo/license/download/LicenseSummaryTest.java b/src/test/java/org/codehaus/mojo/license/download/LicenseSummaryTest.java index 5e46109cf..61d10cde5 100644 --- a/src/test/java/org/codehaus/mojo/license/download/LicenseSummaryTest.java +++ b/src/test/java/org/codehaus/mojo/license/download/LicenseSummaryTest.java @@ -1,8 +1,14 @@ package org.codehaus.mojo.license.download; +import javax.xml.XMLConstants; import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.Source; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactoryConfigurationError; +import javax.xml.transform.stream.StreamSource; +import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; +import javax.xml.validation.Validator; import java.io.File; import java.io.FileInputStream; @@ -11,6 +17,7 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; @@ -29,12 +36,19 @@ import org.codehaus.mojo.license.extended.spreadsheet.ExcelFileWriter; import org.junit.Assert; import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.xml.sax.SAXException; +import static org.codehaus.mojo.license.download.LicenseSummaryWriter.LICENSES_XSD_FILE; +import static org.codehaus.mojo.license.download.LicenseSummaryWriter.LICENSE_PATH; +import static org.junit.Assert.assertTrue; + /** * @since 1.0 */ public class LicenseSummaryTest { + private static final Logger LOG = LoggerFactory.getLogger(LicenseSummaryTest.class); /** * Test reading the license summary xml file into ProjectLicenseInfo objects @@ -46,7 +60,7 @@ public class LicenseSummaryTest { @Test public void testReadLicenseSummary() throws IOException, SAXException, ParserConfigurationException { File licenseSummaryFile = new File("src/test/resources/license-summary-test.xml"); - Assert.assertTrue(licenseSummaryFile.exists()); + assertTrue(licenseSummaryFile.exists()); List list; try (InputStream fis = Files.newInputStream(licenseSummaryFile.toPath())) { list = LicenseSummaryReader.parseLicenseSummary(fis); @@ -106,9 +120,9 @@ public void testWriteReadLicenseSummary() { File licenseSummaryFile = File.createTempFile("licSummary", "tmp"); LicenseSummaryWriter.writeLicenseSummary( - licSummary, licenseSummaryFile, StandardCharsets.UTF_8, Eol.LF, true); + licSummary, licenseSummaryFile, StandardCharsets.UTF_8, Eol.LF, true, true); - Assert.assertTrue(licenseSummaryFile.exists()); + assertTrue(licenseSummaryFile.exists()); FileInputStream fis = new FileInputStream(licenseSummaryFile); List list = LicenseSummaryReader.parseLicenseSummary(fis); fis.close(); @@ -124,14 +138,22 @@ public void testWriteReadLicenseSummary() Assert.assertEquals("http://www.gnu.org/licenses/lgpl-3.0.txt", lic0.getUrl()); Assert.assertEquals("lgpl-3.0.txt", lic0.getFile()); Assert.assertEquals("lgpl version 3.0", lic0.getComments()); + + validateXml(licenseSummaryFile); + + // Check if the LICENSES_XSD_FILE was copied to the target directory. + Path targetXsd = + Paths.get(licenseSummaryFile.toPath().getParent().toFile().getAbsolutePath(), LICENSES_XSD_FILE); + File targetFile = targetXsd.toFile(); + assertTrue(targetFile.exists()); } { - File licenseSummaryFile = File.createTempFile("licSummaryNoVersion", "tmp"); + File licenseSummaryFile = File.createTempFile("licSummaryNoVersionNoXsd", "tmp"); LicenseSummaryWriter.writeLicenseSummary( - licSummary, licenseSummaryFile, StandardCharsets.UTF_8, Eol.LF, false); + licSummary, licenseSummaryFile, StandardCharsets.UTF_8, Eol.LF, false, false); - Assert.assertTrue(licenseSummaryFile.exists()); + assertTrue(licenseSummaryFile.exists()); FileInputStream fis = new FileInputStream(licenseSummaryFile); List list = LicenseSummaryReader.parseLicenseSummary(fis); fis.close(); @@ -147,6 +169,8 @@ public void testWriteReadLicenseSummary() Assert.assertEquals("http://www.gnu.org/licenses/lgpl-3.0.txt", lic0.getUrl()); Assert.assertEquals("lgpl-3.0.txt", lic0.getFile()); Assert.assertEquals("lgpl version 3.0", lic0.getComments()); + + validateXml(licenseSummaryFile); } Path licensesExcelOutputFile = Files.createTempFile("licExcel", ".xlsx"); @@ -156,6 +180,24 @@ public void testWriteReadLicenseSummary() CalcFileWriter.write(licSummary, licensesCalcOutputFile.toFile()); } + /** + * Validate XML against XSD. + * + * @param licenseSummaryFile License summary file. + * @throws SAXException SAX exception, validation problem. + * @throws IOException I/O exception, file problem. + */ + private static void validateXml(File licenseSummaryFile) throws SAXException, IOException { + SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); + try (InputStream inputStream = LicenseSummaryTest.class.getResourceAsStream(LICENSE_PATH)) { + Source schemaSource = new StreamSource(inputStream); + Schema schema = schemaFactory.newSchema(schemaSource); + Validator validator = schema.newValidator(); + Source xmlSource = new StreamSource(licenseSummaryFile); + validator.validate(xmlSource); + } + } + private static ExtendedInfo buildExtendedInfo(int suffix) { ExtendedInfo extendedInfo = new ExtendedInfo(); Artifact artifact = new DefaultArtifact( From 25cc51894f9c9ce3bfadcd01adc82bd3060f4778 Mon Sep 17 00:00:00 2001 From: Jan Diederich Date: Fri, 1 Dec 2023 22:40:54 +0100 Subject: [PATCH 34/34] useXsd removed --- .../pom.xml | 1 - .../postbuild.groovy | 6 +--- .../license/AbstractDownloadLicensesMojo.java | 11 +------ .../mojo/license/AbstractLicensesXmlMojo.java | 5 ++- .../LicensesXmlInsertVersionsMojo.java | 11 +------ .../download/LicenseSummaryWriter.java | 32 +------------------ .../license/download/LicenseSummaryTest.java | 12 ++----- 7 files changed, 8 insertions(+), 70 deletions(-) diff --git a/src/it/aggregate-download-licenses-extended-spreadsheet/pom.xml b/src/it/aggregate-download-licenses-extended-spreadsheet/pom.xml index 7cdc2d7bf..440e75bf5 100644 --- a/src/it/aggregate-download-licenses-extended-spreadsheet/pom.xml +++ b/src/it/aggregate-download-licenses-extended-spreadsheet/pom.xml @@ -56,7 +56,6 @@ true true true - true The Apache Software License, Version 2.0|Apache License, Version 2.0|Apache Public License 2.0 diff --git a/src/it/aggregate-download-licenses-extended-spreadsheet/postbuild.groovy b/src/it/aggregate-download-licenses-extended-spreadsheet/postbuild.groovy index 07fbbc443..6a6fe753f 100644 --- a/src/it/aggregate-download-licenses-extended-spreadsheet/postbuild.groovy +++ b/src/it/aggregate-download-licenses-extended-spreadsheet/postbuild.groovy @@ -83,8 +83,4 @@ try (OdfSpreadsheetDocument spreadsheet = OdfSpreadsheetDocument.loadDocument(ca List tableList = spreadsheet.getTableList() OdfTable table = tableList.get(0) assert table.getRowCount() >= 3 -} - -// ----------- Check for XSD file ---------------- -licensesXsd = new File(basedir, 'target/generated-resources/licenses.xsd') -assert licensesXsd.exists() \ No newline at end of file +} \ No newline at end of file diff --git a/src/main/java/org/codehaus/mojo/license/AbstractDownloadLicensesMojo.java b/src/main/java/org/codehaus/mojo/license/AbstractDownloadLicensesMojo.java index 07fde3bb2..ca741add0 100644 --- a/src/main/java/org/codehaus/mojo/license/AbstractDownloadLicensesMojo.java +++ b/src/main/java/org/codehaus/mojo/license/AbstractDownloadLicensesMojo.java @@ -614,15 +614,6 @@ public abstract class AbstractDownloadLicensesMojo extends AbstractLicensesXmlMo @Parameter(property = "license.writeVersions", defaultValue = "true") private boolean writeVersions; - /** - * If {@code true}, a licenses.xsd file will be written in the same directory as the - * XML file, and be referenced in the XML file. - * - * @since 2.4 - */ - @Parameter(property = "license.useXsd", defaultValue = "false") - private boolean useXsd; - /** * Connect timeout in milliseconds passed to the HTTP client when downloading licenses from remote URLs. * @@ -933,7 +924,7 @@ public void execute() throws MojoExecutionException, MojoFailureException { private void writeLicenseSummaries( List depProjectLicenses, File outputFile, File excelOutputFile, File calcOutputFile) throws ParserConfigurationException, TransformerException, IOException { - writeLicenseSummary(depProjectLicenses, outputFile, writeVersions, useXsd); + writeLicenseSummary(depProjectLicenses, outputFile, writeVersions); if (writeExcelFile) { ExcelFileWriter.write(depProjectLicenses, excelOutputFile); } diff --git a/src/main/java/org/codehaus/mojo/license/AbstractLicensesXmlMojo.java b/src/main/java/org/codehaus/mojo/license/AbstractLicensesXmlMojo.java index 212e53894..b77b007d4 100644 --- a/src/main/java/org/codehaus/mojo/license/AbstractLicensesXmlMojo.java +++ b/src/main/java/org/codehaus/mojo/license/AbstractLicensesXmlMojo.java @@ -157,11 +157,10 @@ protected Path[] getAutodetectEolFiles() { return new Path[] {licensesOutputFile.toPath()}; } - protected void writeLicenseSummary( - List deps, File licensesOutputFile, boolean writeVersions, boolean useXsd) + protected void writeLicenseSummary(List deps, File licensesOutputFile, boolean writeVersions) throws ParserConfigurationException, TransformerException, IOException { initEncoding(); LicenseSummaryWriter.writeLicenseSummary( - deps, licensesOutputFile, charset, licensesOutputFileEol, writeVersions, useXsd); + deps, licensesOutputFile, charset, licensesOutputFileEol, writeVersions); } } diff --git a/src/main/java/org/codehaus/mojo/license/LicensesXmlInsertVersionsMojo.java b/src/main/java/org/codehaus/mojo/license/LicensesXmlInsertVersionsMojo.java index c9490b99c..fe1fae60d 100644 --- a/src/main/java/org/codehaus/mojo/license/LicensesXmlInsertVersionsMojo.java +++ b/src/main/java/org/codehaus/mojo/license/LicensesXmlInsertVersionsMojo.java @@ -76,15 +76,6 @@ public class LicensesXmlInsertVersionsMojo extends AbstractLicensesXmlMojo { @Parameter(property = "license.skipDownloadLicenses", defaultValue = "false") private boolean skipDownloadLicenses; - /** - * If {@code true}, a licenses.xsd file will be written in the same directory as the - * XML file, and be referenced in the XML file. - * - * @since 2.4 - */ - @Parameter(property = "license.useXsd", defaultValue = "false") - private boolean useXsd; - public void execute() throws MojoExecutionException, MojoFailureException { if (skipDownloadLicenses) { @@ -161,7 +152,7 @@ public ArtifactFilters getArtifactFilters() { dependencyLicenseInfo.setVersion(dependency.getVersion()); } - writeLicenseSummary(projectLicenseInfos, licensesOutputFile, true, useXsd); + writeLicenseSummary(projectLicenseInfos, licensesOutputFile, true); } catch (MojoFailureException e) { throw e; } catch (Exception e) { diff --git a/src/main/java/org/codehaus/mojo/license/download/LicenseSummaryWriter.java b/src/main/java/org/codehaus/mojo/license/download/LicenseSummaryWriter.java index 70c1fff8c..2eef92a9b 100644 --- a/src/main/java/org/codehaus/mojo/license/download/LicenseSummaryWriter.java +++ b/src/main/java/org/codehaus/mojo/license/download/LicenseSummaryWriter.java @@ -34,13 +34,9 @@ import java.io.File; import java.io.IOException; -import java.io.InputStream; import java.io.StringWriter; import java.nio.charset.Charset; import java.nio.file.Files; -import java.nio.file.NoSuchFileException; -import java.nio.file.Path; -import java.nio.file.Paths; import java.util.Collection; import java.util.List; import java.util.Optional; @@ -55,8 +51,6 @@ import org.codehaus.mojo.license.Eol; import org.codehaus.mojo.license.extended.ExtendedInfo; import org.codehaus.mojo.license.extended.InfoFile; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; @@ -70,19 +64,12 @@ */ public class LicenseSummaryWriter { - private static final Logger LOG = LoggerFactory.getLogger(LicenseSummaryWriter.class); - static final String LICENSES_XSD_FILE = "licenses.xsd"; private static final String LICENSE_FOLDER = "/org/codehaus/mojo/license/"; static final String LICENSE_PATH = LICENSE_FOLDER + LICENSES_XSD_FILE; public static void writeLicenseSummary( - List dependencies, - File outputFile, - Charset charset, - Eol eol, - boolean writeVersions, - boolean useXsd) + List dependencies, File outputFile, Charset charset, Eol eol, boolean writeVersions) throws ParserConfigurationException, TransformerException, IOException { DocumentBuilderFactory fact = DocumentBuilderFactory.newInstance(); DocumentBuilder parser = fact.newDocumentBuilder(); @@ -90,23 +77,6 @@ public static void writeLicenseSummary( Element root = doc.createElement("licenseSummary"); - if (useXsd) { - root.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance"); - root.setAttribute("xsi:noNamespaceSchemaLocation", LICENSES_XSD_FILE); - Path targetXsd = Paths.get(outputFile.toPath().getParent().toFile().getAbsolutePath(), LICENSES_XSD_FILE); - File targetFile = targetXsd.toFile(); - if (targetFile.exists()) { - LOG.debug("Target XSD file {} already does exist", targetXsd); - } else { - try (InputStream inputStream = LicenseSummaryWriter.class.getResourceAsStream(LICENSE_PATH)) { - if (inputStream == null) { - throw new NoSuchFileException(LICENSE_PATH); - } - Files.copy(inputStream, targetXsd); - } - } - } - doc.appendChild(root); Node dependenciesNode = doc.createElement("dependencies"); root.appendChild(dependenciesNode); diff --git a/src/test/java/org/codehaus/mojo/license/download/LicenseSummaryTest.java b/src/test/java/org/codehaus/mojo/license/download/LicenseSummaryTest.java index 61d10cde5..bea9a9892 100644 --- a/src/test/java/org/codehaus/mojo/license/download/LicenseSummaryTest.java +++ b/src/test/java/org/codehaus/mojo/license/download/LicenseSummaryTest.java @@ -17,7 +17,6 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; @@ -40,7 +39,6 @@ import org.slf4j.LoggerFactory; import org.xml.sax.SAXException; -import static org.codehaus.mojo.license.download.LicenseSummaryWriter.LICENSES_XSD_FILE; import static org.codehaus.mojo.license.download.LicenseSummaryWriter.LICENSE_PATH; import static org.junit.Assert.assertTrue; @@ -120,7 +118,7 @@ public void testWriteReadLicenseSummary() { File licenseSummaryFile = File.createTempFile("licSummary", "tmp"); LicenseSummaryWriter.writeLicenseSummary( - licSummary, licenseSummaryFile, StandardCharsets.UTF_8, Eol.LF, true, true); + licSummary, licenseSummaryFile, StandardCharsets.UTF_8, Eol.LF, true); assertTrue(licenseSummaryFile.exists()); FileInputStream fis = new FileInputStream(licenseSummaryFile); @@ -140,18 +138,12 @@ public void testWriteReadLicenseSummary() Assert.assertEquals("lgpl version 3.0", lic0.getComments()); validateXml(licenseSummaryFile); - - // Check if the LICENSES_XSD_FILE was copied to the target directory. - Path targetXsd = - Paths.get(licenseSummaryFile.toPath().getParent().toFile().getAbsolutePath(), LICENSES_XSD_FILE); - File targetFile = targetXsd.toFile(); - assertTrue(targetFile.exists()); } { File licenseSummaryFile = File.createTempFile("licSummaryNoVersionNoXsd", "tmp"); LicenseSummaryWriter.writeLicenseSummary( - licSummary, licenseSummaryFile, StandardCharsets.UTF_8, Eol.LF, false, false); + licSummary, licenseSummaryFile, StandardCharsets.UTF_8, Eol.LF, false); assertTrue(licenseSummaryFile.exists()); FileInputStream fis = new FileInputStream(licenseSummaryFile);