| // Copyright (C) 2019 The Android Open Source Project |
| // |
| // 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 com.googlesource.gerrit.plugins.copyright.lib; |
| |
| import static java.nio.charset.StandardCharsets.UTF_8; |
| |
| import com.google.common.annotations.VisibleForTesting; |
| import com.google.common.base.Joiner; |
| import com.google.common.collect.ImmutableList; |
| import com.google.common.collect.ImmutableMap; |
| import com.google.common.hash.Hashing; |
| import java.util.NoSuchElementException; |
| import org.apache.commons.lang.StringUtils; |
| |
| /** Constants declaring match patterns for common copyright licenses and owners. */ |
| public abstract class CopyrightPatterns { |
| |
| // No instances |
| private CopyrightPatterns() {} |
| |
| // All of the MAX parameters below have been chosen empirically similar to MATCH_SEARCH_LENGTH to |
| // minimize computing cost while still catching virtually all of the important matches. |
| |
| /** Maximum length of consecutive text characters to match. */ |
| public static final int MAX_NAME_LENGTH = 30; |
| /** Maximum number of potential names to match. */ |
| public static final int MAX_NAME_REPETITION = 35; |
| /** Maximum length of consecutive space/comment characters to match. */ |
| public static final int MAX_SPACE_LENGTH = 47; |
| /** Maximum repetition of potential dates to match. Might have to revisit this in future. */ |
| public static final int MAX_DATE_REPETITION = 30; |
| |
| /** Regular expression matching whitespace or a comment character. */ |
| public static final String WS = "[\\p{Z}\\s*/#ᤦ ]"; |
| /** Regular expression matching whitespace, a comment character, or punctuation. */ |
| public static final String WSPCT = "[-,;.\\p{Z}\\s*/#ᤦ ]"; |
| /** Regular expression matching a text character. */ |
| public static final String NAME_CHAR = "[-\\p{L}\\p{N}]"; // \p{L}->letter, \p{N}->numeral |
| /** Regular expression matching an UPPER CASE text character. */ |
| public static final String UPPER_CHAR = "\\p{Lu}"; |
| /** Regular expression matching a lower case text character. */ |
| public static final String LOWER_CHAR = "\\p{Ll}"; |
| /** Regular expression matching an email character. */ |
| public static final String EMAIL_CHAR = "[-.\\p{L}\\p{N}_]"; |
| /** Regular expression matching a URL character. */ |
| public static final String URL_CHAR = "[-.\\p{L}\\p{N}_=%+]"; |
| /** Regular experssion matching a web address. */ |
| public static final String URL = |
| "https?[:]/(?:[/?&]" // http://example.com/path/?var=val&var=val |
| + URL_CHAR |
| + "{1," |
| + MAX_NAME_LENGTH |
| + "}){1,25}" |
| + "|www[.]" // www.domain or www.domain/path |
| + URL_CHAR |
| + "{1," |
| + MAX_NAME_LENGTH |
| + "}(?:[.]com|[.]net|[.]org|[.]\\p{L}\\p{L})(?:[/?&#]" |
| + URL_CHAR |
| + "{0," |
| + MAX_NAME_LENGTH |
| + "}){0,25}"; |
| /** Regular expression matching a text or email address. */ |
| public static final String NAME = |
| "(?:(?:" |
| + URL // web address |
| + "|[\\p{L}\\p{N}]" // regular text |
| + NAME_CHAR |
| + "{0,mnl}\\b" |
| + "|[<]?[\\p{L}\\p{N}]" // email@domain or <email@domain> |
| + EMAIL_CHAR |
| + "{1,mnl}[@][\\p{L}\\p{N}]" |
| + EMAIL_CHAR |
| + "{1,mnl}\\b[>]?" |
| + "|\\b\\p{N}{1,2}(?:[.]\\p{N}{1,2}){1,5}\\b" // version number |
| + "|\\p{Pi}[^\\p{Pf}]{0,65}\\p{Pf}" // quoted string |
| + "|(?-i:\\p{Lu}[-.]){1,5}" // Initials A.G. or S.A. etc. \\p{Lu} -> uppercase letter |
| + "|" // domain text |
| + EMAIL_CHAR |
| + "{1,mnl}(?:[.]com|[.]org|[.]net|[.]\\p{L}\\p{L})" |
| + ")[,;:]?)"; // punctuation following text |
| /** Regular expression matching an UPPERCASE text. */ |
| public static final String UPPER_NAME = "(?-i:\\b" + UPPER_CHAR + "{1," + MAX_NAME_LENGTH + "})"; |
| /** Regular expression matching a Proper Case text. */ |
| public static final String PROPER_NAME = |
| "(?-i:\\b" + UPPER_CHAR + LOWER_CHAR + "{0," + MAX_NAME_LENGTH + "})"; |
| /** Regular expression matching any text, email address, or quote character. */ |
| public static final String ANY_CHAR = "[-.,\\p{L}\\p{N}]"; |
| /** Regular expression matching any text, email address, or quoted string. */ |
| public static final String ANY_WORD = "(?:" + ANY_CHAR + "{1," + MAX_NAME_LENGTH + "})"; |
| |
| /** Academic Freedom License Version 2.1 */ |
| public static final Rule AFL2_1 = |
| license( |
| ImmutableList.of( |
| ".*SPDX-License-Identifier: AFL-2[.]1", |
| "<license> <name> ?AFL-2[.]1 ?</name>.*", |
| "Academic Free License 2[.]1")); |
| |
| /** Academic Freedom License Version 3.0 */ |
| public static final Rule AFL3_0 = |
| license( |
| ImmutableList.of( |
| ".*SPDX-License-Identifier: AFL-3[.]0", |
| "<license> <name> ?AFL-3[.]0 ?</name>.*", |
| "Academic Free Licen[cs]e 3[.]0")); |
| |
| /** Affero General Public License */ |
| public static final Rule AGPL = |
| license( |
| ImmutableList.of( |
| // "Affero" appears thrice in GPL 3.0 -- match to exclude below. |
| "Use with the GNU Affero General Public License[.]?", |
| "link or combine any covered work with a work licensed under version 3 of the GNU" |
| + " Affero General Public License into a single combined work[,.;:]?", |
| "but the special requirements of the GNU Affero General Public License,?", |
| // "Affero" appears in Mozilla Public License (MPL) -- match to exclude below. |
| "means either the GNU General Public License,?" |
| + " Version 2[.]0,? the GNU Lesser General Public License,?" |
| + " Version 2[.]1,? the GNU Affero General Public License,?", |
| // Otherwise, any occurrence of "Affero" suggests AGPL. |
| "Affero"), |
| ImmutableList.of( |
| // "Affero" appears thrice in GPL 3.0 |
| "Use with the GNU Affero General Public License[.]?", |
| "link or combine any covered work with a work licensed under version 3 of the GNU" |
| + " Affero General Public License into a single combined work[,.;:]?", |
| "but the special requirements of the GNU Affero General Public License,?", |
| // "Affero" appears in Mozilla Public License (MPL) |
| "means either the GNU General Public License,?" |
| + " Version 2[.]0,? the GNU Lesser General Public License,?" |
| + " Version 2[.]1,? the GNU Affero General Public License,?")); |
| |
| /** Android owned or licensed */ |
| public static final Rule ANDROID = |
| new Rule( |
| ImmutableList.of("Android(?:-x86)? Open(?: |-)Source Project", "LK Trusty Authors"), |
| ImmutableList.of("Android Software Development Kit Licen[cs]e Agreement")); |
| |
| /** Apache Software License 1.1 */ |
| public static final Rule APACHE1_1 = |
| license( |
| ImmutableList.of( |
| ".*SPDX-License-Identifier: Apache-1[.]1?", |
| "<license> <name> ?Apache(?: Software)?(?: Public)?(?: Licen[cs]e)?,?" |
| + "(?: |-)1[.]1 ?</name>.*", |
| "<license> <name> ?(?:The )?Apache(?: Software)?(?: Public)?" |
| + " Licen[cs]e,? Version 1[.]1 ?</name>.*", |
| "http://www[.]apache[.]org/licenses/LICENSE-1[.]1", |
| "(?:the )?Apache 1[.]1 Licen[cs]e", |
| ".*Licen[cs]ed under (?:both )?(?:the )?Apache Licen[cs]e,? version 1[.]1", |
| ".+Licen[cs]ed under (?:both )?(?:the )?Apache Licen[cs]e v1[.]1", |
| ".+licen[cs]ed under (?:the )?Apache 1[.]1", |
| "(?:the )?Apache(?: Software)?(?: Public)? Licen[cs]e,? Version 1[.]1", |
| "(?:the )?Apache(?: Software)?(?: Public)? Licen[cs]e,? v1[.]1", |
| "^terms of the Apache 1[.]1 licen[cs]e")); |
| |
| /** Apache 2 owned or licensed */ |
| public static final Rule APACHE2 = |
| new Rule( |
| ImmutableList.of( |
| "(?:by )?(?:The )?Apache Software Foundation.?", |
| "Apache Software Foundation.?" |
| + " This product includes software developed" |
| + " (?:by|at) The Apache Software Foundation"), |
| ImmutableList.of( |
| ".*SPDX-License-Identifier: Apache-2[.]?[0]?", |
| "<license> <name> ?Apache(?: Software)?(?: Public)?(?: Licen[cs]e)?,?" |
| + "(?: |-)2[.]?[0]? ?</name>.*", |
| "<license> <name> ?(?:The )?Apache(?: Software)?(?: Public)?" |
| + " Licen[cs]e,? Version 2[.]?[0]? ?</name>.*", |
| "https?://www[.]apache[.]org/licenses/LICENSE-2[.]0", |
| "Apache 2[.]?[0]? Licen[cs]e", |
| ".*Licen[cs]ed under (?:both )?(?:the )?Apache Licen[cs]e,?(?: version 2[.]?0?)?", |
| ".+Licen[cs]ed under (?:both )?(?:the )?Apache Licen[cs]e v2[.]?(?:[\\p{L}\\p{N}]+)?", |
| ".+licen[cs]ed under (?:the )?Apache 2[.]?", |
| ".+licen[cs]es this file to you under (?:the )?Apache Licen[cs]e,?", |
| "Apache(?: Software)?(?: Public)? Licen[cs]e,? Version 2[.]?[0]?", |
| "^apache2(?:-android)?", |
| "^the apache licen[cs]e", |
| "^terms of the Apache 2[.]?[0]? licen[cs]e", |
| ".+under the terms of (?:either )the Apache Licen[cs]e[,.;]?"), |
| ImmutableList.of("owner as \\p{Pi}?Not a Contribution[.,;:]{0,3}\\p{Pf}?")); |
| |
| /** The Artistic License version 1 or 2 */ |
| public static final Rule ARTISTIC_LICENSE = |
| license( |
| ImmutableList.of( |
| ".*SPDX-License-Identifier: Artistic-[12][.]?[0]?", |
| "<license> <name> ?Artistic-[12][.]?[0]? ?</name>.*", |
| "(?:The )?\\p{Pi}?Artistic Licen[cs]e\\p{Pf}?(?: [12][.]?[0]?)?")); |
| |
| /** The BEER-WARE License */ |
| public static final Rule BEER_WARE = license(ImmutableList.of("\\bTHE BEER-WARE LICEN[CS]E")); |
| |
| /** BSD licensed */ |
| public static final Rule BSD = |
| license( |
| ImmutableList.of( |
| "<license> <name> ?BSD \\p{N}-clause(?: License)? ?</name>.*", |
| "<license> <name> ?BSD(?: |-)style(?: License)? ?</name>.*", |
| "<license> <name> ?(?:New )?BSD(?: New)?(?: Licen[cs]e)? ?</name>.*", |
| "<license> <name> ?Berkeley Software Distribution [(]BSD[)] Licen[cs]e ?</name>.*", |
| ".*SPDX-License-Identifier: BSD-2-Clause", |
| ".*SPDX-License-Identifier: BSD-2-Clause-FreeBSD", |
| ".*SPDX-License-Identifier: BSD-3-Clause", |
| ".*SPDX-License-Identifier: BSD-4-Clause", |
| "^BSD(?:[.]|, see LICEN[CS]E for (?:more )details[.])?", |
| ".*under the terms and conditions of the BSD Licen[cs]e.*", |
| ".*(?:\\p{N}-clause |a )?BSD (?:\\p{N}-clause )?licen[cs]e.*", |
| ".*Redistribution and use in source and binary forms,? with or without modification,?" |
| + " are permitted provided that the following conditions are met[:]?", |
| ".*This header is BSD licen[cs]ed so anyone can use the definitions to implement" |
| + " compatible drivers servers[.:]?.*", |
| ".*Redistribution and use is allowed according to the terms of the" |
| + " (?:\\p{N}-clause )?BSD licen[cs]e[.:]?.*", |
| ".*(?:[-\\p{L}\\p{N}] )?redistributions (?:of|in) source code must retain the" |
| + " (?:(?:above|accompanying) )?copyright notice(?: unmodified)?[,.:;]? this list" |
| + " of conditions[,.;:]? and the following disclaimers?[,.;:]?" |
| + " (?:[-\\p{L}\\p{N}] )?redistributions (?:in|of) binary form must reproduce the" |
| + " (?:above|accompanying) copyright notice[,.;:]? this list of conditions[,.:;]?" |
| + " and the following disclaimer in the documentation[,.;:]? and(?: |[/])or other" |
| + " materials(?: provided with the distribution)?[,.:;]{0,3}")); |
| |
| /** The Boost Software License */ |
| public static final Rule BSL1_0 = |
| license( |
| ImmutableList.of( |
| ".*SPDX-License-Identifier: BSL-1[.]?0?", |
| "<license> <name> ?Boost(?:,? Version 1[.]?0?)? ?</name>.*", |
| "<license> <name> ?Boost Software License(?:,? Version 1[.]?0?)? ?</name>.*", |
| "<license> <name> ?BSL-1[.]?0? ?</name>.*", |
| "https?://www[.]boost[.]org/LICENSE_1_0[.]txt(?: [(]?Boost license[)]?)?", |
| "Boost Software License 1[.]?0?.*", |
| ".*(?:The )?Boost Software License(?:,| ?-)?(?: Version 1[.]?0?)?")); |
| |
| /** Creative Commons Public Domain-like License */ |
| public static final Rule CC0 = |
| license( |
| ImmutableList.of( |
| "<license> <name> ?CC0 ?</name>.*", |
| "https?://[\\p{L}\\p{N}.]*creativecommons[.]org/publicdomain/zero(?:/[\\p{N}.]*)?", |
| "To the extent possible under law[,;:]? the person who associated CC0 with this code" |
| + " has waived all copyright and related or neighboring rights to this code[.]?", |
| "To the greatest extent permitted by,? but not in contravention of,? applicable law,?" |
| + " Affirmer hereby overtly,? fully,? permanently,? irrevocably and" |
| + " unconditionally waives,? abandons,? and surrenders all of Affirmer'?s" |
| + " Copyright and Related Rights and associated claims and causes of action,?" |
| + " whether (?:now )?known or unknown", |
| "Affirmer hereby grants to each affected person a royalty-?free,?" |
| + " non(?: |-)?transferable,? non(?: |-)?sublicensable,? non(?: |-)?exclusive,?" |
| + " irrevocable,? and unconditional license to exercise Affirmer'?s Copyright" |
| + " and Related Rights in the Work")); |
| |
| /** Creative Commons Attribution -- allows commercial */ |
| public static final Rule CC_BY_C = |
| license( |
| ImmutableList.of( |
| "\\bhttps?://[\\p{L}\\p{N}.]*creativecommons[.]org/licen[cs]es/by[-\\p{L}\\p{N}.]*", |
| "(?-i:\\bAttribution(?:-(?:Share ?Alike|NoDerivs)){0,2} )")); |
| |
| /** Creative Commons Non-Commercial License */ |
| public static final Rule CC_BY_NC = |
| license( |
| ImmutableList.of( |
| "\\bhttps?://[\\p{L}\\p{N}.]*creativecommons[.]org/licenses/by" |
| + "(?:-nd)?(?:-sa)?-nc[-/\\p{L}\\p{N}.]*", |
| "\\bAttribution(?:-NoDerivs)?(?:-Share ?Alike)?" |
| + "-NonCommercial(?:-NoDerivs)?(?:-Share ?Alike)?")); |
| |
| /** Clang/LLVM License (NCSA version of MIT) */ |
| public static final Rule CLANG_LLVM = |
| license( |
| ImmutableList.of( |
| "This file is dual licensed under the MIT and the University of Illinois Open" |
| + " Source Licenses[,.;:]?", |
| "to deal with the Software without restriction,? including without limitation")); |
| |
| /** Commons Clause License */ |
| public static final Rule COMMONS_CLAUSE = license(ImmutableList.of("\\bCommons Clause")); |
| |
| /** Common Public Attribution License */ |
| public static final Rule CPAL = |
| license(ImmutableList.of("\\bCommon Public Attribution Licen[cs]e")); |
| |
| /** Eclipse Distribution License (basically BSD 3-clause plus below) */ |
| public static final Rule EDL = |
| license( |
| ImmutableList.of( |
| "https?://www[.]eclipse[.]org/org/documents/edl-v10[.]php", |
| "Eclipse Distribution Licen[cs]e(?: -)? v? ?1[.]0")); |
| |
| /** Eclipse Public License */ |
| public static final Rule EPL = |
| license( |
| ImmutableList.of( |
| "<license> <name> ?Eclipse Public Licen[cs]e" |
| + "(?: -)?(?: (?:v ?|version )?1[.]?[0]?)? ?</name>.*", |
| "^Eclipse Public Licen[cs]e[.]?", |
| ".*under (?:(?:the|this) )?(?:terms of )?(?:the )?eclipse" |
| + " (?:public )?licen[cs]e[,.;:]?.*", |
| ".*terms of (?:(?:the|this) )?eclipse public licen[cs]e[,.;:]?.*")); |
| |
| /** European Union Public License */ |
| public static final Rule EUPL = license(ImmutableList.of(" [(]?EUPL[)]? ")); |
| |
| /** Appears in tests similar to using example.com as a test domain */ |
| public static final Rule EXAMPLES = owner(ImmutableList.of("Your Company[.]?")); |
| |
| /** FreeType Project License */ |
| public static final Rule FTL = |
| new Rule( |
| ImmutableList.of("The FreeType ProjectI(?: [(]?www[.]freetype[.]org[)]?)[,;:.]?"), |
| ImmutableList.of( |
| ".*SPDX-License-Identifier: FTL", |
| "<license> <name> ?(?:The )?Freetype Project ?</name>.*", |
| "<license> <name> ?FTL ?</name>.*", |
| "This license was inspired by the BSD,? Artistic,? and IJG [(]?Independent JPEG" |
| + " Group[)]? licenses,? which all encourage inclusion and use of free software" |
| + " in commercial and freeware products alike[,;:.]?", |
| "you must acknowledge somewhere in your documentation that you have used the FreeType" |
| + " code[.;:.]?", |
| "The FreeType Project LICENSE", |
| "The FreeType Project is distributed in several archive packages[,;.:]?", |
| "This file is part of the FreeType project,? and may only be used,? modified,? and" |
| + " distributed under the terms of the FreeType project license[,.;:]?")); |
| |
| /** Google owned */ |
| public static final Rule GOOGLE = owner(ImmutableList.of("Google,? Inc[.]?", "Google LLC")); |
| |
| /** Generic GNU General Public License */ |
| public static final Rule GPL = |
| license( |
| ImmutableList.of( |
| "\\bIn addition to the permissions in the GNU General Public License[,.;:]?", |
| "See the [\\[]?GNU[\\]]? General Public Licen[cs]e for more details[,.;:]?", |
| "\\bGNU General Public Licen[cs]e", |
| ".*gnu (?:library|lesser) general public licen[cs]e.*"), |
| ImmutableList.of( |
| "See the [\\[]?GNU[\\]]? General Public Licen[cs]e for more details[,.;:]?", |
| "In addition to the permissions in the GNU General Public License[,.;:]?")); |
| |
| /** GNU General Public License v2 */ |
| public static final Rule GPL2 = |
| license( |
| ImmutableList.of( |
| "<license> <name> ?GNU General Public License, Version 2 ?</name>.*", |
| "<license> <name> ?The GPLv2 License ?</name>.*", |
| "<license> <name> ?GPLv2 ?</name>.*", |
| ".*SPDX-License-Identifier: GPL-2.0[+]?", |
| ".*SPDX-License-Identifier: GPL-2.0-only", |
| ".*SPDX-License-Identifier: GPL-2.0-or-later", |
| ".*[\\[]?GNU[\\]]? GPL[,;]? version 2[,.;:]?.*", |
| ".*[\\[]?GNU[\\]]? General Public Licen[cs]e[,;]? version 2[,.;:]?.*", |
| "See the [\\[]?GNU[\\]]? General Public Licen[cs]e for more details[,.;:]?", |
| "You should have received a copy of the [\\[]?GNU[\\]]? General Public Licen[cs]e", |
| ".*[\\[]?GNU[\\]]? General Public Licen[cs]e as published by the Free Software" |
| + " Foundation?(?:[']s)?[,.;:]? (?:either )?version 2.*"), |
| ImmutableList.of( |
| "See the [\\[]?GNU[\\]]? General Public Licen[cs]e for more details[,.;:]?", |
| "In addition to the permissions in the GNU General Public License[,.;:]?")); |
| |
| /** GNU General Public License v3 */ |
| public static final Rule GPL3 = |
| license( |
| ImmutableList.of( |
| "<license> <name> ?GPLv3 ?</name>.*", |
| ".*SPDX-License-Identifier: GPL-3.0[+]?", |
| ".*[\\[]?GNU[\\]]? GPL[,;]? version 3[,.;:]?.*", |
| ".*[\\[]?GNU[\\]]? General Public Licen[cs]e[,;]? version 3[,.;:]?.*", |
| "See the [\\[]?GNU[\\]]? General Public Licen[cs]e for more details[,.;:]?", |
| "You should have received a copy of the [\\[]?GNU[\\]]? General Public Licen[cs]e", |
| ".*[\\[]?GNU[\\]]? General Public Licen[cs]e as published by the Free Software" |
| + " Foundation?(?:[']s)?[,.;:]? (?:either )?version 3.*"), |
| ImmutableList.of( |
| "See the [\\[]?GNU[\\]]? General Public Licen[cs]e for more details[,.;:]?", |
| "In addition to the permissions in the GNU General Public License[,.;:]?")); |
| |
| /** The ISC License */ |
| public static final Rule ISC = |
| license( |
| ImmutableList.of( |
| "<license> <name> ?(?:The )?ISC(?: Licen[cs]e)? ?</name>.*", |
| ".*SPDX-License-Identifier: ISC", |
| "https?://(?:www[.])?spdx[.]org/licenses/ISC", |
| "(?:The )?ISC Licen[cs]e", |
| "Files that are completely new have a Google copyright and an ISC license[,;:.]?", |
| "ISC license used for completely new code in BoringSSL[,.;:]?", |
| "this file is available under an ISC license[,;:.]?", |
| "ISC")); |
| |
| /** The JSON License (MIT plus the sentence below) */ |
| public static final Rule JSON = |
| license(ImmutableList.of("The Software shall be used for Good,? not Evil[.]?")); |
| |
| /** GNU Lessor or Library General Public License */ |
| public static final Rule LGPL = |
| license( |
| ImmutableList.of( |
| "<license> <name> ?GNU (?:Lesser|Library) General Public License ?</name>.*", |
| ".*SPDX-License-Identifier: LGPL.*", |
| ".*LGPL.*", |
| ".*gnu (?:library|lesser) general public licen[cs]e.*")); |
| |
| /** LibTIFF Library */ |
| public static final Rule LIBTIFF = |
| license( |
| ImmutableList.of( |
| "<license> <name> ?libtiff(?: license)? ?</name>.*", |
| ".*SPDX-License-Identifier: libtiff", |
| "https?://(?:www[.])?fedoraproject[.]org/wiki/Licensing/libtiff", |
| "Permission to use,? copy,? modify,? distribute,? and sell this software and its" |
| + " documentation for any purpose is hereby granted without fee,? provided that" |
| + " [(]i[)] the above copyright notices and this permission notice appear in all" |
| + " copies of the software and related documentation,? and [(]ii[)] the names of" |
| + " Sam Leffler and Silicon Graphics may not be used in any advertising")); |
| |
| /** Lucent Public License v 1.02 */ |
| public static final Rule LPL1_02 = |
| license( |
| ImmutableList.of( |
| "<license> <name> ?LPL-1[.]02 ?</name>.*", |
| ".*SPDX-License-Identifier: LPL-1[.]02", |
| "https?://plan9[.]bell-labs[.]com/plan9dist/license[.]html", |
| "https?://(?:www[.])?opensource[.]org/licenses/LPL-1[.]02", |
| "This software is (?:also )?made available under the Lucent Public License,? version" |
| + " 1[.]02", |
| "Lucent Public License,? version 1[.]02", |
| "Lucent Public License v1[.]02")); |
| |
| /** MIT licensed */ |
| public static final Rule MIT = |
| license( |
| ImmutableList.of( |
| "<license> <name> ?(?:The )?MIT Licen[cs]e(?: [(]MIT[)])? ?</name>.*", |
| "<license> <name> ?MIT ?</name>.*", |
| ".*SPDX-License-Identifier: MIT", |
| "http://www.opensource.org/licenses/mit-license.php", |
| "^the mit licen[cs]e(?:[:] http://www.opensource.org/licenses/mit-license.php)?", |
| "^MIT licen[cs]e[,.;:]? http://www.ibiblio.org/pub/Linux/LICENSE", |
| ".*under (?:(?:the|this) )?(?:terms of )?(?:the )?mit" |
| + " (?:open source )?licen[cs]e[,.;:]?.*", |
| ".*MIT licen[cs]ed", |
| ".*terms of (?:(?:the|this) )?mit licen[cs]e[,.;:]?.*", |
| ".*this code is licen[cs]ed under the mit licen[cs]e[,;.:]?.*", |
| ".*the mit or psf open source licen[cs]es[,.]?.*", |
| ".*Dual licen[cs]ed under the MIT or.*", |
| ".*Use of this software is governed by the MIT licen[cs]e[,.;:]?.*", |
| ".*This library is free software[,.;:]? you can redistribute it and or modify it" |
| + " under the terms of the MIT licen[cs]e[,.;:]?.*", |
| ".*may be distributed under the MIT or PSF open source licen[cs]es[,.;:]?.*", |
| ".*permission is (?:hereby )?granted[,;]? free of charge[,;]? to any person.*", |
| "(?:the mit licen[cs]e )?permission is (?:hereby )?granted[,;]? free of charge[,;]?" |
| + " to any person obtaining a copy of this software and associated documentation" |
| + " files [(]?the \\p{Pi}?software\\p{Pf}[)]?[,;]? to deal (?:in|with) 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[,;.:]?", |
| ".*permission to use[,;]? copy[,;]? modify[,;]? (?:and )?distribute" |
| + " (?:and sell )?this software (?:and its documentation )?(?:for any purpose )?" |
| + "(?:(?:and|with or) without fee)?is (?:hereby )?granted[,;]?" |
| + " (?:without fee )?provided that the above copyright notice.*", |
| ".*I hereby give permission[,;]? free of charge[,;]? to copy[,;]? modify[,;]? and" |
| + " redistribute this software[,;]? in source or binary form[,;]? provided that" |
| + " the above copyright notice and the following disclaimer are included.*")); |
| |
| /** Microsoft Public License */ |
| public static final Rule MSPL = |
| license( |
| ImmutableList.of( |
| "<license> <name> ?(?:The )?Microsoft Public Licen[cs]e ?</name>.*", |
| "<license> <name> ?MS-PL ?</name>.*", |
| ".*SPDX-License-Identifier: MS-PL")); |
| |
| /** NCSA License */ |
| public static final Rule NCSA = |
| license( |
| ImmutableList.of( |
| "<license> <name> ?NCSA ?</name>.*", |
| ".*SPDX-License-Identifier: NCSA", |
| "https?://otm[.]illinois[.]edu/uiuc_openSource", |
| "https?://(?:www[.])?opensource[.]org/licenses/NCSA", |
| "University of Illinois[/]NCSA Open Source Licen[cs]e", |
| "University of Illinois NCSA Open Source Licen[cs]e", |
| "Redistributions of source code must retain the above copyright notice,? this list of" |
| + " conditions and the following disclaimers[,;:.]?")); |
| |
| /** Generic non-commercial disclaimer. */ |
| public static final Rule NON_COMMERCIAL = |
| license(ImmutableList.of("\\bNON-?COMMERCIAL LICEN[CS]E")); |
| |
| /** Rejects distribution under APACHE */ |
| public static final Rule NOT_A_CONTRIBUTION = |
| license( |
| ImmutableList.of( |
| ".*(?:" |
| + ANY_WORD |
| + " ){2}\\p{Pi}?" // 2 words to exclude false +ves |
| + "Not a Contribution[.,;:]{0,3}\\p{Pf}?.*"), // explicitly disclaims license |
| ImmutableList.of("owner as \\p{Pi}?Not a Contribution[.,;:]{0,3}\\p{Pf}?")); |
| |
| /** OpenSSL License */ |
| public static final Rule OPENSSL = |
| new Rule( |
| ImmutableList.of("The OpenSSL Project[,.;:]?"), |
| ImmutableList.of( |
| "<license> <name> ?OpenSSL ?</name>.*", |
| ".*SPDX-License-Identifier: OpenSSL", |
| "https?://(?:www[.])?openssl[.]org/source/license[.]html", |
| "Licensed under the OpenSSL license(?: [(]?the \\p{Pi}?License\\p{Pf}?[)]?)?[,.;:]?", |
| "\\p{Pi}?This product includes software developed by the OpenSSL Project for use in" |
| + " the OpenSSL Toolkit[,;:.]?" |
| + "(?: [(]?https?://(?:www[.])?openssl[.]org(?:/| )?[)]?\\p{Pf}?)?", |
| "The names \\p{Pi}?OpenSSL Toolkit\\p{Pf}? and \\p{Pi}?OpenSSL Project\\p{Pf}? must" |
| + " not be used to endorse or promote", |
| "Original SSLeay License", |
| "OpenSSL License")); |
| |
| /** Python Software Foundation */ |
| public static final Rule PSF = owner(ImmutableList.of("Python Software Foundation")); |
| |
| /** Python Software Foundation License */ |
| public static final Rule PSFL = |
| license( |
| ImmutableList.of( |
| "(?:The )?PSF Licen[cs]e", |
| ".*Python Software Foundation license(?: version \\p{N})?[,.;:]?.*", |
| ".*Permission to use[,;]? copy[,;]? modify[,;]? and distribute this Python software" |
| + " and its associated documentation for any purpose.*")); |
| |
| /** Sun Insdustry Standards Source License */ |
| public static final Rule SISSL = |
| license(ImmutableList.of("\\bSun Industry Standards Source Licen[cs]e")); |
| |
| /** Server Side Public License */ |
| public static final Rule SSPL = |
| license( |
| ImmutableList.of( |
| ".*Server Side Public Licen[cs]e.*", |
| ".*SPDX-License-Identifier: SSPL-1[.]0", |
| "\\p{Pi}?This License\\p{Pf}? refers to (?:the )?Server Side Public License[,;:.]?", |
| "If you make the functionality of the Program (?:or a modified version )?available to" |
| + " third parties as a service,? you must make the Service Source Code available", |
| "\\p{Pi}?Service Source Code\\p{Pf}? means the Corresponding Source for the Program" |
| + "(?: or the modified version),? and the Corresponding Source for all programs" |
| + " that you use to make the Program", |
| "(?:https?://)?(?:www[.])?mongodb[.]com/licensing/server-side-public-license", |
| "SSPL-\\p{N}[.]?\\p{N}?", |
| "This program is free software[,.;:]? you can redistribute it and/or modify it under" |
| + " the terms of the Server Side Public License.*", |
| "You must comply with the Server Side Public License in all respects")); |
| |
| /** Unicode Data Files and Software/Terms of Use */ |
| public static final Rule UNICODE = |
| license( |
| ImmutableList.of( |
| ".*SPDX-License-Identifier: Unicode-DFS-\\p{N}{4}", |
| ".*SPDX-License-Identifier: Unicode-TOU", |
| "https?://(?:www[.])?unicode[.]org/copyright[.]html", |
| "UNICODE,? INC[.]? LICENSE AGREEMENT(?: -)? DATA FILES AND SOFTWARE", |
| "Permission is hereby granted,? free of charge,? to any person obtaining a copy of" |
| + " the Unicode data files and any associated documentation", |
| "Certain documents and files on this website contain a legend indicating that" |
| + " \\p{Pi}?Modification is permitted[,;:.]?\\p{Pf}?", |
| "the particular set of data files known as the \\p{Pi}?Unicode Character" |
| + " Database\\p{Pf}? can be found in", |
| "Each version of the Unicode Standard has further specifications of rights and" |
| + " restrictions of use[,;:.]?", |
| "Unicode License Agreement(?: -)? Data Files and Software(?: [(]?\\p{N}{4}[)]?)?", |
| "Unicode Terms of Use")); |
| |
| /** Unlicense (public domain) */ |
| public static final Rule UNLICENSE = |
| license( |
| ImmutableList.of( |
| ".*SPDX-License-Identifier: Unlicen[cs]e", |
| "<license> <name> ?Unlicen[cs]e ?</name>.*", |
| "This is free and unencumbered software released into the public domain[,;:.]?", |
| "the author (?:or authors )?of this software dedicate any and all copyright interest" |
| + " in the software to the public domain[,;:.]?", |
| "(?:https?://)?(?:www[.])?unlicen[cs]e[.]org(?:/UNLICEN[CS]E)?")); |
| |
| /** Universal Permissive License */ |
| public static final Rule UPL = |
| license( |
| ImmutableList.of( |
| "<license> <name> ?UPL(?:-1[.]0)? ?</name>.*", |
| ".*SPDX-License-Identifier: UPL-1[.]0", |
| "Universal Permissive License v1[.]0", |
| "The above copyright notice and either this complete permission notice or at a" |
| + " minimum a reference to the UPL must be included in all copies", |
| "The Universal Permissive License(?: [(]?UPL[)]?)?,?(?: Version 1[.]0)?")); |
| |
| /** W3C Software Notice and License */ |
| public static final Rule W3C = |
| new Rule( |
| ImmutableList.of( |
| "World Wide Web Consortium[,.;:]?", |
| "Massachusetts Institute of Technology,? European Research Consortium for Informatics" |
| + " and Mathematics, Keio University"), |
| ImmutableList.of( |
| ".*SPDX-License-Identifier: W3C(?:-(?:19980720|20021231|20150513))?", |
| "<license> <name> ? W3C(?:-(?:19980720|20021231|20150513))? ?</name>.*", |
| "https?://(?:www[.])?opensource[.]org/licenses/W3C", |
| "https?://(?:www[.])?w3[.]org/Consortium/Legal/copyright-software-19980720[.]html", |
| "https?://(?:www[.])?w3[.]org/Consortium/Legal/2002" |
| + "/copyright-software-20021231[.]html", |
| "https?://(?:www[.])?w3[.]org/Consortium/Legal/2015/copyright-software-and-document", |
| "If none exist,? a short notice of the following form", |
| "If none exist,? the W3C Software Short Notice should be included", |
| "If none exist,? the W3C Software and Document Short Notice should be included[.]?", |
| "W3C(?:®|[(]R[)])? SOFTWARE (?:NOTICE AND )?LICEN[CS]E" |
| + "(?: [(]?(?:1998-07-20|2002-12-31|2015-05-13)[)]?)?")); |
| |
| /** Watcom-1.0 license */ |
| public static final Rule WATCOM = |
| license( |
| ImmutableList.of( |
| ".*SPDX-License-Identifier: Watcom-1[.]0", |
| ".*Sybase Open Watcom Public License.*", |
| ".*automatically without notice if You[,;]? at any time during the term of this" |
| + " Licen[cs]e[,;]? commence an action for patent infringement [(]?including as a" |
| + " cross claim or counterclaim[)]?.*")); |
| |
| /** Do What The Fuck You Want To Public License */ |
| public static final Rule WTFPL = |
| license( |
| ImmutableList.of( |
| "<license> <name> ?WTFPL ?</name>.*", |
| ".*SPDX-License-Identifier: WTFPL", |
| "\\bDo What The F.ck You Want To Public Licen[cs]e")); |
| |
| /** X.Net License */ |
| public static final Rule XNET = |
| license( |
| ImmutableList.of( |
| "<license> <name> ?X[.]Net(?: Licen[cs]e)? ?</name>.*", |
| "<license> <name> ?Xnet ?</name>.*", |
| ".*SPDX-License-Identifier: Xnet", |
| "https?://(?:www[.])?opensource[.]org/licenses/Xnet", |
| "X.Net Licen[cs]e")); |
| |
| /** Zend Engine License version 2.00 */ |
| public static final Rule ZEND = |
| license( |
| ImmutableList.of( |
| "<license> <name> ?Zend(?: Engine)? License(?: (?:v|version )2[.]00?)? ?</name>.*", |
| "<license> <name> ?Zend(?:-2[.]00?)? ?</name>.*", |
| ".*SPDX-License-Identifier: Zend-2[.]0", |
| "https?://(?:www[.])?zend[.]com/license/2_00[.]txt", |
| "Zend (?:Engine )?License,? v2[.]00?", |
| "The Zend Engine License,? version 2[.]00?")); |
| |
| /** Zlib/libpng License */ |
| public static final Rule ZLIB = |
| license( |
| ImmutableList.of( |
| "<license> <name> ?zlib Licen[cs]e ?</name>.*", |
| "<license> <name> ?zlib/libpng Licen[cs]e(?: with Acknowledgement)? ?</name>.*", |
| ".*SPDX-License-Identifier: Zlib", |
| ".*SPDX-License-Identifier: zlib-acknowledgement", |
| "https?://(?:www[.])?opensource[.]org/licenses/zlib-license[.]php", |
| "https?://(?:www[.])?zlib[.]net/zlib_license[.]html", |
| "https?://(?:www[.])?opensource[.]org/licenses/Zlib", |
| "https?://(?:www[.])?fedoraproject[.]org/wiki/Licensing/ZlibWithAcknowledgement", |
| "Permission is granted to anyone to use this software for any purpose,? including" |
| + " commercial applications,? and to alter it and redistribute it freely,?" |
| + " subject to the following restrictions[,.;:]?", |
| "(?:The )?zlib/libpng License(?: with Acknowledgement)?", |
| "(?:The )?zlib/libpng License [(]Zlib[)]", |
| "zlib licen[cs]e")); |
| |
| /** Zope Public License */ |
| public static final Rule ZPL = |
| license( |
| ImmutableList.of( |
| "<license> <name> ?Zope Public License,?(?: version \\p{N}[.]?\\p{N}?)? ?</name>.*", |
| "<license> <name> ?ZPL-\\p{N}[.]?\\p{N}? ?</name>.*", |
| ".*SPDX-License-Identifier: ZPL-\\p{N}[.]?\\p{N}?", |
| "https?://(?:www[.])?opensource[.]org/licenses/ZPL-\\p{N}[.]?\\p{N}?", |
| "This product includes software developed by Zope Corporation", |
| "Names associated with Zope or Zope Corporation must not be used", |
| "The name Zope Corporation ?[(]tm[)] must not be used", |
| "Names of the copyright holders must not be used to endorse or promote products" |
| + " derived from this software without prior written permission from the" |
| + " copyright holders[,;:.]?", |
| "Zope Public License(?: [(]?ZPL[)]?)?(?: Version)?(?: \\p{N}[.]?\\p{N}?)?")); |
| |
| @VisibleForTesting |
| static ImmutableMap<String, Rule> lookup = |
| ImmutableMap.<String, Rule>builder() |
| .put("AFL2.1", AFL2_1) |
| .put("AFL3.0", AFL3_0) |
| .put("AGPL", AGPL) |
| .put("ANDROID", ANDROID) |
| .put("APACHE1.1", APACHE1_1) |
| .put("APACHE2", APACHE2) |
| .put("ARTISTIC_LICENSE", ARTISTIC_LICENSE) |
| .put("BEER_WARE", BEER_WARE) |
| .put("BOOST", BSL1_0) |
| .put("BSD", BSD) |
| .put("BSL1.0", BSL1_0) |
| .put("CC0", CC0) |
| .put("CC_BY_C", CC_BY_C) |
| .put("CC_BY_NC", CC_BY_NC) |
| .put("CLANG_LLVM", CLANG_LLVM) |
| .put("COMMONS_CLAUSE", COMMONS_CLAUSE) |
| .put("CPAL", CPAL) |
| .put("EDL", EDL) |
| .put("EPL", EPL) |
| .put("EUPL", EUPL) |
| .put("EXAMPLES", EXAMPLES) |
| .put("FTL", FTL) |
| .put("GOOGLE", GOOGLE) |
| .put("GPL", GPL) |
| .put("GPL2", GPL2) |
| .put("GPL3", GPL3) |
| .put("JSON", JSON) |
| .put("LGPL", LGPL) |
| .put("LIBTIFF", LIBTIFF) |
| .put("LPL1.02", LPL1_02) |
| .put("MIT", MIT) |
| .put("MS-PL", MSPL) |
| .put("NCSA", NCSA) |
| .put("NON_COMMERCIAL", NON_COMMERCIAL) |
| .put("NOT_A_CONTRIBUTION", NOT_A_CONTRIBUTION) |
| .put("OPENSSL", OPENSSL) |
| .put("PSF", PSF) |
| .put("PSFL", PSFL) |
| .put("SISSL", SISSL) |
| .put("SSPL", SSPL) |
| .put("UNLICENSE", UNLICENSE) |
| .put("UNICODE", UNICODE) |
| .put("UPL", UPL) |
| .put("W3C", W3C) |
| .put("WATCOM", WATCOM) |
| .put("WTFPL", WTFPL) |
| .put("XNET", XNET) |
| .put("ZEND", ZEND) |
| .put("ZLIB", ZLIB) |
| .put("ZPL", ZPL) |
| .build(); |
| |
| /** Immutable set of copyright rules described as lists of regular expression strings. */ |
| public static class RuleSet { |
| public final ImmutableList<String> firstPartyLicenses; |
| public final ImmutableList<String> thirdPartyLicenses; |
| public final ImmutableList<String> forbiddenLicenses; |
| public final ImmutableList<String> firstPartyOwners; |
| public final ImmutableList<String> thirdPartyOwners; |
| public final ImmutableList<String> forbiddenOwners; |
| public final ImmutableList<String> excludePatterns; |
| |
| /** Returns a Builder object for the RuleSet class. */ |
| public static Builder builder() { |
| return new Builder(); |
| } |
| |
| public String signature() { |
| StringBuilder sb = new StringBuilder(); |
| sb.append("1pl:\n"); |
| sb.append(Joiner.on("\n").join(firstPartyLicenses)); |
| sb.append("\n1po:\n"); |
| sb.append(Joiner.on("\n").join(firstPartyOwners)); |
| sb.append("\n3pl:\n"); |
| sb.append(Joiner.on("\n").join(thirdPartyLicenses)); |
| sb.append("\n3po:\n"); |
| sb.append(Joiner.on("\n").join(thirdPartyOwners)); |
| sb.append("\n!!l:\n"); |
| sb.append(Joiner.on("\n").join(forbiddenLicenses)); |
| sb.append("\n!!o:\n"); |
| sb.append(Joiner.on("\n").join(forbiddenOwners)); |
| sb.append("\nxx:\n"); |
| sb.append(Joiner.on("\n").join(excludePatterns)); |
| return Hashing.farmHashFingerprint64().hashBytes(sb.toString().getBytes(UTF_8)).toString(); |
| } |
| |
| /** Implements the Builder pattern for CopyrightPatterns.RuleSet. */ |
| public static class Builder { |
| private final ImmutableList.Builder<String> firstPartyLicenses = |
| ImmutableList.<String>builder(); |
| private final ImmutableList.Builder<String> thirdPartyLicenses = |
| ImmutableList.<String>builder(); |
| private final ImmutableList.Builder<String> forbiddenLicenses = |
| ImmutableList.<String>builder(); |
| private final ImmutableList.Builder<String> firstPartyOwners = |
| ImmutableList.<String>builder(); |
| private final ImmutableList.Builder<String> thirdPartyOwners = |
| ImmutableList.<String>builder(); |
| private final ImmutableList.Builder<String> forbiddenOwners = ImmutableList.<String>builder(); |
| private final ImmutableList.Builder<String> excludePatterns = ImmutableList.<String>builder(); |
| |
| private Builder() {} |
| |
| /** Create a RuleSet reflecting the current state of this Builder. */ |
| public RuleSet build() { |
| return new RuleSet( |
| firstPartyLicenses.build(), |
| thirdPartyLicenses.build(), |
| forbiddenLicenses.build(), |
| firstPartyOwners.build(), |
| thirdPartyOwners.build(), |
| forbiddenOwners.build(), |
| excludePatterns.build()); |
| } |
| |
| /** Look up `ruleName` and add it as a 1p rule type. */ |
| public Builder addFirstParty(String ruleName) { |
| Rule pattern = lookup.get(ruleName); |
| if (pattern == null) { |
| throw unknownPatternName(ruleName); |
| } |
| if (pattern.licenses != null) { |
| firstPartyLicenses.addAll(pattern.licenses); |
| } |
| if (pattern.owners != null) { |
| firstPartyOwners.addAll(pattern.owners); |
| } |
| if (pattern.exclusions != null) { |
| excludePatterns.addAll(pattern.exclusions); |
| } |
| return this; |
| } |
| |
| /** Add the regular expression `pattern` as a 1p owner. */ |
| public Builder addFirstPartyOwner(String pattern) { |
| firstPartyOwners.add(pattern); |
| return this; |
| } |
| |
| /** Add the regular expression `pattern` as a 1p license */ |
| public Builder addFirstPartyLicense(String pattern) { |
| firstPartyLicenses.add(pattern); |
| return this; |
| } |
| |
| /** Look up `ruleName` and add it as a 3p rule type. */ |
| public Builder addThirdParty(String ruleName) { |
| Rule pattern = lookup.get(ruleName); |
| if (pattern == null) { |
| throw unknownPatternName(ruleName); |
| } |
| if (pattern.licenses != null) { |
| thirdPartyLicenses.addAll(pattern.licenses); |
| } |
| if (pattern.owners != null) { |
| thirdPartyOwners.addAll(pattern.owners); |
| } |
| if (pattern.exclusions != null) { |
| excludePatterns.addAll(pattern.exclusions); |
| } |
| return this; |
| } |
| |
| /** Add the regular expression `pattern` as a 3p owner. */ |
| public Builder addThirdPartyOwner(String pattern) { |
| thirdPartyOwners.add(pattern); |
| return this; |
| } |
| |
| /** Add the regular expression `pattern` as a 3p license. */ |
| public Builder addThirdPartyLicense(String pattern) { |
| thirdPartyLicenses.add(pattern); |
| return this; |
| } |
| |
| /** Look up `ruleName` and add it as a forbidden rule type. */ |
| public Builder addForbidden(String ruleName) { |
| Rule pattern = lookup.get(ruleName); |
| if (pattern == null) { |
| throw unknownPatternName(ruleName); |
| } |
| if (pattern.licenses != null) { |
| forbiddenLicenses.addAll(pattern.licenses); |
| } |
| if (pattern.owners != null) { |
| forbiddenOwners.addAll(pattern.owners); |
| } |
| if (pattern.exclusions != null) { |
| excludePatterns.addAll(pattern.exclusions); |
| } |
| return this; |
| } |
| |
| /** Add the regular expression `pattern` as a forbidden owner. */ |
| public Builder addForbiddenOwner(String pattern) { |
| forbiddenOwners.add(pattern); |
| return this; |
| } |
| |
| /** Add the regular expression `pattern` as a forbidden license. */ |
| public Builder addForbiddenLicense(String pattern) { |
| forbiddenLicenses.add(pattern); |
| return this; |
| } |
| |
| /** Look up `ruleName` and add it as a rule type to ignore completely. */ |
| public Builder exclude(String ruleName) { |
| Rule pattern = lookup.get(ruleName); |
| if (pattern == null) { |
| throw unknownPatternName(ruleName); |
| } |
| if (pattern.licenses != null) { |
| excludePatterns.addAll(pattern.licenses); |
| } |
| if (pattern.owners != null) { |
| excludePatterns.addAll(pattern.owners); |
| } |
| if (pattern.exclusions != null) { |
| excludePatterns.addAll(pattern.exclusions); |
| } |
| return this; |
| } |
| |
| /** Add the regular expression `pattern` to the list of patterns to ignore when found. */ |
| public Builder excludePattern(String pattern) { |
| excludePatterns.add(pattern); |
| return this; |
| } |
| } |
| |
| private RuleSet( |
| ImmutableList<String> firstPartyLicenses, |
| ImmutableList<String> thirdPartyLicenses, |
| ImmutableList<String> forbiddenLicenses, |
| ImmutableList<String> firstPartyOwners, |
| ImmutableList<String> thirdPartyOwners, |
| ImmutableList<String> forbiddenOwners, |
| ImmutableList<String> excludePatterns) { |
| this.firstPartyLicenses = firstPartyLicenses; |
| this.thirdPartyLicenses = thirdPartyLicenses; |
| this.forbiddenLicenses = forbiddenLicenses; |
| this.firstPartyOwners = firstPartyOwners; |
| this.thirdPartyOwners = thirdPartyOwners; |
| this.forbiddenOwners = forbiddenOwners; |
| this.excludePatterns = excludePatterns; |
| } |
| |
| private static UnknownPatternName unknownPatternName(String ruleName) { |
| int minDist = -1; |
| for (String key : lookup.keySet()) { |
| int dist = StringUtils.getLevenshteinDistance(key, ruleName); |
| if (minDist < 0 || dist < minDist) { |
| minDist = dist; |
| } |
| } |
| ImmutableList.Builder<String> closeMatches = ImmutableList.builder(); |
| int numClose = 0; |
| if (minDist < 3) { |
| for (String key : lookup.keySet()) { |
| int dist = StringUtils.getLevenshteinDistance(key, ruleName); |
| if (dist == minDist) { |
| closeMatches.add(key); |
| numClose++; |
| } |
| } |
| } |
| String matches = Joiner.on(", ").join(numClose > 0 ? closeMatches.build() : lookup.keySet()); |
| int lastIndex = matches.lastIndexOf(", "); |
| if (lastIndex > 0) { |
| matches = matches.substring(0, lastIndex + 2) + "or " + matches.substring(lastIndex + 2); |
| } |
| String message = |
| "Unknown license or copyright owner name: " |
| + ruleName |
| + "\n\n" |
| + (numClose > 0 |
| ? "Did you mean " + matches + "?" |
| : "Known names are: " + matches + "."); |
| |
| return new UnknownPatternName(message); |
| } |
| } |
| |
| /** Initialize a pattern consisting of only a list of owner patterns. */ |
| private static Rule owner(ImmutableList<String> owners) { |
| return new Rule(owners, null, null); |
| } |
| |
| /** Initialize a pattern consisting of only a list of license patterns. */ |
| private static Rule license(ImmutableList<String> licenses) { |
| return new Rule(null, licenses, null); |
| } |
| |
| /** Initialize a pattern consisting of lists of license and exclusion patterns. */ |
| private static Rule license(ImmutableList<String> licenses, ImmutableList<String> exclusions) { |
| return new Rule(null, licenses, exclusions); |
| } |
| |
| /** |
| * A matching rule described by lists of regular expressions matching relevant licenses and |
| * owners, and a list of regular expressions matching hits to ignore when found. |
| * |
| * <p>e.g. The text "not a contribution" is important for Apache2 licensed code because it |
| * disclaims the terms of the otherwise described Apache2 license. However, this very text exists |
| * inside the Apache2 license to allow such disclaimers. An effective rule for /not a |
| * contribution/ will have to match /not a contribution/ but ignore /owner as "not a |
| * contribution"/ like it appears in the license itself. |
| */ |
| @VisibleForTesting |
| static class Rule { |
| public final ImmutableList<String> exclusions; |
| public final ImmutableList<String> owners; |
| public final ImmutableList<String> licenses; |
| |
| private Rule(ImmutableList<String> owners, ImmutableList<String> licenses) { |
| this(owners, licenses, null); |
| } |
| |
| private Rule( |
| ImmutableList<String> owners, |
| ImmutableList<String> licenses, |
| ImmutableList<String> exclusions) { |
| this.owners = owners; |
| this.licenses = licenses; |
| this.exclusions = exclusions; |
| } |
| } |
| |
| /** Thrown when requesting a pattern by a name that does not appear among the known patterns. */ |
| public static class UnknownPatternName extends NoSuchElementException { |
| UnknownPatternName(String message) { |
| super(message); |
| } |
| } |
| } |