From 460a584aac6348da27f24bb07d73cf944edf2438 Mon Sep 17 00:00:00 2001 From: goneall Date: Mon, 13 Jan 2014 12:13:05 -0800 Subject: [PATCH] Initial Commit --- LICENSE | 202 +++++ NOTICE | 170 ++++ README.txt | 17 + pom.xml | 123 +++ src/it/settings.xml | 55 ++ src/it/simple-it/pom.xml | 34 + src/it/simple-it/verify.groovy | 3 + src/main/java/org/spdx/maven/ArtifactOf.java | 60 ++ .../java/org/spdx/maven/CreateSpdxMojo.java | 762 ++++++++++++++++++ .../org/spdx/maven/NonStandardLicense.java | 118 +++ .../spdx/maven/SpdxCollectionException.java | 70 ++ .../maven/SpdxDefaultFileInformation.java | 101 +++ .../org/spdx/maven/SpdxFileCollector.java | 352 ++++++++ .../spdx/maven/SpdxProjectInformation.java | 245 ++++++ src/test/java/TestSpdxFileCollector.java | 91 +++ 15 files changed, 2403 insertions(+) create mode 100644 LICENSE create mode 100644 NOTICE create mode 100644 README.txt create mode 100644 pom.xml create mode 100644 src/it/settings.xml create mode 100644 src/it/simple-it/pom.xml create mode 100644 src/it/simple-it/verify.groovy create mode 100644 src/main/java/org/spdx/maven/ArtifactOf.java create mode 100644 src/main/java/org/spdx/maven/CreateSpdxMojo.java create mode 100644 src/main/java/org/spdx/maven/NonStandardLicense.java create mode 100644 src/main/java/org/spdx/maven/SpdxCollectionException.java create mode 100644 src/main/java/org/spdx/maven/SpdxDefaultFileInformation.java create mode 100644 src/main/java/org/spdx/maven/SpdxFileCollector.java create mode 100644 src/main/java/org/spdx/maven/SpdxProjectInformation.java create mode 100644 src/test/java/TestSpdxFileCollector.java diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..fef8c29 --- /dev/null +++ b/LICENSE @@ -0,0 +1,202 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/NOTICE b/NOTICE new file mode 100644 index 0000000..738ba34 --- /dev/null +++ b/NOTICE @@ -0,0 +1,170 @@ + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + This package has dependencies on the SPDX Tools project which contains the following notices: + + Copyright 2010, 2011, 2012 Source Auditor Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + This package includes software from Jena under the following License: + /* + * (c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Hewlett-Packard Development Company, LP + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +This package includes the GRDDL parser developed by Hewlett Packard under the following license: +� Copyright 2007 Hewlett-Packard Development Company, LP + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +The Jena GRDDL Reader is built on top of other sub-systems which we gratefully acknowledge: + +. +The Saxon XSLT and XQuery Processor from Saxonica Limited +This is distributed under Mozilla Public License Version 1.0 . The version used is Saxon B 8.8; source and binary versions are available from the Saxon download area on SourceForge +CyberNeko HTML Parser +The version used is 0.9.5. It is redistributed, in binary form, under The CyberNeko Software License, Version 1.0. +BrowserLauncher2 +The version used is 1.0. It is redistributed, in binary form, under the GNU Lesser GENERAL PUBLIC LICENSE. Each source file is copyrighted separately, please download the source code for details. + BrowserLauncher2 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 Lesser General Public License for more details. + See also the Jena license and its list of subsystems. + +This package includes software developed by the +Apache Software Foundation (http://www.apache.org/). + +This package includes software from Java-RDFa (https://github.com/shellac/java-rdfa/wiki) under the following license notice: +This work was developed as part of the STARS project [1] at the ILRT. +The project was funded by JISC. + +[1] + +/* + * (c) Copyright 2009 University of Bristol + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + This package includes Jackson (http://jackson.codehaus.org/Download) licensed under the following license choices: + Jackson is dual-licensed under two alternative popular Open Source licenses: Apache (AL 2.0) and GNU Lesser GPL (LGPL 2.1). You choose one or the other, as necessary (if you want to redistribute the code -- for use, you do not need license), and abide by the license rules as defined by the respective license agreement (and only that one). + + This package includes Mustache-Java (https://github.com/spullara/mustache.java) + Mustache-Java is licensed under Apache License 2.0 + + This package includes Google guava-libraries (http://code.google.com/p/guava-libraries/) + guava-libraries are licensed under Apache License 2.0 + + This package includes ANTLR 3.4 (http://www.antlr.org/) + licensed under the following: + The "BSD licence" + Copyright (c) 2007 Terence Parr + All rights reserved. + +Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This package contains opencsv (http://sourceforge.net/projects/opencsv/) licensed under the Apache 2.0 license + + This package contains JSoup (http://jsoup.org) licensed under the MIT license: + jsoup License +The jsoup code-base (include source and compiled packages) are distributed under the open source MIT license as described below. + +The MIT License +Copyright � 2009 - 2013 Jonathan Hedley (jonathan@hedley.net) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..d9ab9a9 --- /dev/null +++ b/README.txt @@ -0,0 +1,17 @@ +NOTE: Currently this is a PROTOTYPE plugin for supporting SPDX in a Maven build. + +Goal which creates a new SPDX file for the package being built. Will replace +any existing SPDX file. + +All SPDX document and SPDX package properties are supported as parameters +to the plugin. + +File level data supports default parameters which are applied to all files. +Future versions of this plugin will support file specific parameters. + +The treatment of licenses for Maven is somewhat involved. Where possible, +SPDX standard licenses ID's should be used. If no SPDX standard license +is available, a nonStandardLicense must be declared as a parameter including +a unique license ID and the verbatim license text. + +This project is licensed under the Apache 2.0 License \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..46f9111 --- /dev/null +++ b/pom.xml @@ -0,0 +1,123 @@ + + 4.0.0 + + org.spdx + spdx-maven-plugin + 0.0.2-SNAPSHOT + maven-plugin + + spdx-maven-plugin Maven Plugin + + + http://maven.apache.org + + + UTF-8 + + + + + org.apache.maven + maven-plugin-api + 2.0 + + + org.apache.maven.plugin-tools + maven-plugin-annotations + 3.2 + provided + + + org.codehaus.plexus + plexus-utils + 3.0.8 + + + junit + junit + 4.8.2 + test + + + org.spdx + spdx-tools + 1.2.2-SNAPSHOT + + + org.apache.maven + maven-project + 2.2.1 + + + + + + + org.apache.maven.plugins + maven-plugin-plugin + 3.2 + + spdx-maven-plugin + true + + + + mojo-descriptor + + descriptor + + + + help-goal + + helpmojo + + + + + + + + + run-its + + + + + org.apache.maven.plugins + maven-invoker-plugin + 1.7 + + true + ${project.build.directory}/it + + */pom.xml + + verify + ${project.build.directory}/local-repo + src/it/settings.xml + + clean + test-compile + + + + + integration-test + + install + integration-test + verify + + + + + + + + + + NOTE: Currently this is a prototype plugin for supporting SPDX in a Maven build. + Goal which creates a new SPDX file for the package being built. + diff --git a/src/it/settings.xml b/src/it/settings.xml new file mode 100644 index 0000000..c8f77f0 --- /dev/null +++ b/src/it/settings.xml @@ -0,0 +1,55 @@ + + + + + + + + it-repo + + true + + + + local.central + @localRepositoryUrl@ + + true + + + true + + + + + + local.central + @localRepositoryUrl@ + + true + + + true + + + + + + diff --git a/src/it/simple-it/pom.xml b/src/it/simple-it/pom.xml new file mode 100644 index 0000000..1155723 --- /dev/null +++ b/src/it/simple-it/pom.xml @@ -0,0 +1,34 @@ + + + 4.0.0 + + org.spdx.it + simple-it + 1.0-SNAPSHOT + + A simple IT verifying the basic use case. + + + UTF-8 + + + + + + @project.groupId@ + @project.artifactId@ + @project.version@ + + + touch + validate + + touch + + + + + + + diff --git a/src/it/simple-it/verify.groovy b/src/it/simple-it/verify.groovy new file mode 100644 index 0000000..7b307c7 --- /dev/null +++ b/src/it/simple-it/verify.groovy @@ -0,0 +1,3 @@ +File touchFile = new File( basedir, "target/touch.txt" ); + +assert touchFile.isFile() diff --git a/src/main/java/org/spdx/maven/ArtifactOf.java b/src/main/java/org/spdx/maven/ArtifactOf.java new file mode 100644 index 0000000..17e3ecf --- /dev/null +++ b/src/main/java/org/spdx/maven/ArtifactOf.java @@ -0,0 +1,60 @@ +/* + * Copyright 2014 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.spdx.maven; + +import java.net.URL; + +import org.apache.maven.plugins.annotations.Parameter; + +/** + * Class to contain information on an SPDX doap project using + * maven parameters to describe the package + * @author Gary O'Neall + * + */ +public class ArtifactOf { + + /** + * Required name of a project from which a file was derived + */ + @Parameter(required = true) + String name; + + /** + * Optional parameter to indicate the location of the project from which the file has been derived + */ + @Parameter + URL homePage; + + public ArtifactOf() { + + } + + /** + * @return the name + */ + public String getName() { + return name; + } + + /** + * @return the homePage + */ + public URL getHomePage() { + return homePage; + } + +} diff --git a/src/main/java/org/spdx/maven/CreateSpdxMojo.java b/src/main/java/org/spdx/maven/CreateSpdxMojo.java new file mode 100644 index 0000000..818fbde --- /dev/null +++ b/src/main/java/org/spdx/maven/CreateSpdxMojo.java @@ -0,0 +1,762 @@ +package org.spdx.maven; + +/* + * Copyright 2014 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import org.apache.maven.model.DistributionManagement; +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; + +import org.apache.maven.plugins.annotations.Execute; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.project.MavenProject; +import org.spdx.rdfparser.DOAPProject; +import org.spdx.rdfparser.InvalidSPDXAnalysisException; +import org.spdx.rdfparser.SPDXCreatorInformation; +import org.spdx.rdfparser.SPDXDocument; +import org.spdx.rdfparser.SPDXLicenseInfo; +import org.spdx.rdfparser.SPDXLicenseInfoFactory; +import org.spdx.rdfparser.SPDXNonStandardLicense; +import org.spdx.rdfparser.SPDXStandardLicense; +import org.spdx.rdfparser.SpdxNoAssertionLicense; +import org.spdx.rdfparser.SpdxRdfConstants; +import org.spdx.rdfparser.SpdxVerificationHelper; +import org.spdx.spdxspreadsheet.InvalidLicenseStringException; + +import com.hp.hpl.jena.rdf.model.Model; +import com.hp.hpl.jena.rdf.model.ModelFactory; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.net.URL; +import java.security.NoSuchAlgorithmException; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.regex.Pattern; + +/** + * NOTE: Currently this is a prototype plugin for supporting SPDX in a Maven build. + * + * Goal which creates a new SPDX file for the package being built. Will replace + * any existing SPDX file. + * + * All SPDX document and SPDX package properties are supported as parameters + * to the plugin. + * + * File level data supports default parameters which are applied to all files. + * Future versions of this plugin will support file specific parameters. + * + * The treatment of licenses for Maven is somewhat involved. Where possible, + * SPDX standard licenses ID's should be used. If no SPDX standard license + * is available, a nonStandardLicense must be declared as a parameter including + * a unique license ID and the verbatim license text. + */ +//TODO: Document POM information mappings +//TODO: Change tabs to 4 spaces +//TODO: Change (param to ( param + +@Mojo( name = "createSPDX", defaultPhase = LifecyclePhase.PREPARE_PACKAGE ) +@Execute ( goal = "createSPDX", phase = LifecyclePhase.PREPARE_PACKAGE ) +public class CreateSpdxMojo + extends AbstractMojo +{ + + static DateFormat format = new SimpleDateFormat(SpdxRdfConstants.SPDX_DATE_FORMAT); + + private static final String CREATOR_TOOL_MAVEN_PLUGIN = "tool: spdx-maven-plugin"; + + /** + * @parameter default-value="${project}" + * @required + * @readonly + */ + @Parameter ( defaultValue ="${project}" ) + MavenProject mavenProject; + + // Parameters for the plugin + /** + * Location of the SPDX file. + */ + @Parameter( defaultValue = "${project.build.directory}/${project.name}-${project.version}-SPDX.rdf", property = "spdxFileName", required = true ) + private File spdxFile; + + /** + * Document URL - must be unique for the artifact and SPDX file + */ + @Parameter( defaultValue = "http://spdx.org/spdxpackages/${project.name}-${project.version}", property = "spdxDocumentUrl", required = true ) + private URL spdxDocumentUrl; + + /** + * Non standard licenses referenced within the Maven SPDX plugin configuration. + * All non standard licenses must be configured containing the required license ID + * and license text. + */ + @Parameter + private NonStandardLicense[] nonStandardLicenses; + + /** + * optional default SPDX file comment field. + * The file comment field provides a place for the SPDX file creator to + * record any general comments about the file. + */ + @Parameter + private String defaultFileComment; + + /** + * optional list of default file contributors. + * This field provides a place for the SPDX file creator to record file contributors. + * Contributors could include names of copyright holders and/or authors who may not be + * copyright holders, yet contributed to the file content. + */ + @Parameter + private String[] defaultFileContributors; + + /** + * Required default file copyright text. + * The copyrightText field Identifies the copyright holder of the file, + * as well as any dates present. The text must much the copyright notice found in the file. + * The options to populate this field are limited to: + * (a) any text relating to a copyright notice, even if not complete; + * (b) NONE, if the file contains no license information whatsoever; or + * (c) NOASSERTION, if the SPDX creator has not examined the contents of the actual file or if the SPDX creator has intentionally provided no information(no meaning should be implied from the absence of an assertion). + */ + @Parameter(required = true) + private String defaultFileCopyright; + + /** + * Optional default file license comment. + * The licenseComments property allows the preparer of the SPDX + * document to describe why the licensing in spdx:licenseConcluded was chosen. + */ + @Parameter + private String defaultFileLicenseComment; + + /** + * Optional default file notice text. + * This field provides a place for the SPDX file creator to record potential legal notices found in the file. + * This may or may not include copyright statements. + */ + @Parameter + private String defaultFileNotice; + + /** + * Required default file concluded license. + * This field contains the license the SPDX file creator has concluded as governing the file or alternative values + * if the governing license cannot be determined. + * The options to populate this field are limited to: + * (a) the SPDX standardized license short form identifier, if the concluded license is on the SPDX License List; + * (b) a reference to the licenses, denoted by LicenseRef-#LicenseRef-[idString], + * if the concluded license is not on the SPDX License List. The license must be specified as a license. + * (c) NOASSERTION should be used if: + * (i) the SPDX file creator has attempted to but cannot reach a reasonable objective determination of the concluded license; + * (ii) the SPDX file creator is uncomfortable concluding a license, despite some license information being available; + * (iii) the SPDX file creator has made no attempt to arrive at a concluded license; + * (iv) the SPDX file creator has intentionally provided no information (no meaning should be implied by doing so); or + * (v) there is no license information from which to conclude a license for the file. + * For a license set, when there is a choice between licenses (“disjunctive license”), + * they should be separated with “or” and enclosed in brackets. + * Similarly when multiple licenses need to be applied (“conjunctive license”), + * they should be separated with “and” and enclosed in parentheses. + */ + @Parameter( required = true ) + private String defaultFileConcludedLicense; + + /** + * Required default license information in file. + * This field contains the license information actually found in the file, + * if any. Any license information not actually in the file, e.g., “COPYING.txt” file in a toplevel directory, should not be reflected in this field. This information is most commonly found in the header of the file, although it may be in other areas of the actual file. The options to populate this field are limited to: + * (a) the SPDX License List short form identifier, if the license is on the SPDX License List; + * (b) a reference to the license, denoted by LicenseRef-#LicenseRef-[idString], if the license is not on the SPDX License List; + * (c) NONE, if the actual file contains no license information whatsoever; or + * (d) NOASSERTION, if the SPDX file creator has not examined the contents of the actual file or the SPDX file creator has intentionally provided no information (no meaning should be implied by doing so). + * For a license set, when there is a choice between licenses (“disjunctive license”), + * they should be separated with “or” and enclosed in brackets. + * Similarly when multiple licenses need to be applied (“conjunctive license”), + * they should be separated with “and” and enclosed in parentheses. + */ + @Parameter( required = true ) + private String defaultLicenseInformationInFile; + + /** + * Optional default file artifactOf. + * ArtifactOf indicates the origin for a given file if it originates from a separate project. + */ + @Parameter + private ArtifactOf[] defaultFileArtifactOfs; + + // the following parameters are for the SPDX project + + /** + * License declared by the originator for the package. If no license + * is specified, the license information in the project POM file will be mapped + * to a standard SPDX license if available. If a non-standard license is used, + * a NOASSERTION value will be used. The format of the string follows the + * standard license string format for SPDX files (see the defaultFileConcludedLicense parameter + * for a full description). + */ + @Parameter + private String licenseDeclared; + + /** + * This field contains the license the SPDX file creator has concluded as governing the package or alternative values, + * if the governing license cannot be determined. + * If this field is not specified, the declared license value will be used for the + * concluded license. + * The format of the string follows the + * standard license string format for SPDX files (see the defaultFileConcludedLicense parameter + * for a full description). + */ + @Parameter + private String licenseConcluded; + + /** + * An optional field for creators of the SPDX file to provide general comments + * about the creation of the SPDX file + * or any other relevant comment not included in the other fields. + */ + @Parameter + private String creatorComment; + + /** + * Identify who (or what, in the case of a tool) created the SPDX file. + * If the SPDX file was created by an individual, indicate the person's name. + * If the SPDX file was created on behalf of a company or organization, indicate the entity name. + * If multiple participants or tools were involved, use multiple instances of this field. + * Person name or organization name may be designated as “anonymous” if appropriate. + * Format: single line of text with the following keywords: + * ”Person: person name” and optional “(email)” + * "Organization: organization” and optional “(email)” + * "Tool: toolidentifier-version” + * + * NOTE: the Tool: spdx-maven-plugin will automatically be added by the plugin + */ + @Parameter + private String[] creators; + + /** + * This field provides a place for the SPDX file creator to record any general comments about the license. + */ + @Parameter + private String licenseComments; + + /** + * The name and, optionally, contact information of the person or organization that originally created the package. + * Note that the supplier field of SPDX is filled in by the Organization in the POM. However, the originator may + * be different than the supplier (e.g. a Maven POM was build by organization X containing code originating from organization Y). + */ + @Parameter + private String originator; + //TODO: Determine if the POM organization should be the originator or the supplier or both + + /** + * Regular expressions for any file or directory names which should be excluded from the SPDX verification code. + * These typically are meta data files which are not included in the distribution of the source files. + * See http://spdx.org/rdf/terms#PackageVerificationCode + */ + @Parameter + private String[] excludedFilePatterns; + + /** + * Directory of files which are included in the package. This is used to create + * the SPDXFiles and the verification code. If there are files in the directory + * which should not be included, the excludedFilePatterns parameter + * can be used to specify any patterns for file or directory names which should be skipped + */ + @Parameter( required = true ) + private File[] includedDirectories; + + + + + + public void execute() + throws MojoExecutionException + { + this.getLog().info("Creating SPDX File "+spdxFile.getPath()); + File f = spdxFile; + + if ( !f.exists() ) + { + File parentDir = f.getParentFile(); + if ( !parentDir.exists() ) { + if ( !f.mkdirs() ) { + this.getLog().error("Unable to create directory containing the SPDX file: "+parentDir.getPath()); + throw(new MojoExecutionException("Unable to create directories for SPDX file")); + } + } + + try { + if (!f.createNewFile()) { + this.getLog().error("Unable to create the SPDX file: "+f.getPath()); + throw(new MojoExecutionException("Unable to create the SPDX file")); + } + } catch (IOException e) { + this.getLog().error("IO error creating the SPDX file "+f.getPath() + ":"+e.getMessage(),e); + throw(new MojoExecutionException("IO error creating the SPDX file")); + } + } + if (!f.canWrite()) { + this.getLog().error("Can not write to SPDX file "+f.getPath()); + throw(new MojoExecutionException("Unable to write to SPDX file - check permissions: "+f.getPath())); + } + if (!spdxFile.exists()) { + this.getLog().error("Can not create SPDX from project - file "+spdxFile.getName()+ " does not exist."); + throw(new MojoExecutionException("Can not create SPDX from project - file "+spdxFile.getName()+ " does not exist.")); + } + if (!spdxFile.canWrite()) { + this.getLog().error("Can not write to SPDX file "+spdxFile.getName() + "."); + throw(new MojoExecutionException("Can not write to SPDX file "+spdxFile.getName()+ ".")); + } + Model model = ModelFactory.createDefaultModel(); + SPDXDocument spdxDoc; + try { + spdxDoc = new SPDXDocument(model); + } catch (InvalidSPDXAnalysisException e) { + this.getLog().error("Error creating SPDX document", e); + throw(new MojoExecutionException("Error creating SPDX document: "+e.getMessage())); + } + try { + spdxDoc.createSpdxAnalysis(spdxDocumentUrl.toString()); + } catch (InvalidSPDXAnalysisException e) { + this.getLog().error("Error creating SPDX analysis", e); + throw(new MojoExecutionException("Error creating SPDX analysis: "+e.getMessage())); + } + try { + spdxDoc.createSpdxPackage(); + } catch (InvalidSPDXAnalysisException e) { + this.getLog().error("Error creating SPDX package", e); + throw(new MojoExecutionException("Error creating SPDX package: "+e.getMessage())); + } + Pattern[] excludedFilePatterns = getPatternFromParameters(); + File[] includedDirectories = getIncludedDirectoriesFromParameters(); + processNonStandardLicenses(spdxDoc); + SpdxProjectInformation projectInformation = getSpdxProjectInfoFromParameters(); + SpdxDefaultFileInformation defaultFileInformation = getDefaultFileInfoFromParameters(); + + // The following is for debugging purposes + logExcludedFilePatterns(excludedFilePatterns); + logIncludedDirectories(includedDirectories); + logNonStandardLicenses(this.nonStandardLicenses); + projectInformation.logInfo(this.getLog()); + logDefaultFileInformation(defaultFileInformation); +// createSpdxFromProject(f, spdxDoc, spdxDocumentUrl, excludedFilePatterns, includedDirectories, +// projectInformation, defaultFileInformation); + } + + /** + * Primarily for debugging purposes - logs defaultFileInformation as info + * @param defaultFileInformation + */ + private void logDefaultFileInformation( + SpdxDefaultFileInformation defaultFileInformation) { + if (defaultFileInformation == null) { + return; + } + this.getLog().info("Default File Comment: "+defaultFileInformation.getComment()); + this.getLog().info("Default File Copyright: "+defaultFileInformation.getCopyright()); + this.getLog().info("Default File License Comment: "+defaultFileInformation.getLicenseComment()); + this.getLog().info("Default File Notice: "+defaultFileInformation.getNotice()); + this.getLog().info("Default File Concluded License: "+defaultFileInformation.getConcludedLicense().toString()); + this.getLog().info("Default File Declared License: "+defaultFileInformation.getDeclaredLicense().toString()); + DOAPProject[] artifactOfs = defaultFileInformation.getArtifactOf(); + if (artifactOfs != null) { + for (int i = 0; i < artifactOfs.length; i++) { + this.getLog().info("Default ArtifactOf Project Name: "+artifactOfs[i].getName()); + this.getLog().info("Default ArtifactOf Project HomePage: "+artifactOfs[i].getHomePage()); + } + } + String[] contributors = defaultFileInformation.getContributors(); + if (contributors != null) { + for (int i = 0; i < contributors.length; i++) { + this.getLog().info("Default File Contributors: "+contributors[i]); + } + } + } + + /** + * Primarily for debugging purposes - logs nonStandardLicenses as info + * @param nonStandardLicenses + */ + private void logNonStandardLicenses( + NonStandardLicense[] nonStandardLicenses) { + if (nonStandardLicenses == null) { + return; + } + for (int i = 0; i < nonStandardLicenses.length; i++) { + this.getLog().info("Non standard license ID: "+nonStandardLicenses[i].getLicenseId()); + this.getLog().info("Non standard license Text: "+nonStandardLicenses[i].getExtractedText()); + this.getLog().info("Non standard license Comment: "+nonStandardLicenses[i].getComment()); + this.getLog().info("Non standard license Name: "+nonStandardLicenses[i].getName()); + String[] crossReferences = nonStandardLicenses[i].getCrossReference(); + if (crossReferences != null) { + for (int j = 0; j < crossReferences.length; j++) { + this.getLog().info("Non standard license cross reference: "+crossReferences[j]); + } + } + } + } + + /** + * Primarily for debugging purposes - logs includedDirectories as info + * @param includedDirectories + */ + private void logIncludedDirectories(File[] includedDirectories) { + if (includedDirectories == null) { + return; + } + for (int i = 0; i < includedDirectories.length; i++) { + this.getLog().info("Included Directory: "+includedDirectories[i].getPath()); + } + } + + /** + * Primarily for debugging purposes - logs excludedFilePatterns as info + * @param excludedFilePatterns + */ + private void logExcludedFilePatterns(Pattern[] excludedFilePatterns) { + if (excludedFilePatterns == null) { + return; + } + for (int i = 0; i < excludedFilePatterns.length; i++) { + this.getLog().info("Excluded File Pattern: "+excludedFilePatterns[i].pattern()); + } + } + + /** + * Run through the non standard licenses and add them to the SPDX document + * @param spdxDoc + * @throws MojoExecutionException + */ + private void processNonStandardLicenses(SPDXDocument spdxDoc) throws MojoExecutionException { + if (this.nonStandardLicenses != null) { + for (int i = 0; i < this.nonStandardLicenses.length; i++) { + NonStandardLicense license = this.nonStandardLicenses[i]; + SPDXNonStandardLicense spdxLicense = new SPDXNonStandardLicense( + license.getLicenseId(), license.getExtractedText(), license.getName(), + license.getCrossReference(), license.getComment()); + try { + spdxDoc.addNewExtractedLicenseInfo(spdxLicense); + } catch (InvalidSPDXAnalysisException e) { + String licenseId = license.getLicenseId(); + if (licenseId == null) { + licenseId = "[NullLicenseId]"; + } + this.getLog().error("Error adding license "+licenseId, e); + throw(new MojoExecutionException("Unable to add non standard license "+licenseId+": "+e.getMessage(),e)); + } + } + } + } + + /** + * @return default file information from the plugin parameters + * @throws MojoExecutionException + */ + private SpdxDefaultFileInformation getDefaultFileInfoFromParameters() throws MojoExecutionException { + SpdxDefaultFileInformation retval = new SpdxDefaultFileInformation(); + retval.setArtifactOf(getDefaultFileProjects()); + retval.setComment(defaultFileComment); + SPDXLicenseInfo concludedLicense = null; + try { + concludedLicense = SPDXLicenseInfoFactory.parseSPDXLicenseString(defaultFileConcludedLicense.trim()); + } catch (InvalidLicenseStringException e) { + this.getLog().error("Invalid default file concluded license: "+e.getMessage()); + throw(new MojoExecutionException("Invalid default file concluded license: "+e.getMessage())); + } + retval.setConcludedLicense(concludedLicense); + retval.setContributors(defaultFileContributors); + retval.setCopyright(defaultFileCopyright); + SPDXLicenseInfo declaredLicense = null; + try { + declaredLicense = SPDXLicenseInfoFactory.parseSPDXLicenseString(defaultLicenseInformationInFile.trim()); + } catch (InvalidLicenseStringException e) { + this.getLog().error("Invalid default file declared license: "+e.getMessage()); + throw(new MojoExecutionException("Invalid default file declared license: "+e.getMessage())); + } + retval.setDeclaredLicense(declaredLicense); + retval.setLicenseComment(defaultFileLicenseComment); + retval.setNotice(defaultFileNotice); + return retval; + } + + private DOAPProject[] getDefaultFileProjects() { + if (this.defaultFileArtifactOfs == null) { + return new DOAPProject[0]; + } + DOAPProject[] retval = new DOAPProject[this.defaultFileArtifactOfs.length]; + for (int i = 0; i < retval.length; i++) { + retval[i] = new DOAPProject(defaultFileArtifactOfs[i].getName(), + defaultFileArtifactOfs[i].getHomePage().toString()); + } + return retval; + } + + /** + * Get the SPDX project level information from the parameters + * The following project level information is taken from the POM project description: + * declaredLicense - mapped by the license parameter in the project. Can be overriden by specifying a plugin configuration declaredLicense string + * concludedLicense - same as the declared license unless overridden by the plugin configuration parameter concludedLicense + * name - name of the project. If not provided, the artifactId is used + * distributionManagement().downloadUrl - If not provided, a default value of 'NOASSERTION' is used + * packageFileName is the artifact().getFile fileName if it can be found. The checksum is also calculated from this value. If no file + * could be determined, a 'NOASSERTION' value is used + * description - The project description is used for the SPDX package description and SPDX package summary + * organization - the project organization is used for the supplier. "ORGANIZATION: " is prepended + * @return + * @throws MojoExecutionException + */ + private SpdxProjectInformation getSpdxProjectInfoFromParameters() throws MojoExecutionException { + SpdxProjectInformation retval = new SpdxProjectInformation(); + SPDXLicenseInfo declaredLicense = null; + if (this.licenseDeclared == null) { + declaredLicense = mapProjectLicense(); + } else { + try { + declaredLicense = SPDXLicenseInfoFactory.parseSPDXLicenseString(this.licenseDeclared.trim()); + } catch (InvalidLicenseStringException e) { + this.getLog().error("Invalid declared license: "+e.getMessage()); + throw(new MojoExecutionException("Invalid declared license: "+e.getMessage())); + } + } + SPDXLicenseInfo concludedLicense = null; + if (this.licenseConcluded == null) { + concludedLicense = declaredLicense; + } else { + try { + concludedLicense = SPDXLicenseInfoFactory.parseSPDXLicenseString(this.licenseConcluded.trim()); + } catch (InvalidLicenseStringException e) { + this.getLog().error("Invalid concluded license: "+e.getMessage()); + throw(new MojoExecutionException("Invalid concluded license: "+e.getMessage())); + } + } + retval.setConcludedLicense(concludedLicense); + retval.setCreatorComment(this.creatorComment); + retval.setCreators(this.creators); + retval.setDeclaredLicense(declaredLicense); + String projectName = mavenProject.getName(); + if (projectName == null || projectName.isEmpty()) { + projectName = getDefaultProjectName(); + } + retval.setName(projectName); + retval.setDescription(mavenProject.getDescription()); + String downloadUrl = "NOASSERTION"; + DistributionManagement distributionManager = mavenProject.getDistributionManagement(); + if (distributionManager != null) { + if (distributionManager.getDownloadUrl() != null && !distributionManager.getDownloadUrl().isEmpty()) { + downloadUrl = distributionManager.getDownloadUrl(); + } + } + retval.setDownloadUrl(downloadUrl); + retval.setHomePage(mavenProject.getUrl()); + retval.setLicenseComment(this.licenseComments); + retval.setOriginator(this.originator); + String packageFileName; + File packageFile = mavenProject.getArtifact().getFile(); + if (packageFile != null) { + packageFileName = packageFile.getName(); + } else { + packageFileName = "NOASSERTION"; + } + retval.setPackageArchiveFileName(packageFileName); + String sha1 = null; + if (packageFile != null) { + try + { + sha1 = SpdxFileCollector.generateSha1( packageFile ); + } + catch ( SpdxCollectionException e ) + { + this.getLog().warn( "Unable to collect sha1 value for "+packageFile.getName()+":"+e.getMessage() ); + } + } + retval.setSha1(sha1); + retval.setShortDescription(mavenProject.getDescription()); + String supplier = mavenProject.getOrganization().getName(); + if (supplier != null && !supplier.isEmpty()) { + supplier = "ORGANIZATION: "+supplier; + retval.setSupplier(supplier); + } + retval.setVersionInfo(mavenProject.getVersion()); + return retval; + } + + + /** + * Get the default project name if no project name is specified in the POM + * @return + */ + private String getDefaultProjectName() { + return this.mavenProject.getArtifactId(); + } + + /** + * Map the license declared in the POM file to an SPDX license + * @return + */ + private SPDXLicenseInfo mapProjectLicense() { + // TODO Auto-generated method stub + return new SpdxNoAssertionLicense(); + } + + private File[] getIncludedDirectoriesFromParameters() { + return this.includedDirectories; + //TODO: See if this can be extracted from other parameters + } + + private Pattern[] getPatternFromParameters() throws MojoExecutionException { + if (this.excludedFilePatterns == null) { + return new Pattern[0]; + } + Pattern[] retval = new Pattern[this.excludedFilePatterns.length]; + for (int i = 0; i < retval.length; i++) { + try { + retval[i] = Pattern.compile( excludedFilePatterns[i] ); + } catch (Exception e) { + this.getLog().error( "Error in excluded file pattern "+excludedFilePatterns[i], e ); + throw(new MojoExecutionException( "Error in excluded file pattern "+excludedFilePatterns[i]+": "+e.getMessage())); + } + } + return retval; + } + + public void createSpdxFromProject(File spdxFile, SPDXDocument spdxDoc, URL spdxDocumentUrl, Pattern[] excludedFilePatterns, + File[] includedDirectories, SpdxProjectInformation projectInformation, + SpdxDefaultFileInformation defaultFileInformation) throws MojoExecutionException { + + FileOutputStream spdxOut = null; + try { + spdxOut = new FileOutputStream(spdxFile); + fillSpdxDocumentInformation(spdxDoc, projectInformation); + collectSpdxFileInformation(spdxDoc, excludedFilePatterns, includedDirectories, + defaultFileInformation, spdxFile.getPath().replace("\\", "/")); + spdxDoc.getModel().write(spdxOut); + } catch (FileNotFoundException e) { + this.getLog().error("Error saving SPDX data to file", e); + throw(new MojoExecutionException("Error saving SPDX data to file: "+e.getMessage())); + } catch (InvalidSPDXAnalysisException e) { + this.getLog().error("Error collecting SPDX file data", e); + throw(new MojoExecutionException("Error collecting SPDX file data: "+e.getMessage())); + } finally { + if (spdxOut != null) { + try { + spdxOut.close(); + } catch (IOException e) { + this.getLog().warn("Error closing SPDX output file", e); + } + } + } + } + + private void fillSpdxDocumentInformation(SPDXDocument spdxDoc, + SpdxProjectInformation projectInformation) throws MojoExecutionException { + try { + // creator + fillCreatorInfo(spdxDoc, projectInformation); + // data license + SPDXStandardLicense dataLicense = (SPDXStandardLicense)(SPDXLicenseInfoFactory.parseSPDXLicenseString(SPDXDocument.SPDX_DATA_LICENSE_ID)); + spdxDoc.setDataLicense(dataLicense); + // reviewers - not implemented + // packageName + spdxDoc.getSpdxPackage().setDeclaredName(projectInformation.getName()); + // concluded license + spdxDoc.getSpdxPackage().setConcludedLicenses(projectInformation.getConcludedLicense()); + // declared license + spdxDoc.getSpdxPackage().setDeclaredLicense(projectInformation.getDeclaredLicense()); + // description + spdxDoc.getSpdxPackage().setDescription(projectInformation.getDescription()); + // download url + spdxDoc.getSpdxPackage().setDownloadUrl(projectInformation.getDownloadUrl()); + // archive file name + spdxDoc.getSpdxPackage().setFileName(projectInformation.getPackageArchiveFileName()); + // home page + spdxDoc.getSpdxPackage().setHomePage(projectInformation.getHomePage()); + // license comment + spdxDoc.getSpdxPackage().setLicenseComment(projectInformation.getLicenseComment()); + // originator + spdxDoc.getSpdxPackage().setOriginator(projectInformation.getOriginator()); + // sha1 checksum + spdxDoc.getSpdxPackage().setSha1(projectInformation.getSha1()); + // short description + spdxDoc.getSpdxPackage().setShortDescription(projectInformation.getShortDescription()); + // supplier + spdxDoc.getSpdxPackage().setSupplier(projectInformation.getSupplier()); + // version info + spdxDoc.getSpdxPackage().setVersionInfo(projectInformation.getVersionInfo()); + } catch (InvalidSPDXAnalysisException e) { + this.getLog().error("SPDX error filling SPDX information", e); + throw(new MojoExecutionException("Error adding package information to SPDX document: "+e.getMessage())); + } catch (InvalidLicenseStringException e) { + this.getLog().error("SPDX error creating license", e); + throw(new MojoExecutionException("Error adding package information to SPDX document: "+e.getMessage())); + } + } + + private void fillCreatorInfo(SPDXDocument spdxDoc, + SpdxProjectInformation projectInformation) throws InvalidSPDXAnalysisException { + ArrayList creators = new ArrayList(); + creators.add(CREATOR_TOOL_MAVEN_PLUGIN); + String[] parameterCreators = projectInformation.getCreators(); + for (int i = 0; i < parameterCreators.length; i++) { + String verify = SpdxVerificationHelper.verifyCreator(parameterCreators[i]); + if (verify == null) { + creators.add(parameterCreators[i]); + } else { + this.getLog().warn("Invalid creator string ("+verify+"), "+ + parameterCreators[i]+" will be skipped."); + } + } + SPDXCreatorInformation spdxCreator = new SPDXCreatorInformation( + creators.toArray(new String[creators.size()]), format.format(new Date()), + projectInformation.getCreatorComment(), + SPDXLicenseInfoFactory.DEFAULT_LICENSE_LIST_VERSION); + spdxDoc.setCreationInfo(spdxCreator); + } + + private void collectSpdxFileInformation(SPDXDocument spdxDoc, + Pattern[] excludedFilePatterns, File[] includedDirectories, + SpdxDefaultFileInformation defaultFileInformation, + String spdxFileName) throws InvalidSPDXAnalysisException, MojoExecutionException { + + SpdxFileCollector fileCollector = new SpdxFileCollector(spdxDoc, + excludedFilePatterns, defaultFileInformation); + + for (int i = 0; i < includedDirectories.length; i++) { + try { + fileCollector.collectFilesInDirectory(includedDirectories[i]); + } catch (SpdxCollectionException e) { + this.getLog().error("SPDX error collecting file information", e); + throw(new MojoExecutionException("Error collecting SPDX file information: "+e.getMessage())); + } + } + spdxDoc.getSpdxPackage().setFiles(fileCollector.getFiles()); + spdxDoc.getSpdxPackage().setLicenseInfoFromFiles(fileCollector.getLicenseInfoFromFiles()); + try { + spdxDoc.getSpdxPackage().setVerificationCode(fileCollector.getVerificationCode(spdxFileName)); + } catch (NoSuchAlgorithmException e) { + this.getLog().error("Error calculating verification code", e); + throw(new MojoExecutionException("Unable to calculate verification code")); + } catch (InvalidSPDXAnalysisException e) { + this.getLog().error("SPDX Error updating verification code", e); + throw(new MojoExecutionException("Unable to update verification code")); + } + } +} diff --git a/src/main/java/org/spdx/maven/NonStandardLicense.java b/src/main/java/org/spdx/maven/NonStandardLicense.java new file mode 100644 index 0000000..6ebee56 --- /dev/null +++ b/src/main/java/org/spdx/maven/NonStandardLicense.java @@ -0,0 +1,118 @@ +/* + * Copyright 2014 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.spdx.maven; + +import java.net.URL; + +import org.apache.maven.plugins.annotations.Parameter; + +/** + * Non standard license (e.g. license which is not in the SPDX standard license list http://spdx.org/licenses) + * @author Gary O'Neall + * + */ +public class NonStandardLicense { + + /** + * Required license ID. Must be of the form "LicenseRef-"[idString] + * where [idString] is a unique string containing letters, numbers, “.”, “-” or “+”. + * Note that this is required for the Maven use of non standard licenses. The SPDX + * standard does not generally require this parameter. + */ + @Parameter(required = true) + private String licenseId; + + /** + * Required verbatim license or licensing notice text + */ + @Parameter(required = true) + private String extractedText; + + /** + * Optional: Common name of the license not on the SPDX list. + * If there is no common name or it is not known, please use NOASSERTION. + */ + @Parameter + private String name; + /** + * + */ + @Parameter + private String comment; + + /** + * Provide a pointer to the official source of a license that is not included + * in the SPDX table, that is referenced by the id. + */ + @Parameter + URL[] crossReference; + + /** + * Create a default, non standard license + */ + public NonStandardLicense() { + + } + + /** + * @return the licenseId + */ + public String getLicenseId() { + return licenseId; + } + + /** + * @return the extractedText + */ + public String getExtractedText() { + return extractedText; + } + + /** + * @return the name + */ + public String getName() { + if (name == null) { + return ""; + } + return name; + } + + /** + * @return the comment + */ + public String getComment() { + if (comment == null) { + return ""; + } + return comment; + } + + /** + * @return the crossReference + */ + public String[] getCrossReference() { + if (this.crossReference == null) { + return new String[0]; + } + String[] retval = new String[this.crossReference.length]; + for (int i = 0; i < retval.length; i++) { + retval[i] = this.crossReference[i].toString(); + } + return retval; + } + +} diff --git a/src/main/java/org/spdx/maven/SpdxCollectionException.java b/src/main/java/org/spdx/maven/SpdxCollectionException.java new file mode 100644 index 0000000..fe8e12a --- /dev/null +++ b/src/main/java/org/spdx/maven/SpdxCollectionException.java @@ -0,0 +1,70 @@ +/* + * Copyright 2014 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.spdx.maven; + +/** + * Exceptions for the collection of SPDX information + * @author Gary O'Neall + * + */ +public class SpdxCollectionException extends Exception { + + /** + * + */ + private static final long serialVersionUID = 1L; + + /** + * + */ + public SpdxCollectionException() { + super(); + } + + /** + * @param message + */ + public SpdxCollectionException(String message) { + super(message); + } + + /** + * @param cause + */ + public SpdxCollectionException(Throwable cause) { + super(cause); + } + + /** + * @param message + * @param cause + */ + public SpdxCollectionException(String message, Throwable cause) { + super(message, cause); + } + + /** + * @param message + * @param cause + * @param enableSuppression + * @param writableStackTrace + */ + public SpdxCollectionException(String message, Throwable cause, + boolean enableSuppression, boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } + +} diff --git a/src/main/java/org/spdx/maven/SpdxDefaultFileInformation.java b/src/main/java/org/spdx/maven/SpdxDefaultFileInformation.java new file mode 100644 index 0000000..f1ebbae --- /dev/null +++ b/src/main/java/org/spdx/maven/SpdxDefaultFileInformation.java @@ -0,0 +1,101 @@ +/* + * Copyright 2014 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.spdx.maven; + +import org.spdx.rdfparser.DOAPProject; +import org.spdx.rdfparser.SPDXLicenseInfo; +import org.spdx.rdfparser.SpdxNoAssertionLicense; + +/** + * Simple structure to hold information obout default file information + * @author Gary O'Neall + * + */ +public class SpdxDefaultFileInformation { + + private SPDXLicenseInfo declaredLicense = new SpdxNoAssertionLicense(); + private String copyright = "NOASSERTION"; + private String notice = ""; + private String comment = ""; + private String[] contributors = new String[0]; + private DOAPProject[] artifactOf = new DOAPProject[0]; + private SPDXLicenseInfo concludedLicense = new SpdxNoAssertionLicense();; + private String licenseComment = ""; + + public SPDXLicenseInfo getDeclaredLicense() { + return this.declaredLicense; + } + + public void setDeclaredLicense(SPDXLicenseInfo license) { + this.declaredLicense = license; + } + + public String getCopyright() { + return this.copyright ; + } + + public void setCopyright(String copyright) { + this.copyright = copyright; + } + + public String getNotice() { + return this.notice; + } + + public void setNotice(String notice) { + this.notice = notice; + } + + public String getComment() { + return this.comment; + } + + public void setComment(String comment) { + this.comment = comment; + } + + public String[] getContributors() { + return this.contributors; + } + + public void setContributors(String[] contributors) { + this.contributors = contributors; + } + + public DOAPProject[] getArtifactOf() { + return this.artifactOf; + } + + public void setArtifactOf(DOAPProject[] projects) { + this.artifactOf = projects; + } + + public SPDXLicenseInfo getConcludedLicense() { + return this.concludedLicense; + } + + public void setConcludedLicense(SPDXLicenseInfo license) { + this.concludedLicense = license; + } + + public String getLicenseComment() { + return this.licenseComment; + } + + public void setLicenseComment(String licenseComment) { + this.licenseComment = licenseComment; + } +} diff --git a/src/main/java/org/spdx/maven/SpdxFileCollector.java b/src/main/java/org/spdx/maven/SpdxFileCollector.java new file mode 100644 index 0000000..652701e --- /dev/null +++ b/src/main/java/org/spdx/maven/SpdxFileCollector.java @@ -0,0 +1,352 @@ +/* + * Copyright 2014 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.spdx.maven; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.Charset; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + + +import org.spdx.rdfparser.DOAPProject; +import org.spdx.rdfparser.SPDXDocument; +import org.spdx.rdfparser.SPDXFile; +import org.spdx.rdfparser.SPDXLicenseInfo; +import org.spdx.rdfparser.SpdxPackageVerificationCode; +import org.spdx.rdfparser.SpdxRdfConstants; + +/** + * Collects SPDX file information from directories. + * + * The method collectFilesInDirectory(File directory) will scan and + * create SPDX File information for all files in the directory. + * + * File patterns can be passed to the constructor file files which should be ignored. + * + * @author Gary O'Neall + * + */ +public class SpdxFileCollector { + + // constants for mapping extensions to types. + //TODO: These static hashsets should be converted to using properties rather than constants + static HashSet SOURCE_EXTENSION = new HashSet(); + + static { + SOURCE_EXTENSION.add("C"); SOURCE_EXTENSION.add("H"); + SOURCE_EXTENSION.add("JAVA"); SOURCE_EXTENSION.add("CS"); + SOURCE_EXTENSION.add("JS"); SOURCE_EXTENSION.add("HH"); + SOURCE_EXTENSION.add("CC"); SOURCE_EXTENSION.add("CPP"); + SOURCE_EXTENSION.add("CXX"); SOURCE_EXTENSION.add("HPP"); + SOURCE_EXTENSION.add("ASP"); SOURCE_EXTENSION.add("BAS"); + SOURCE_EXTENSION.add("BAT"); SOURCE_EXTENSION.add("HTM"); + SOURCE_EXTENSION.add("HTML"); SOURCE_EXTENSION.add("LSP"); + SOURCE_EXTENSION.add("PAS"); SOURCE_EXTENSION.add("XML"); + SOURCE_EXTENSION.add("PAS"); SOURCE_EXTENSION.add("ADA"); + SOURCE_EXTENSION.add("VB"); SOURCE_EXTENSION.add("ASM"); + SOURCE_EXTENSION.add("CBL"); SOURCE_EXTENSION.add("COB"); + SOURCE_EXTENSION.add("F77"); SOURCE_EXTENSION.add("M3"); + SOURCE_EXTENSION.add("MK"); SOURCE_EXTENSION.add("MKE"); + SOURCE_EXTENSION.add("RMK"); SOURCE_EXTENSION.add("MOD"); + SOURCE_EXTENSION.add("PL"); SOURCE_EXTENSION.add("PM"); + SOURCE_EXTENSION.add("PRO"); SOURCE_EXTENSION.add("REX"); + SOURCE_EXTENSION.add("SM"); SOURCE_EXTENSION.add("ST"); + SOURCE_EXTENSION.add("SNO"); SOURCE_EXTENSION.add("PY"); + SOURCE_EXTENSION.add("PHP"); SOURCE_EXTENSION.add("CSS"); + SOURCE_EXTENSION.add("XSL"); SOURCE_EXTENSION.add("XSLT"); + SOURCE_EXTENSION.add("SH"); SOURCE_EXTENSION.add("XSD"); + SOURCE_EXTENSION.add("RB"); SOURCE_EXTENSION.add("RBX"); + SOURCE_EXTENSION.add("RHTML"); SOURCE_EXTENSION.add("RUBY"); + } + + static HashSet BINARY_EXTENSIONS = new HashSet(); + static { + BINARY_EXTENSIONS.add("EXE"); BINARY_EXTENSIONS.add("DLL"); + BINARY_EXTENSIONS.add("JAR"); BINARY_EXTENSIONS.add("CLASS"); + BINARY_EXTENSIONS.add("SO"); BINARY_EXTENSIONS.add("A"); + } + + static HashSet ARCHIVE_EXTENSIONS = new HashSet(); + static { + ARCHIVE_EXTENSIONS.add("ZIP"); ARCHIVE_EXTENSIONS.add("EAR"); + ARCHIVE_EXTENSIONS.add("TAR"); ARCHIVE_EXTENSIONS.add("GZ"); + ARCHIVE_EXTENSIONS.add("TGZ"); ARCHIVE_EXTENSIONS.add("BZ2"); + ARCHIVE_EXTENSIONS.add("RPM"); + } + + static final String SHA1_ALGORITHM = "SHA-1"; + static final String PACKAGE_VERIFICATION_CHARSET = "UTF-8"; + private static MessageDigest digest; + static { + try { + digest = MessageDigest.getInstance(SHA1_ALGORITHM); + } catch (NoSuchAlgorithmException e) { + digest = null; + }; + } + + + private SPDXDocument spdxDoc; + private Pattern[] excludedFilePatterns; + private SpdxDefaultFileInformation defaultFileInformation; + /** + * All licenses found within the files + */ + HashSet licensesFromFiles = new HashSet(); + /** + * Map of fileName, SPDXFile for all files in the SPDX document + */ + HashMap spdxFiles = new HashMap(); + + + /** + * SpdxFileCollector collects SPDX file information for files + * @param spdxDoc SPDX document containing any existing license information. Any new license created will be added to the SPDX document. + * @param excludedFilePatterns Array of patterns which, if a file name or directory name is matched, will be skipped. + * @param defaultFileInformation Information on default SPDX field data for the files + */ + public SpdxFileCollector(SPDXDocument spdxDoc, + Pattern[] excludedFilePatterns, + SpdxDefaultFileInformation defaultFileInformation) { + this.spdxDoc = spdxDoc; + this.excludedFilePatterns = excludedFilePatterns; + this.defaultFileInformation = defaultFileInformation; + } + + /** + * Collect file information in the directory (including subdirectories). + * @param directory + * @throws SpdxCollectionException + */ + public void collectFilesInDirectory(File directory) throws SpdxCollectionException { + if (isExcluded(directory.getName())) { + return; + } + if (!directory.isDirectory()) { + SPDXFile spdxFile = convertToSpdxFile(directory); + spdxFiles.put(directory.getPath(), spdxFile); + SPDXLicenseInfo[] seenLicenses = spdxFile.getSeenLicenses(); + for (int j = 0; j < seenLicenses.length; j++) { + licensesFromFiles.add(seenLicenses[j]); + } + return; + } + File[] children = directory.listFiles(); + for (int i = 0; i < children.length; i++) { + if (isExcluded(children[i].getName())) { + continue; + } + if (children[i].isDirectory()) { + collectFilesInDirectory(children[i]); + } else { + SPDXFile spdxFile = convertToSpdxFile(children[i]); + spdxFiles.put(directory.getPath(), spdxFile); + SPDXLicenseInfo[] seenLicenses = spdxFile.getSeenLicenses(); + for (int j = 0; j < seenLicenses.length; j++) { + licensesFromFiles.add(seenLicenses[j]); + } + } + } + } + + private SPDXFile convertToSpdxFile(File file) throws SpdxCollectionException { + String relativePath = file.getPath(); + String fileType = extensionToFileType(getExtension(file)); + String sha1 = generateSha1(file); + SPDXLicenseInfo license; + license = this.defaultFileInformation.getDeclaredLicense(); + String copyright = this.defaultFileInformation.getCopyright(); + String notice = this.defaultFileInformation.getNotice(); + String comment = this.defaultFileInformation.getComment(); + String[] contributors = this.defaultFileInformation.getContributors(); + DOAPProject[] artifactOf = this.defaultFileInformation.getArtifactOf(); + SPDXLicenseInfo concludedLicense = this.defaultFileInformation.getConcludedLicense(); + String licenseComment = this.defaultFileInformation.getLicenseComment(); + return new SPDXFile(relativePath, fileType, + sha1, concludedLicense, new SPDXLicenseInfo[] {license}, + licenseComment, copyright, artifactOf, comment, null, + contributors, notice); + } + + public String getExtension(File file) { + String fileName = file.getName(); + int lastDot = fileName.lastIndexOf('.'); + if (lastDot < 1) { + return ""; + } else { + return fileName.substring(lastDot+1); + } + } + + private static String extensionToFileType(String fileExtension) { + if (fileExtension == null) { + return SpdxRdfConstants.FILE_TYPE_OTHER; + } + String upperExtension = fileExtension.toUpperCase(); + if (SOURCE_EXTENSION.contains(upperExtension)) { + return SpdxRdfConstants.FILE_TYPE_SOURCE; + } else if (BINARY_EXTENSIONS.contains(upperExtension)) { + return SpdxRdfConstants.FILE_TYPE_BINARY; + } else if (ARCHIVE_EXTENSIONS.contains(upperExtension)) { + return SpdxRdfConstants.FILE_TYPE_ARCHIVE; + } else { + return SpdxRdfConstants.FILE_TYPE_OTHER; + } + } + + private boolean isExcluded(String fileName) { + for (int i = 0; i < excludedFilePatterns.length; i++) { + Matcher matcher = excludedFilePatterns[i].matcher(fileName); + if (matcher.matches()) { + return true; + } + } + return false; + } + + /** + * @return SPDX Files which have been acquired through the collectFilesInDirectory method + */ + public SPDXFile[] getFiles() { + return spdxFiles.values().toArray(new SPDXFile[spdxFiles.size()]); + } + + /** + * @return all license information used in the SPDX files + */ + public SPDXLicenseInfo[] getLicenseInfoFromFiles() { + return new SPDXLicenseInfo[licensesFromFiles.size()]; + } + + public SpdxPackageVerificationCode getVerificationCode(String spdxFileName) throws NoSuchAlgorithmException { + ArrayList excludedFileNamesFromVerificationCode = new ArrayList(); + + if (spdxFiles.containsKey(spdxFileName)) { + excludedFileNamesFromVerificationCode.add(spdxFileName); + } + SpdxPackageVerificationCode verificationCode; + verificationCode = calculatePackageVerificationCode(spdxFiles.values(), excludedFileNamesFromVerificationCode); + return verificationCode; + } + + /** + * Calculate the package verification code for a collection of SPDX files + * @param spdxFiles Files used to calculate the verification code + * @param excludedFileNamesFromVerificationCode List of file names to exclude + * @return + * @throws NoSuchAlgorithmException + */ + private SpdxPackageVerificationCode calculatePackageVerificationCode( + Collection spdxFiles, + ArrayList excludedFileNamesFromVerificationCode) throws NoSuchAlgorithmException { + ArrayList fileChecksums = new ArrayList(); + Iterator iter = spdxFiles.iterator(); + while (iter.hasNext()) { + SPDXFile file = iter.next(); + if (includeInVerificationCode(file.getName(), excludedFileNamesFromVerificationCode)) { + fileChecksums.add(file.getSha1()); + } + } + Collections.sort(fileChecksums); + MessageDigest verificationCodeDigest = MessageDigest.getInstance("SHA-1"); + for (int i = 0;i < fileChecksums.size(); i++) { + byte[] hashInput = fileChecksums.get(i).getBytes(Charset.forName("UTF-8")); + verificationCodeDigest.update(hashInput); + } + String value = convertChecksumToString(verificationCodeDigest.digest()); + return new SpdxPackageVerificationCode(value, excludedFileNamesFromVerificationCode.toArray( + new String[excludedFileNamesFromVerificationCode.size()])); + } + + private boolean includeInVerificationCode(String name, ArrayList excludedFileNamesFromVerificationCode) { + for (int i = 0; i < excludedFileNamesFromVerificationCode.size(); i++) { + if (excludedFileNamesFromVerificationCode.get(i).equals(name)) { + return false; + } + } + return true; + } + + /** + * Converts an array of bytes to a string compliant with the SPDX sha1 representation + * @param digestBytes + * @return + */ + public static String convertChecksumToString(byte[] digestBytes) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < digestBytes.length; i++) { + String hex = Integer.toHexString(0xff & digestBytes[i]); + if (hex.length() < 2) { + sb.append('0'); + } + sb.append(hex); + } + return sb.toString(); + } + + /** + * Generate the Sha1 for a given file. Must have read access to the file. + * @param file + * @return + * @throws SpdxCollectionException + */ + public static String generateSha1(File file) throws SpdxCollectionException { + if (digest == null) { + try { + digest = MessageDigest.getInstance(SHA1_ALGORITHM); + } catch (NoSuchAlgorithmException e) { + throw(new SpdxCollectionException("Unable to create the message digest for generating the File SHA1")); + } + } + digest.reset(); + InputStream in; + try { + in = new FileInputStream(file); + } catch (IOException e1) { + throw(new SpdxCollectionException("IO getting file content while calculating the SHA1")); + } + try { + byte[] buffer = new byte[2048]; + int numBytes = in.read(buffer); + while (numBytes >= 0) { + digest.update(buffer, 0, numBytes); + numBytes = in.read(buffer); + } + return convertChecksumToString(digest.digest()); + } catch (IOException e) { + throw(new SpdxCollectionException("IO error reading file input stream while calculating the SHA1")); + } finally { + try { + if (in != null) { + in.close(); + } + } catch (IOException e) { + throw(new SpdxCollectionException("IO error closing file input stream while calculating the SHA1")); + } + } + } +} diff --git a/src/main/java/org/spdx/maven/SpdxProjectInformation.java b/src/main/java/org/spdx/maven/SpdxProjectInformation.java new file mode 100644 index 0000000..6fdabc2 --- /dev/null +++ b/src/main/java/org/spdx/maven/SpdxProjectInformation.java @@ -0,0 +1,245 @@ +/* + * Copyright 2014 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.spdx.maven; + +import org.apache.maven.plugin.logging.Log; +import org.spdx.rdfparser.SPDXLicenseInfo; +import org.spdx.rdfparser.SpdxNoAssertionLicense; + +/** + * Simple structure to hold information about SPDX project + * @author Gary O'Neall + * + */ +class SpdxProjectInformation { + String[] creators = new String[0]; + String creatorComment = ""; + SPDXLicenseInfo concludedLicense = new SpdxNoAssertionLicense(); + SPDXLicenseInfo declaredLicense = new SpdxNoAssertionLicense(); + String description; + String downloadUrl; + String homePage; + String shortDescription; + String originator; + String supplier; + String packageArchiveFileName; + String versionInfo; + String licenseComment; + String sha1; + String name; + /** + * @return the sha1 + */ + public String getSha1() { + return sha1; + } + /** + * @param sha1 the sha1 to set + */ + public void setSha1(String sha1) { + this.sha1 = sha1; + } + /** + * @return the concludedLicense + */ + public SPDXLicenseInfo getConcludedLicense() { + return concludedLicense; + } + /** + * @param concludedLicense the concludedLicense to set + */ + public void setConcludedLicense(SPDXLicenseInfo concludedLicense) { + this.concludedLicense = concludedLicense; + } + /** + * @return the declaredLicense + */ + public SPDXLicenseInfo getDeclaredLicense() { + return declaredLicense; + } + /** + * @param declaredLicense the declaredLicense to set + */ + public void setDeclaredLicense(SPDXLicenseInfo declaredLicense) { + this.declaredLicense = declaredLicense; + } + /** + * @return the description + */ + public String getDescription() { + return description; + } + /** + * @param description the description to set + */ + public void setDescription(String description) { + this.description = description; + } + /** + * @return the downloadUrl + */ + public String getDownloadUrl() { + return downloadUrl; + } + /** + * @param downloadUrl the downloadUrl to set + */ + public void setDownloadUrl(String downloadUrl) { + this.downloadUrl = downloadUrl; + } + /** + * @return the homePage + */ + public String getHomePage() { + return homePage; + } + /** + * @param homePage the homePage to set + */ + public void setHomePage(String homePage) { + this.homePage = homePage; + } + /** + * @return the shortDescription + */ + public String getShortDescription() { + return shortDescription; + } + /** + * @param shortDescription the shortDescription to set + */ + public void setShortDescription(String shortDescription) { + this.shortDescription = shortDescription; + } + /** + * @return the originator + */ + public String getOriginator() { + return originator; + } + /** + * @param originator the originator to set + */ + public void setOriginator(String originator) { + this.originator = originator; + } + /** + * @return the supplier + */ + public String getSupplier() { + return supplier; + } + /** + * @param supplier the supplier to set + */ + public void setSupplier(String supplier) { + this.supplier = supplier; + } + /** + * @return the packageArchiveFileName + */ + public String getPackageArchiveFileName() { + return packageArchiveFileName; + } + /** + * @param packageArchiveFileName the packageArchiveFileName to set + */ + public void setPackageArchiveFileName(String packageArchiveFileName) { + this.packageArchiveFileName = packageArchiveFileName; + } + /** + * @return the versionInfo + */ + public String getVersionInfo() { + return versionInfo; + } + /** + * @param versionInfo the versionInfo to set + */ + public void setVersionInfo(String versionInfo) { + this.versionInfo = versionInfo; + } + /** + * @return the licenseComment + */ + public String getLicenseComment() { + return licenseComment; + } + /** + * @param licenseComment the licenseComment to set + */ + public void setLicenseComment(String licenseComment) { + this.licenseComment = licenseComment; + } + /** + * @return the creators + */ + public String[] getCreators() { + return creators; + } + /** + * @param creators the creators to set + */ + public void setCreators(String[] creators) { + this.creators = creators; + } + /** + * @return the creatorComment + */ + public String getCreatorComment() { + return creatorComment; + } + /** + * @param creatorComment the creatorComment to set + */ + public void setCreatorComment(String creatorComment) { + this.creatorComment = creatorComment; + } + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + /** + * Log information on all fields - typically used for debugging + * @param log + */ + public void logInfo(Log log) { + log.info("SPDX Project Name: "+this.getName()); + log.info("SPDX Creator comment: "+this.getCreatorComment()); + log.info("SPDX Description: "+this.getDescription()); + log.info("SPDX License comment: "+this.getLicenseComment()); + log.info("SPDX Originator: "+this.getOriginator()); + log.info("SPDX PackageArchiveFileName: "+this.getPackageArchiveFileName()); + log.info("SPDX SHA1: "+this.getSha1()); + log.info("SPDX Short description: "+this.getShortDescription()); + log.info("SPDX Supplier: "+this.getSupplier()); + log.info("SPDX Version info: "+this.getVersionInfo()); + log.info("SPDX Concluded license: "+this.getConcludedLicense().toString()); + log.info("SPDX Declared license: "+this.getDeclaredLicense().toString()); + log.info("SPDX Download URL: "+this.getDownloadUrl()); + log.info("SPDX Home page: "+this.getHomePage()); + String[] creators = this.getCreators(); + if (creators != null) { + for (int i = 0; i < creators.length; i++) { + log.info("SPDX Creator: "+creators[i]); + } + } + } +} diff --git a/src/test/java/TestSpdxFileCollector.java b/src/test/java/TestSpdxFileCollector.java new file mode 100644 index 0000000..12595f8 --- /dev/null +++ b/src/test/java/TestSpdxFileCollector.java @@ -0,0 +1,91 @@ +import static org.junit.Assert.*; + +import java.io.File; +import java.util.regex.Pattern; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.spdx.maven.SpdxDefaultFileInformation; +import org.spdx.maven.SpdxFileCollector; +import org.spdx.rdfparser.InvalidSPDXAnalysisException; +import org.spdx.rdfparser.SPDXDocument; + +import com.hp.hpl.jena.rdf.model.Model; +import com.hp.hpl.jena.rdf.model.ModelFactory; + + +public class TestSpdxFileCollector { + + + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + } + + @AfterClass + public static void tearDownAfterClass() throws Exception { + } + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testSpdxFileCollector() { + //TODO: Implement test + } + + @Test + public void testCollectFilesInDirectory() { + //TODO: Implement test + } + + @Test + public void testGetExtension() throws InvalidSPDXAnalysisException { + Model model = ModelFactory.createDefaultModel(); + SPDXDocument spdxDoc = new SPDXDocument(model); + SpdxFileCollector collector = new SpdxFileCollector(spdxDoc, + new Pattern[] {}, new SpdxDefaultFileInformation()); + File noExtension = new File("noextension"); + String result = collector.getExtension(noExtension); + assertTrue(result.isEmpty()); + String ext = "abcd"; + File abcd = new File("fileName" + "." + ext); + result = collector.getExtension(abcd); + assertEquals(ext, result); + File startsWithDot = new File(".configfile"); + result = collector.getExtension(startsWithDot); + assertTrue(result.isEmpty()); + File multipleDots = new File ("file.with.more.dots."+ext); + result = collector.getExtension(multipleDots); + assertEquals(ext, result); + } + + @Test + public void testGetFiles() { + //TODO: Implement test + } + + @Test + public void testGetLicenseInfoFromFiles() { + //TODO: Implement test + } + + @Test + public void testGetVerificationCode() { + //TODO: Implement test + } + + @Test + public void testConvertChecksumToString() { + //TODO: Implement test + } + +}