You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by da...@apache.org on 2018/11/03 20:59:59 UTC
[3/3] lucene-solr:jira/gradle: Add checkLicenses task
Add checkLicenses task
Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/d541e180
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/d541e180
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/d541e180
Branch: refs/heads/jira/gradle
Commit: d541e180047cfc2a0c528caa7216fcb3f34678bb
Parents: 15f3bce
Author: Cao Manh Dat <da...@apache.org>
Authored: Sat Nov 3 20:59:48 2018 +0000
Committer: Cao Manh Dat <da...@apache.org>
Committed: Sat Nov 3 20:59:48 2018 +0000
----------------------------------------------------------------------
build.gradle | 9 +-
buildSrc/build.gradle | 14 +
.../lucene/gradle/CheckWorkingCopy.groovy | 81 +++++
.../apache/lucene/gradle/LicenseCheckTask.java | 300 ++++++++++++++++
.../apache/lucene/gradle/LicenseCheckTask2.java | 356 +++++++++++++++++++
.../org/apache/lucene/gradle/LicenseType.java | 75 ++++
lucene/build.gradle | 8 +
lucene/licenses/asm-tree-5.1.jar.sha1 | 1 +
lucene/licenses/commons-codec-1.9.jar.sha1 | 1 +
lucene/licenses/commons-logging-1.1.3.jar.sha1 | 1 -
lucene/licenses/commons-logging-1.2.jar.sha1 | 1 +
lucene/licenses/hamcrest-core-1.1.jar.sha1 | 1 +
lucene/licenses/hamcrest-core-LICENSE-BSD.txt | 27 ++
lucene/licenses/hamcrest-core-NOTICE.txt | 0
.../jetty-security-9.4.11.v20180605.jar.sha1 | 1 +
lucene/replicator/ivy.xml | 2 -
solr/build.gradle | 8 +
17 files changed, 880 insertions(+), 6 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d541e180/build.gradle
----------------------------------------------------------------------
diff --git a/build.gradle b/build.gradle
index 6013e5f..6c46251 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,3 +1,5 @@
+import org.apache.lucene.gradle.CheckWorkingCopy
+
/*
* This file was generated by the Gradle 'init' task.
*
@@ -31,11 +33,12 @@ subprojects {
}
}
tasks.withType(Test) {
- maxParallelForks = Runtime.runtime.availableProcessors() / 2
- }
-
+ maxParallelForks = Runtime.runtime.availableProcessors() / 2
+ }
}
+tasks.create('checkWorkingCopy', CheckWorkingCopy, true)
+
// These versions are defined here because they represent
// a dependency version which should match across multiple
// Maven artifacts.
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d541e180/buildSrc/build.gradle
----------------------------------------------------------------------
diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle
new file mode 100644
index 0000000..20921a9
--- /dev/null
+++ b/buildSrc/build.gradle
@@ -0,0 +1,14 @@
+apply plugin: 'groovy'
+apply plugin: 'java'
+group = 'org.lucene.gradle'
+
+repositories {
+ jcenter()
+}
+
+dependencies {
+ compile gradleApi()
+ compile localGroovy()
+
+ compile 'org.eclipse.jgit:org.eclipse.jgit:4.6.0.201612231935-r'
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d541e180/buildSrc/src/main/groovy/org/apache/lucene/gradle/CheckWorkingCopy.groovy
----------------------------------------------------------------------
diff --git a/buildSrc/src/main/groovy/org/apache/lucene/gradle/CheckWorkingCopy.groovy b/buildSrc/src/main/groovy/org/apache/lucene/gradle/CheckWorkingCopy.groovy
new file mode 100644
index 0000000..8680f11
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/lucene/gradle/CheckWorkingCopy.groovy
@@ -0,0 +1,81 @@
+package org.apache.lucene.gradle
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/** Task script that is called by Ant's build.xml file:
+ * Checks GIT working copy for unversioned or modified files.
+ */
+
+import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.api.Status;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
+import org.eclipse.jgit.errors.*;
+import org.gradle.api.DefaultTask
+import org.gradle.api.GradleException
+import org.gradle.api.tasks.TaskAction
+
+import javax.inject.Inject
+
+class CheckWorkingCopy extends DefaultTask {
+ boolean failonmodifications
+
+ @Inject
+ CheckWorkingCopy(boolean failonmodifications) {
+ this.failonmodifications = failonmodifications
+ }
+
+ @TaskAction
+ void check() {
+ try {
+ println 'Initializing working copy...' + failonmodifications
+ final Repository repository = new FileRepositoryBuilder()
+ .setWorkTree(project.getRootDir())
+ .setMustExist(true)
+ .build();
+
+ println 'Checking working copy status...'
+ final Status status = new Git(repository).status().call();
+ if (!status.isClean()) {
+ final SortedSet unversioned = new TreeSet(), modified = new TreeSet();
+ status.properties.each{ prop, val ->
+ if (val instanceof Set) {
+ if (prop in ['untracked', 'untrackedFolders', 'missing']) {
+ unversioned.addAll(val);
+ } else if (prop != 'ignoredNotInIndex') {
+ modified.addAll(val);
+ }
+ }
+ }
+ if (unversioned) {
+ throw new GradleException(
+ "Source checkout is dirty (unversioned/missing files) after running tests!!! Offending files:\n" +
+ '* ' + unversioned.join('\n* '))
+ }
+ if (failonmodifications) {
+ throw new GradleException(
+ "Source checkout is modified!!! Offending files:\n"+
+ '* ' + unversioned.join('\n* '))
+ }
+ }
+ } catch (RepositoryNotFoundException | NoWorkTreeException | NotSupportedException e) {
+ logger.error('WARNING: Development directory is not a valid GIT checkout! Disabling checks...')
+ }
+ }
+}
+
+
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d541e180/buildSrc/src/main/java/org/apache/lucene/gradle/LicenseCheckTask.java
----------------------------------------------------------------------
diff --git a/buildSrc/src/main/java/org/apache/lucene/gradle/LicenseCheckTask.java b/buildSrc/src/main/java/org/apache/lucene/gradle/LicenseCheckTask.java
new file mode 100644
index 0000000..271d1b8
--- /dev/null
+++ b/buildSrc/src/main/java/org/apache/lucene/gradle/LicenseCheckTask.java
@@ -0,0 +1,300 @@
+package org.apache.lucene.gradle;
+
+import org.gradle.api.DefaultTask;
+import org.gradle.api.GradleException;
+import org.gradle.api.artifacts.ResolvedArtifact;
+import org.gradle.api.logging.LogLevel;
+
+import javax.inject.Inject;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
+import java.security.DigestInputStream;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+public class LicenseCheckTask extends DefaultTask {
+ private final static String CHECKSUM_TYPE = "sha1";
+ private static final int CHECKSUM_BUFFER_SIZE = 8 * 1024;
+ private static final int CHECKSUM_BYTE_MASK = 0xFF;
+ private static final String FAILURE_MESSAGE = "License check failed. Check the logs.\n"
+ + "If you recently modified ivy-versions.properties or any module's build.gradle,\n"
+ + "make sure you run \"ant clean-jars jar-checksums\" before running precommit.";
+ private static final Map<Pattern, String> REPLACE_PATTERNS = new HashMap<>();
+ static {
+ REPLACE_PATTERNS.put(Pattern.compile("jetty([^/]+)$"), "jetty");
+ REPLACE_PATTERNS.put(Pattern.compile("asm([^/]+)$"), "asm");
+ REPLACE_PATTERNS.put(Pattern.compile("slf4j-([^/]+)$"), "slf4j");
+ REPLACE_PATTERNS.put(Pattern.compile("javax\\.servlet([^/]+)$"), "javax.servlet");
+ REPLACE_PATTERNS.put(Pattern.compile("(bcmail|bcprov)-([^/]+)$"), "\1");
+ }
+
+ private Pattern skipRegexChecksum;
+ private boolean skipSnapshotsChecksum;
+ private boolean skipChecksum;
+
+
+ /**
+ * Directory containing licenses
+ */
+ private File licenseDirectory;
+
+ /**
+ * Failure flag.
+ */
+ private boolean failures;
+
+ @Inject
+ public LicenseCheckTask(File licenseDirectory) {
+ this.licenseDirectory = licenseDirectory;
+ doLast(task -> {
+ Set<ResolvedArtifact> deps = new HashSet<>();
+ getProject().getSubprojects().forEach(project -> {
+ project.getConfigurations().forEach(config -> {
+ if (config.isCanBeResolved()) {
+ deps.addAll(config.getResolvedConfiguration().getResolvedArtifacts());
+ }
+ });
+ });
+ deps.removeIf(artifact -> {
+ String groupName = artifact.getModuleVersion().getId().getGroup();
+ return "org.apache.lucene".equals(groupName) || "org.apache.solr".equals(groupName);
+ });
+
+ doCheck(deps);
+ });
+ }
+
+ public void setSkipSnapshotsChecksum(boolean skipSnapshotsChecksum) {
+ this.skipSnapshotsChecksum = skipSnapshotsChecksum;
+ }
+
+ public void setSkipChecksum(boolean skipChecksum) {
+ this.skipChecksum = skipChecksum;
+ }
+
+ public void setSkipRegexChecksum(String skipRegexChecksum) {
+ try {
+ if (skipRegexChecksum != null && skipRegexChecksum.length() > 0) {
+ this.skipRegexChecksum = Pattern.compile(skipRegexChecksum);
+ }
+ } catch (PatternSyntaxException e) {
+ throw new GradleException("Unable to compile skipRegexChecksum pattern. Reason: "
+ + e.getMessage() + " " + skipRegexChecksum, e);
+ }
+ }
+
+ /**
+ * Execute the task.
+ */
+ public void doCheck(Set<ResolvedArtifact> jars) {
+ if (skipChecksum) {
+ getLogger().info("Skipping checksum verification for dependencies");
+ } else {
+ if (skipSnapshotsChecksum) {
+ getLogger().info("Skipping checksum for SNAPSHOT dependencies");
+ }
+
+ if (skipRegexChecksum != null) {
+ getLogger().info("Skipping checksum for dependencies matching regex: " + skipRegexChecksum.pattern());
+ }
+ }
+
+ processJars(jars);
+
+ if (failures) {
+ throw new GradleException(FAILURE_MESSAGE);
+ }
+ }
+
+ /**
+ * Process all JARs.
+ */
+ private void processJars(Set<ResolvedArtifact> jars) {
+ long start = System.currentTimeMillis();
+ int errors = 0;
+ int checked = 0;
+ for (ResolvedArtifact artifact : jars) {
+ if (!checkJarFile(artifact)) {
+ errors++;
+ }
+ checked++;
+ }
+
+ getLogger().log(errors > 0 ? LogLevel.ERROR : LogLevel.INFO, String.format(Locale.ROOT,
+ "Scanned %d JAR file(s) for licenses (in %.2fs.), %d error(s).",
+ checked, (System.currentTimeMillis() - start) / 1000.0, errors));
+ }
+
+ /**
+ * Check a single JAR file.
+ */
+ private boolean checkJarFile(ResolvedArtifact artifact) {
+ File jarFile = artifact.getFile();
+ getLogger().debug("Scanning: {}", jarFile.getPath());
+
+ if (!skipChecksum) {
+ boolean skipDueToSnapshot = skipSnapshotsChecksum && jarFile.getName().contains("-SNAPSHOT");
+ if (!skipDueToSnapshot && !matchesRegexChecksum(jarFile, skipRegexChecksum)) {
+ // validate the jar matches against our expected hash
+ final File checksumFile = new File(licenseDirectory, jarFile.getName()
+ + "." + CHECKSUM_TYPE);
+ if (!(checksumFile.exists() && checksumFile.canRead())) {
+ getLogger().error("MISSING {} checksum file for: {}", CHECKSUM_TYPE, jarFile.getPath());
+ this.failures = true;
+ return false;
+ } else {
+ final String expectedChecksum = readChecksumFile(checksumFile);
+ try {
+ final MessageDigest md = MessageDigest.getInstance(CHECKSUM_TYPE);
+ byte[] buf = new byte[CHECKSUM_BUFFER_SIZE];
+ try {
+ FileInputStream fis = new FileInputStream(jarFile);
+ try {
+ DigestInputStream dis = new DigestInputStream(fis, md);
+ try {
+ while (dis.read(buf, 0, CHECKSUM_BUFFER_SIZE) != -1) {
+ // NOOP
+ }
+ } finally {
+ dis.close();
+ }
+ } finally {
+ fis.close();
+ }
+ } catch (IOException ioe) {
+ throw new GradleException("IO error computing checksum of file: "
+ + jarFile, ioe);
+ }
+ final byte[] checksumBytes = md.digest();
+ final String checksum = createChecksumString(checksumBytes);
+ if (!checksum.equals(expectedChecksum)) {
+ getLogger().error("CHECKSUM FAILED for " + jarFile.getPath() + " (expected: \""
+ + expectedChecksum + "\" was: \"" + checksum + "\")");
+ this.failures = true;
+ return false;
+ }
+
+ } catch (NoSuchAlgorithmException ae) {
+ throw new GradleException("Digest type " + CHECKSUM_TYPE
+ + " not supported by your JVM", ae);
+ }
+ }
+ } else if (skipDueToSnapshot) {
+ getLogger().info("Skipping jar because it is a SNAPSHOT : "
+ + jarFile.getAbsolutePath());
+ } else {
+ getLogger().info("Skipping jar because it matches regex pattern: {} pattern:{}",
+ jarFile.getAbsolutePath(), skipRegexChecksum.pattern());
+ }
+ }
+
+ // Get the expected license path base from the mapper and search for license files.
+ Map<File, LicenseType> foundLicenses = new LinkedHashMap<>();
+ List<File> expectedLocations = new ArrayList<>();
+ outer:
+ for (LicenseType licenseType : LicenseType.values()) {
+ String artifactName = artifact.getModuleVersion().getId().getName();
+ for (Map.Entry<Pattern, String> entry : REPLACE_PATTERNS.entrySet()) {
+ artifactName = entry.getKey().matcher(artifactName).replaceAll(entry.getValue());
+ }
+ File licensePath = new File(licenseDirectory,
+ artifactName + licenseType.licenseFileSuffix());
+ if (licensePath.exists()) {
+ foundLicenses.put(licensePath, licenseType);
+ getLogger().debug(" FOUND " + licenseType.name() + " license at " + licensePath.getPath());
+ // We could continue scanning here to detect duplicate associations?
+ break outer;
+ } else {
+ expectedLocations.add(licensePath);
+ }
+ }
+
+ // Check for NOTICE files.
+ for (Map.Entry<File, LicenseType> e : foundLicenses.entrySet()) {
+ LicenseType license = e.getValue();
+ String licensePath = e.getKey().getName();
+ String baseName = licensePath.substring(
+ 0, licensePath.length() - license.licenseFileSuffix().length());
+ File noticeFile = new File(licenseDirectory, baseName + license.noticeFileSuffix());
+
+ if (noticeFile.exists()) {
+ getLogger().debug(" FOUND NOTICE file at " + noticeFile.getAbsolutePath());
+ } else {
+ if (license.isNoticeRequired()) {
+ this.failures = true;
+ getLogger().error("MISSING NOTICE for the license file:\n "
+ + licensePath + "\n Expected location below:\n "
+ + noticeFile.getAbsolutePath());
+ }
+ }
+ }
+
+ // In case there is something missing, complain.
+ if (foundLicenses.isEmpty()) {
+ this.failures = true;
+ StringBuilder message = new StringBuilder();
+ message.append(
+ "MISSING LICENSE for the following file:\n " + jarFile.getAbsolutePath()
+ + "\n Expected locations below:\n");
+ for (File location : expectedLocations) {
+ message.append(" => ").append(location.getAbsolutePath()).append("\n");
+ }
+ getLogger().error(message.toString());
+ return false;
+ }
+
+ return true;
+ }
+
+ private static String createChecksumString(byte[] digest) {
+ StringBuilder checksum = new StringBuilder();
+ for (byte aDigest : digest) {
+ checksum.append(String.format(Locale.ROOT, "%02x",
+ CHECKSUM_BYTE_MASK & aDigest));
+ }
+ return checksum.toString();
+ }
+
+ private static String readChecksumFile(File f) {
+ BufferedReader reader = null;
+ try {
+ reader = new BufferedReader(new InputStreamReader
+ (new FileInputStream(f), StandardCharsets.UTF_8));
+ try {
+ String checksum = reader.readLine();
+ if (null == checksum || 0 == checksum.length()) {
+ throw new GradleException("Failed to find checksum in file: " + f);
+ }
+ return checksum;
+ } finally {
+ reader.close();
+ }
+ } catch (IOException e) {
+ throw new GradleException("IO error reading checksum file: " + f, e);
+ }
+ }
+
+ private static final boolean matchesRegexChecksum(File jarFile, Pattern skipRegexChecksum) {
+ if (skipRegexChecksum == null) {
+ return false;
+ }
+ Matcher m = skipRegexChecksum.matcher(jarFile.getName());
+ return m.matches();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d541e180/buildSrc/src/main/java/org/apache/lucene/gradle/LicenseCheckTask2.java
----------------------------------------------------------------------
diff --git a/buildSrc/src/main/java/org/apache/lucene/gradle/LicenseCheckTask2.java b/buildSrc/src/main/java/org/apache/lucene/gradle/LicenseCheckTask2.java
new file mode 100644
index 0000000..83a93b6
--- /dev/null
+++ b/buildSrc/src/main/java/org/apache/lucene/gradle/LicenseCheckTask2.java
@@ -0,0 +1,356 @@
+///*
+// * Licensed to the Apache Software Foundation (ASF) under one or more
+// * contributor license agreements. See the NOTICE file distributed with
+// * this work for additional information regarding copyright ownership.
+// * The ASF licenses this file to You under the Apache License, Version 2.0
+// * (the "License"); you may not use this file except in compliance with
+// * the License. You may obtain a copy of the License at
+// *
+// * http://www.apache.org/licenses/LICENSE-2.0
+// *
+// * Unless required by applicable law or agreed to in writing, software
+// * distributed under the License is distributed on an "AS IS" BASIS,
+// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// * See the License for the specific language governing permissions and
+// * limitations under the License.
+// */
+//package org.apache.lucene.gradle;
+//
+//import java.io.File;
+//import java.io.FileInputStream;
+//import java.io.BufferedReader;
+//import java.io.InputStreamReader;
+//import java.io.IOException;
+//import java.nio.charset.StandardCharsets;
+//import java.util.ArrayList;
+//import java.util.Iterator;
+//import java.util.LinkedHashMap;
+//import java.util.List;
+//import java.util.Locale;
+//import java.util.Map;
+//import java.util.regex.Matcher;
+//import java.util.regex.Pattern;
+//import java.util.regex.PatternSyntaxException;
+//import java.security.DigestInputStream;
+//import java.security.MessageDigest;
+//import java.security.NoSuchAlgorithmException;
+//
+//import org.apache.tools.ant.BuildException;
+//import org.apache.tools.ant.Project;
+//import org.apache.tools.ant.Task;
+//import org.apache.tools.ant.types.Mapper;
+//import org.apache.tools.ant.types.Resource;
+//import org.apache.tools.ant.types.ResourceCollection;
+//import org.apache.tools.ant.types.resources.FileResource;
+//import org.apache.tools.ant.types.resources.Resources;
+//import org.apache.tools.ant.util.FileNameMapper;
+//import org.gradle.api.DefaultTask;
+//
+///**
+// * An ANT task that verifies if JAR file have associated <tt>LICENSE</tt>,
+// * <tt>NOTICE</tt>, and <tt>sha1</tt> files.
+// */
+//public class LicenseCheckTask extends DefaultTask {
+//
+// public final static String CHECKSUM_TYPE = "sha1";
+// private static final int CHECKSUM_BUFFER_SIZE = 8 * 1024;
+// private static final int CHECKSUM_BYTE_MASK = 0xFF;
+// private static final String FAILURE_MESSAGE = "License check failed. Check the logs.\n"
+// + "If you recently modified ivy-versions.properties or any module's ivy.xml,\n"
+// + "make sure you run \"ant clean-jars jar-checksums\" before running precommit.";
+//
+// private Pattern skipRegexChecksum;
+// private boolean skipSnapshotsChecksum;
+// private boolean skipChecksum;
+//
+// /**
+// * All JAR files to check.
+// */
+// private Resources jarResources = new Resources();
+//
+// /**
+// * Directory containing licenses
+// */
+// private File licenseDirectory;
+//
+// /**
+// * License file mapper.
+// */
+// private FileNameMapper licenseMapper;
+//
+// /**
+// * A logging level associated with verbose logging.
+// */
+// private int verboseLevel = Project.MSG_VERBOSE;
+//
+// /**
+// * Failure flag.
+// */
+// private boolean failures;
+//
+// /**
+// * Adds a set of JAR resources to check.
+// */
+// public void add(ResourceCollection rc) {
+// jarResources.add(rc);
+// }
+//
+// /**
+// * Adds a license mapper.
+// */
+// public void addConfiguredLicenseMapper(Mapper mapper) {
+// if (licenseMapper != null) {
+// throw new BuildException("Only one license mapper is allowed.");
+// }
+// this.licenseMapper = mapper.getImplementation();
+// }
+//
+// public void setVerbose(boolean verbose) {
+// verboseLevel = (verbose ? Project.MSG_INFO : Project.MSG_VERBOSE);
+// }
+//
+// public void setLicenseDirectory(File file) {
+// licenseDirectory = file;
+// }
+//
+// public void setSkipSnapshotsChecksum(boolean skipSnapshotsChecksum) {
+// this.skipSnapshotsChecksum = skipSnapshotsChecksum;
+// }
+//
+// public void setSkipChecksum(boolean skipChecksum) {
+// this.skipChecksum = skipChecksum;
+// }
+//
+// public void setSkipRegexChecksum(String skipRegexChecksum) {
+// try {
+// if (skipRegexChecksum != null && skipRegexChecksum.length() > 0) {
+// this.skipRegexChecksum = Pattern.compile(skipRegexChecksum);
+// }
+// } catch (PatternSyntaxException e) {
+// throw new BuildException("Unable to compile skipRegexChecksum pattern. Reason: "
+// + e.getMessage() + " " + skipRegexChecksum, e);
+// }
+// }
+//
+// /**
+// * Execute the task.
+// */
+//
+// public void execute() throws BuildException {
+// this.getTaskDependencies().visitDependencies();
+// if (licenseMapper == null) {
+// throw new BuildException("Expected an embedded <licenseMapper>.");
+// }
+//
+// if (skipChecksum) {
+// log("Skipping checksum verification for dependencies", Project.MSG_INFO);
+// } else {
+// if (skipSnapshotsChecksum) {
+// log("Skipping checksum for SNAPSHOT dependencies", Project.MSG_INFO);
+// }
+//
+// if (skipRegexChecksum != null) {
+// log("Skipping checksum for dependencies matching regex: " + skipRegexChecksum.pattern(),
+// Project.MSG_INFO);
+// }
+// }
+//
+// jarResources.setProject(getProject());
+// processJars();
+//
+// if (failures) {
+// throw new BuildException(FAILURE_MESSAGE);
+// }
+// }
+//
+// /**
+// * Process all JARs.
+// */
+// private void processJars() {
+// log("Starting scan.", verboseLevel);
+// long start = System.currentTimeMillis();
+//
+// @SuppressWarnings("unchecked")
+// Iterator<Resource> iter = (Iterator<Resource>) jarResources.iterator();
+// int checked = 0;
+// int errors = 0;
+// while (iter.hasNext()) {
+// final Resource r = iter.next();
+// if (!r.isExists()) {
+// throw new BuildException("JAR resource does not exist: " + r.getName());
+// }
+// if (!(r instanceof FileResource)) {
+// throw new BuildException("Only filesystem resource are supported: " + r.getName()
+// + ", was: " + r.getClass().getName());
+// }
+//
+// File jarFile = ((FileResource) r).getFile();
+// if (! checkJarFile(jarFile) ) {
+// errors++;
+// }
+// checked++;
+// }
+//
+// log(String.format(Locale.ROOT,
+// "Scanned %d JAR file(s) for licenses (in %.2fs.), %d error(s).",
+// checked, (System.currentTimeMillis() - start) / 1000.0, errors),
+// errors > 0 ? Project.MSG_ERR : Project.MSG_INFO);
+// }
+//
+// /**
+// * Check a single JAR file.
+// */
+// private boolean checkJarFile(File jarFile) {
+// log("Scanning: " + jarFile.getPath(), verboseLevel);
+//
+// if (!skipChecksum) {
+// boolean skipDueToSnapshot = skipSnapshotsChecksum && jarFile.getName().contains("-SNAPSHOT");
+// if (!skipDueToSnapshot && !matchesRegexChecksum(jarFile, skipRegexChecksum)) {
+// // validate the jar matches against our expected hash
+// final File checksumFile = new File(licenseDirectory, jarFile.getName()
+// + "." + CHECKSUM_TYPE);
+// if (!(checksumFile.exists() && checksumFile.canRead())) {
+// log("MISSING " + CHECKSUM_TYPE + " checksum file for: "
+// + jarFile.getPath(), Project.MSG_ERR);
+// log("EXPECTED " + CHECKSUM_TYPE + " checksum file : "
+// + checksumFile.getPath(), Project.MSG_ERR);
+// this.failures = true;
+// return false;
+// } else {
+// final String expectedChecksum = readChecksumFile(checksumFile);
+// try {
+// final MessageDigest md = MessageDigest.getInstance(CHECKSUM_TYPE);
+// byte[] buf = new byte[CHECKSUM_BUFFER_SIZE];
+// try {
+// FileInputStream fis = new FileInputStream(jarFile);
+// try {
+// DigestInputStream dis = new DigestInputStream(fis, md);
+// try {
+// while (dis.read(buf, 0, CHECKSUM_BUFFER_SIZE) != -1) {
+// // NOOP
+// }
+// } finally {
+// dis.close();
+// }
+// } finally {
+// fis.close();
+// }
+// } catch (IOException ioe) {
+// throw new BuildException("IO error computing checksum of file: "
+// + jarFile, ioe);
+// }
+// final byte[] checksumBytes = md.digest();
+// final String checksum = createChecksumString(checksumBytes);
+// if (!checksum.equals(expectedChecksum)) {
+// log("CHECKSUM FAILED for " + jarFile.getPath() + " (expected: \""
+// + expectedChecksum + "\" was: \"" + checksum + "\")",
+// Project.MSG_ERR);
+// this.failures = true;
+// return false;
+// }
+//
+// } catch (NoSuchAlgorithmException ae) {
+// throw new BuildException("Digest type " + CHECKSUM_TYPE
+// + " not supported by your JVM", ae);
+// }
+// }
+// } else if (skipDueToSnapshot) {
+// log("Skipping jar because it is a SNAPSHOT : "
+// + jarFile.getAbsolutePath(), Project.MSG_INFO);
+// } else {
+// log("Skipping jar because it matches regex pattern: "
+// + jarFile.getAbsolutePath() + " pattern: " + skipRegexChecksum.pattern(), Project.MSG_INFO);
+// }
+// }
+//
+// // Get the expected license path base from the mapper and search for license files.
+// Map<File, LicenseType> foundLicenses = new LinkedHashMap<>();
+// List<File> expectedLocations = new ArrayList<>();
+// outer:
+// for (String mappedPath : licenseMapper.mapFileName(jarFile.getName())) {
+// for (LicenseType licenseType : LicenseType.values()) {
+// File licensePath = new File(licenseDirectory, mappedPath + licenseType.licenseFileSuffix());
+// if (licensePath.exists()) {
+// foundLicenses.put(licensePath, licenseType);
+// log(" FOUND " + licenseType.name() + " license at " + licensePath.getPath(),
+// verboseLevel);
+// // We could continue scanning here to detect duplicate associations?
+// break outer;
+// } else {
+// expectedLocations.add(licensePath);
+// }
+// }
+// }
+//
+// // Check for NOTICE files.
+// for (Map.Entry<File, LicenseType> e : foundLicenses.entrySet()) {
+// LicenseType license = e.getValue();
+// String licensePath = e.getKey().getName();
+// String baseName = licensePath.substring(
+// 0, licensePath.length() - license.licenseFileSuffix().length());
+// File noticeFile = new File(licenseDirectory, baseName + license.noticeFileSuffix());
+//
+// if (noticeFile.exists()) {
+// log(" FOUND NOTICE file at " + noticeFile.getAbsolutePath(), verboseLevel);
+// } else {
+// if (license.isNoticeRequired()) {
+// this.failures = true;
+// log("MISSING NOTICE for the license file:\n "
+// + licensePath + "\n Expected location below:\n "
+// + noticeFile.getAbsolutePath(), Project.MSG_ERR);
+// }
+// }
+// }
+//
+// // In case there is something missing, complain.
+// if (foundLicenses.isEmpty()) {
+// this.failures = true;
+// StringBuilder message = new StringBuilder();
+// message.append(
+// "MISSING LICENSE for the following file:\n " + jarFile.getAbsolutePath()
+// + "\n Expected locations below:\n");
+// for (File location : expectedLocations) {
+// message.append(" => ").append(location.getAbsolutePath()).append("\n");
+// }
+// log(message.toString(), Project.MSG_ERR);
+// return false;
+// }
+//
+// return true;
+// }
+//
+// private static final String createChecksumString(byte[] digest) {
+// StringBuilder checksum = new StringBuilder();
+// for (int i = 0; i < digest.length; i++) {
+// checksum.append(String.format(Locale.ROOT, "%02x",
+// CHECKSUM_BYTE_MASK & digest[i]));
+// }
+// return checksum.toString();
+// }
+// private static final String readChecksumFile(File f) {
+// BufferedReader reader = null;
+// try {
+// reader = new BufferedReader(new InputStreamReader
+// (new FileInputStream(f), StandardCharsets.UTF_8));
+// try {
+// String checksum = reader.readLine();
+// if (null == checksum || 0 == checksum.length()) {
+// throw new BuildException("Failed to find checksum in file: " + f);
+// }
+// return checksum;
+// } finally {
+// reader.close();
+// }
+// } catch (IOException e) {
+// throw new BuildException("IO error reading checksum file: " + f, e);
+// }
+// }
+//
+// private static final boolean matchesRegexChecksum(File jarFile, Pattern skipRegexChecksum) {
+// if (skipRegexChecksum == null) {
+// return false;
+// }
+// Matcher m = skipRegexChecksum.matcher(jarFile.getName());
+// return m.matches();
+// }
+//}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d541e180/buildSrc/src/main/java/org/apache/lucene/gradle/LicenseType.java
----------------------------------------------------------------------
diff --git a/buildSrc/src/main/java/org/apache/lucene/gradle/LicenseType.java b/buildSrc/src/main/java/org/apache/lucene/gradle/LicenseType.java
new file mode 100644
index 0000000..8c1d2b8
--- /dev/null
+++ b/buildSrc/src/main/java/org/apache/lucene/gradle/LicenseType.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.lucene.gradle;
+
+
+/**
+ * A list of accepted licenses. See also http://www.apache.org/legal/3party.html
+ *
+ **/
+public enum LicenseType {
+ ASL("Apache Software License 2.0", true),
+ BSD("Berkeley Software Distribution", true),
+ BSD_LIKE("BSD like license", true),//BSD like just means someone has taken the BSD license and put in their name, copyright, or it's a very similar license.
+ CDDL("Common Development and Distribution License", false),
+ CPL("Common Public License", true),
+ EPL("Eclipse Public License Version 1.0", false),
+ MIT("Massachusetts Institute of Tech. License", false),
+ MPL("Mozilla Public License", false), //NOT SURE on the required notice
+ PD("Public Domain", false),
+ //SUNBCLA("Sun Binary Code License Agreement"),
+ SUN("Sun Open Source License", false),
+ COMPOUND("Compound license (see NOTICE).", true),
+ FAKE("FAKE license - not needed", false);
+
+ private String display;
+ private boolean noticeRequired;
+
+ LicenseType(String display, boolean noticeRequired) {
+ this.display = display;
+ this.noticeRequired = noticeRequired;
+ }
+
+ public boolean isNoticeRequired() {
+ return noticeRequired;
+ }
+
+ public String getDisplay() {
+ return display;
+ }
+
+ public String toString() {
+ return "LicenseType{" +
+ "display='" + display + '\'' +
+ '}';
+ }
+
+ /**
+ * Expected license file suffix for a given license type.
+ */
+ public String licenseFileSuffix() {
+ return "-LICENSE-" + this.name() + ".txt";
+ }
+
+ /**
+ * Expected notice file suffix for a given license type.
+ */
+ public String noticeFileSuffix() {
+ return "-NOTICE.txt";
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d541e180/lucene/build.gradle
----------------------------------------------------------------------
diff --git a/lucene/build.gradle b/lucene/build.gradle
index e69de29..d772627 100644
--- a/lucene/build.gradle
+++ b/lucene/build.gradle
@@ -0,0 +1,8 @@
+import org.apache.lucene.gradle.LicenseCheckTask
+
+subprojects {
+ group = 'org.apache.lucene'
+}
+
+tasks.create("checkLicenses", LicenseCheckTask, new File(projectDir.getAbsolutePath()
+ + System.properties['file.separator'] + "licenses"))
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d541e180/lucene/licenses/asm-tree-5.1.jar.sha1
----------------------------------------------------------------------
diff --git a/lucene/licenses/asm-tree-5.1.jar.sha1 b/lucene/licenses/asm-tree-5.1.jar.sha1
new file mode 100644
index 0000000..60d1311
--- /dev/null
+++ b/lucene/licenses/asm-tree-5.1.jar.sha1
@@ -0,0 +1 @@
+87b38c12a0ea645791ead9d3e74ae5268d1d6c34
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d541e180/lucene/licenses/commons-codec-1.9.jar.sha1
----------------------------------------------------------------------
diff --git a/lucene/licenses/commons-codec-1.9.jar.sha1 b/lucene/licenses/commons-codec-1.9.jar.sha1
new file mode 100644
index 0000000..5a14ad7
--- /dev/null
+++ b/lucene/licenses/commons-codec-1.9.jar.sha1
@@ -0,0 +1 @@
+9ce04e34240f674bc72680f8b843b1457383161a
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d541e180/lucene/licenses/commons-logging-1.1.3.jar.sha1
----------------------------------------------------------------------
diff --git a/lucene/licenses/commons-logging-1.1.3.jar.sha1 b/lucene/licenses/commons-logging-1.1.3.jar.sha1
deleted file mode 100644
index c8756c4..0000000
--- a/lucene/licenses/commons-logging-1.1.3.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-f6f66e966c70a83ffbdb6f17a0919eaf7c8aca7f
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d541e180/lucene/licenses/commons-logging-1.2.jar.sha1
----------------------------------------------------------------------
diff --git a/lucene/licenses/commons-logging-1.2.jar.sha1 b/lucene/licenses/commons-logging-1.2.jar.sha1
new file mode 100644
index 0000000..c314688
--- /dev/null
+++ b/lucene/licenses/commons-logging-1.2.jar.sha1
@@ -0,0 +1 @@
+4bfc12adfe4842bf07b657f0369c4cb522955686
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d541e180/lucene/licenses/hamcrest-core-1.1.jar.sha1
----------------------------------------------------------------------
diff --git a/lucene/licenses/hamcrest-core-1.1.jar.sha1 b/lucene/licenses/hamcrest-core-1.1.jar.sha1
new file mode 100644
index 0000000..6d004b6
--- /dev/null
+++ b/lucene/licenses/hamcrest-core-1.1.jar.sha1
@@ -0,0 +1 @@
+860340562250678d1a344907ac75754e259cdb14
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d541e180/lucene/licenses/hamcrest-core-LICENSE-BSD.txt
----------------------------------------------------------------------
diff --git a/lucene/licenses/hamcrest-core-LICENSE-BSD.txt b/lucene/licenses/hamcrest-core-LICENSE-BSD.txt
new file mode 100644
index 0000000..0bf6264
--- /dev/null
+++ b/lucene/licenses/hamcrest-core-LICENSE-BSD.txt
@@ -0,0 +1,27 @@
+BSD License
+
+Copyright (c) 2000-2015 www.hamcrest.org
+All rights reserved.
+
+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.
+
+Neither the name of Hamcrest nor the names of its contributors may be used to endorse
+or promote products derived from this software without specific prior written
+permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGE.
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d541e180/lucene/licenses/hamcrest-core-NOTICE.txt
----------------------------------------------------------------------
diff --git a/lucene/licenses/hamcrest-core-NOTICE.txt b/lucene/licenses/hamcrest-core-NOTICE.txt
new file mode 100644
index 0000000..e69de29
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d541e180/lucene/licenses/jetty-security-9.4.11.v20180605.jar.sha1
----------------------------------------------------------------------
diff --git a/lucene/licenses/jetty-security-9.4.11.v20180605.jar.sha1 b/lucene/licenses/jetty-security-9.4.11.v20180605.jar.sha1
new file mode 100644
index 0000000..8d8caad
--- /dev/null
+++ b/lucene/licenses/jetty-security-9.4.11.v20180605.jar.sha1
@@ -0,0 +1 @@
+926def86d31ee07ca4b4658833dc6ee6918b8e86
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d541e180/lucene/replicator/ivy.xml
----------------------------------------------------------------------
diff --git a/lucene/replicator/ivy.xml b/lucene/replicator/ivy.xml
index 24b053c..7732d44 100644
--- a/lucene/replicator/ivy.xml
+++ b/lucene/replicator/ivy.xml
@@ -39,8 +39,6 @@
<dependency org="org.eclipse.jetty" name="jetty-continuation" rev="${/org.eclipse.jetty/jetty-continuation}" conf="jetty"/>
<dependency org="org.eclipse.jetty" name="jetty-http" rev="${/org.eclipse.jetty/jetty-http}" conf="jetty"/>
- <dependency org="commons-logging" name="commons-logging" rev="${/commons-logging/commons-logging}" conf="logging"/>
-
<exclude org="*" ext="*" matcher="regexp" type="${ivy.exclude.types}"/>
</dependencies>
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d541e180/solr/build.gradle
----------------------------------------------------------------------
diff --git a/solr/build.gradle b/solr/build.gradle
new file mode 100644
index 0000000..38c0584
--- /dev/null
+++ b/solr/build.gradle
@@ -0,0 +1,8 @@
+import org.apache.lucene.gradle.LicenseCheckTask
+
+subprojects {
+ group = 'org.apache.solr'
+}
+
+tasks.create("checkLicenses", LicenseCheckTask, new File(projectDir.getAbsolutePath()
+ + System.properties['file.separator'] + "licenses"))
\ No newline at end of file