blob: 390ffe2275fad1eb7641c355a44efde2885827eb [file] [log] [blame]
// 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 com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import java.util.NoSuchElementException;
/** 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 = "[\\s*/#]";
/** Regular expression matching whitespace, a comment character, or punctuation. */
public static final String WSPCT = "[-,;.\\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 + "})";
/** Affero General Public License */
public static final Rule AGPL = license(ImmutableList.of("Affero"));
/** 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 2 owned or licensed */
public static final Rule APACHE2 =
new Rule(
ImmutableList.of(
".*SPDX-License-Identifier: Apache-2.0",
"(?:by )?(?:The )?Apache Software Foundation.?",
"Apache Software Foundation.?"
+ " This product includes software developed"
+ " (?:by|at) The Apache Software Foundation"),
ImmutableList.of(
"http://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 Licen[cs]e Version 2[.]0",
"^apache2(?:-android)?",
"^the apache licen[cs]e",
"^terms of the Apache 2 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 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(
".*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}"));
/** 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)?"));
/** Commons Cause License */
public static final Rule COMMONS_CAUSE = license(ImmutableList.of("\\bCommons Clause"));
/** Common Public Attribution License */
public static final Rule CPAL =
license(ImmutableList.of("\\bCommon Public Attribution Licen[cs]e"));
/** Eclipse Public License */
public static final Rule EPL =
license(
ImmutableList.of(
"^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."));
/** Google owned */
public static final Rule GOOGLE = owner(ImmutableList.of("Google,? Inc."));
/** 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(
".*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(
".*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[,.;:]?"));
/** GNU Lessor or Library General Public License */
public static final Rule LGPL =
license(
ImmutableList.of(
".*SPDX-License-Identifier: LGPL.*",
".*LGPL.*",
".*gnu (?:library|lesser) general public licen[cs]e.*"));
/** MIT licensed */
public static final Rule MIT =
license(
ImmutableList.of(
".*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.*"));
/** 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}?"));
/** 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(
".*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"));
/** Watcom-1.0 license */
public static final Rule WATCOM =
license(
ImmutableList.of(
".*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("\\bDo What The Fuck You Want To Public Licen[cs]e"));
@VisibleForTesting
static ImmutableMap<String, Rule> lookup =
ImmutableMap.<String, Rule>builder()
.put("AGPL", AGPL)
.put("ANDROID", ANDROID)
.put("APACHE2", APACHE2)
.put("BEER_WARE", BEER_WARE)
.put("BSD", BSD)
.put("CC_BY_C", CC_BY_C)
.put("CC_BY_NC", CC_BY_NC)
.put("COMMONS_CLAUSE", COMMONS_CAUSE)
.put("CPAL", CPAL)
.put("EPL", EPL)
.put("EUPL", EUPL)
.put("EXAMPLES", EXAMPLES)
.put("GOOGLE", GOOGLE)
.put("GPL", GPL)
.put("GPL2", GPL2)
.put("GPL3", GPL3)
.put("LGPL", LGPL)
.put("MIT", MIT)
.put("NON_COMMERCIAL", NON_COMMERCIAL)
.put("NOT_A_CONTRIBUTION", NOT_A_CONTRIBUTION)
.put("PSF", PSF)
.put("PSFL", PSFL)
.put("SISSL", SISSL)
.put("WATCOM", WATCOM)
.put("WTFPL", WTFPL)
.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();
}
/** 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 new 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 new 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 new 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 new 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;
}
}
/** 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 ruleName) {
super(
"Unknown pattern name: "
+ ruleName
+ "\nKnown pattern names include: "
+ Joiner.on(", ").join(lookup.keySet()));
}
}
}